Files
portal/plans/uhhm.yaml
T

182 lines
9.0 KiB
YAML
Raw Normal View History

# UHHM, uhhm.no: the studio that builds portal and carries redoal.
# Rebuilt from the live site (uhhm/questions) on 2026-09-23. The five
# buckets the site already holds keep their live state and event
# names (`events:`), so every record on the owners' desk stays where
# it is. Two are new: a business trying the trainer on its own
# workflow (`trials`, approved by a person before anything is built),
# and what reaches UHHM as the custodian of the redoal network
# (`custody_requests`, a desk of its own).
business: UHHM
language: en
contact: { name: Bendik Aagaard Lynghaug, email: bl@uhhm.no }
about: >
UHHM builds software around a clear argument: infrastructure, tools
and products for organizations that can say what problem they have.
It also builds and carries the redoal network - the gesture math,
the relay, the first node, and the portal this site runs on - and
answers for what that network keeps.
groups:
- { id: owners, label: Owners }
# The people who answer for the redoal network: they host its first
# node and relay, keep what is left there, and decide what stays.
- { id: custodians, label: redoal custodians, invited_by: [owners] }
# Owners onboard into every desk; a custodian can vouch for another.
invites_by: [owners]
doors:
- id: build
who: an organization with a problem software should solve, or a business that wants to see its own workflow as a working site before paying anyone
- id: join
who: someone who wants to build with us, hear from us now and then, or change this site
needs:
- id: commission
who: an organization with a problem it wants software to solve
wants: a considered reply to a brief, from people who read the whole thing
door: build
lands_in: projects
handled_by: owners
stages: [open, accepted, declined]
done_when: [accepted, declined]
success: [accepted]
events: { open: submitted }
max_fields: 4
collects:
- { name: name }
- { name: email, type: email }
- { name: project, type: textarea }
- { name: organization }
- { name: org_contact, optional: true }
# The client feature: the trainer tried on a real business. A person
# approves each intake before anything is built from it.
- id: trial
who: someone who runs a business where requests, approvals and handovers get lost, and wants to see it as a site before committing to anything
wants: a first draft of a site for their own roles, built from their own words and approved by a person first
door: build
lands_in: trials
handled_by: owners
stages: [open, approved, previewed, declined]
done_when: [previewed, declined]
success: [previewed]
attended_by: >
approved -> previewed: the n8n workflow that builds the draft
site from an approved intake (docker, rauthy, portal content)
and sends the preview link. Until it exists, owners run
portal-trainer by hand and press the button.
max_fields: 6
collects:
- { name: business }
- { name: email, type: email }
- { name: what_we_do, type: textarea }
- { name: who_comes_to_us, type: textarea }
- { name: what_we_keep_track_of, type: textarea }
- { name: who_is_involved, type: textarea }
- { name: what_slows_us_down, type: textarea, optional: true }
- id: collaborate
who: someone who wants to work with us on what we build
wants: to be read as a person, and invited in if there is a fit
door: join
lands_in: applicants
handled_by: owners
stages: [open, invited, active, departed, declined]
done_when: [departed, declined]
success: [departed]
events: { open: applied, active: onboarded }
max_fields: 3
collects:
- { name: name }
- { name: email, type: email }
- { name: interest, type: textarea }
- { name: note, type: textarea, optional: true }
- id: subscribe
who: someone who wants to hear from us when there is something to say
wants: a note now and then, and an easy way out
door: join
lands_in: subscribers
handled_by: owners
stages: [open, unsubscribed]
done_when: [unsubscribed]
events: { open: subscribed }
moves_by: { unsubscribed: [submitter, owners] }
max_fields: 2
collects:
- { name: name }
- { name: email, type: email }
# This site proposes its own changes through itself.
- id: propose
who: a visitor who sees how a page on this site should change
wants: the change read by a person and, if approved, made
door: join
lands_in: development_proposals
handled_by: owners
stages: [open, approved, rejected]
done_when: [approved, rejected]
success: [approved]
events: { open: proposed }
max_fields: 3
collects:
- { name: submitted_by }
- { name: email, type: email, optional: true }
- { name: page, optional: true }
- { name: rationale, type: textarea }
- { name: proposed_yaml, type: textarea }
# The custodian role, on the front door: UHHM answers for the redoal
# network it hosts. Owners see these too, and move nothing.
- id: custody
who: someone who runs, builds on, or is affected by the redoal network and needs the people who keep its first node
wants: an answer from a custodian, and action where the network keeps something it should not
lands_in: custody_requests
handled_by: custodians
watched_by: [owners]
stages: [open, in_dialogue, resolved, declined]
done_when: [resolved, declined]
success: [resolved]
max_fields: 4
collects:
- { name: name }
- { name: email, type: email }
- { name: about, type: select, options: [Running a node of my own, Building on the network, Something the network keeps about me, Something else] }
- { name: what, type: textarea }
# Internal: a relationship worth tracking before it is a project.
- id: prospect
who: an owner who has met an organization worth following up
wants: it written down and walked through its states from the desk
enters_as: owners
lands_in: organizations
handled_by: owners
stages: [prospect, client, past_client]
done_when: [past_client]
skippable: [client]
events: { prospect: identified, client: became_client, past_client: churned }
max_fields: 2
collects:
- { name: name }
- { name: contact }
- { name: note, type: textarea, optional: true }
# Held out from every model that writes words. The first eight are the
# 2026-09-21 set (runs/uhhm-2026-09-21); the rest are for what is new.
personas:
- { id: architecture-firm, need: commission, text: "We run a small architecture firm and our project files are scattered across three cloud drives. We want to pay someone to set up proper storage and backups we control ourselves." }
- { id: climbing-gym-founder, need: commission, text: "I have an idea for a booking app for climbing gyms and I'm looking for a team that can build the first version with me." }
- { id: municipality-buyer, need: commission, text: "Our municipality needs an internal tool for tracking building permits. We are looking for a vendor who can scope it and deliver it." }
- { id: exhibition-visitor, need: subscribe, text: "I saw your drawing network at an exhibition and liked it. I don't want to get involved, I'd just like to know when there is news." }
- { id: tech-journalist, need: subscribe, text: "I write about Nordic technology. Keep me posted on what you release so I can cover it." }
- { id: rust-developer, need: collaborate, text: "I'm a Rust developer between jobs and I like that you build in the open. I would love to contribute, and maybe join you." }
- { id: interaction-designer, need: collaborate, text: "I'm an interaction designer. I want to work with you on the drawing interface." }
- { id: student-intern, need: collaborate, text: "I'm a computer science student looking for a summer internship doing infrastructure work." }
- { id: plumber-owner, need: trial, text: "I run a plumbing company with four vans. Jobs come in by phone and text and some get lost. I'd like to see how this would look for us before I spend any money." }
- { id: dance-school, need: trial, text: "We are a dance school. Enrolments, cancellations and invoices all go through one email inbox that only I understand. Can you show me a version made for us?" }
- { id: node-runner, need: custody, text: "I run a small server in Berlin and want to host a redoal node that peers with yours. Who do I talk to?" }
- { id: recorded-name, need: custody, text: "Someone left a recording on redoal that says my full name and where I live. I want it gone, and I want to know who is responsible for that network." }
- { id: app-builder, need: custody, text: "I'm building a music app and would like to use redoal's gesture addresses in it. Is that possible, and who decides?" }
- { id: wording-fix, need: propose, text: "The subscribe page should say how often you actually write. I'd like to suggest that exact change to the page." }
- { id: rewrite, need: propose, text: "One page on this site reads wrong to me and I know exactly how I'd rewrite it. Where do I send the new text?" }