---
title: "Design process"
source: "docs/decisions/ADR-0004-design-process.md"
---

> Part of [botgumi docs](https://botgumi.com/docs/llms.txt). Every page: [llms.txt](https://botgumi.com/llms.txt).

# ADR-0004: The design process

Status: accepted · 2026-10-18

## Context

The human gates name a brand, a design system, lo-fi, hi-fi and a screenshot direction (ADR-0001, decision 15),
and the design worker has a role file. Nothing says what each stage produces, what it needs first, or what
"done" means. `templates/app/design/` is empty.

The first app built this way followed one order and it held up:

- **Wireframes first,** every screen and its states, with the flows between them, then a one-page clickable
  prototype built from the wireframe files. People tapped through it before anything was drawn in colour.
- **Hi-fi on real data.** Every screen in every state (loading, empty, error, offline and the screen's own),
  drawn with numbers and names from example API responses that a check validates against the contract.
  Drawing with real data found contract gaps before any app code existed.
- **One contract per screen.** Each screen lists what it shows and where each value comes from. A small script
  prints one screen's contract, its boards and the app files that build it, so an agent building the screen
  reads one thing.
- **Tokens in one source,** read by the app code. Pictures alone drifted from the code.
- **Store screenshots last,** drawn from approved hi-fi screens.

Where the order slipped (a screen built from a lo-fi board, a value drawn that no endpoint sends), the screen
was built twice.

## Decision

**D1. Five stages, in this order.** Each is produced by the design worker in `design/` and closed by a human
gate. A stage starts only when the stage before it has passed its gate.

| # | Stage | Inputs | Output files | Gate |
|---|---|---|---|---|
| 1 | Brand brief | PRD review (problem, audience, first value) | `design/brand/brief.md` (name, voice, mark, do and don't), `design/brand/mark.svg` (light and dark), 3 to 5 name options with the domain check | Brand and name |
| 2 | Design system | Brand brief | `design/system/options/` (3 to 5 options, each a token set on two sample screens), then for the chosen one `design/system/design-system.md` (type, colour, space, radius, components and their states) and `design/system/tokens.source.json` | Design system choice |
| 3 | Lo-fi | PRD, design system, the draft contract (`docs/api/openapi.yaml`) | `design/lofi/screens.md` (every screen, its states and flows), `design/lofi/wireframes/<ID>.*` (one per screen), a clickable prototype built from the wireframes, linked from `screens.md` | Lo-fi approval |
| 4 | Hi-fi | Lo-fi, tokens, example API responses (`docs/api/examples/`) | `design/hifi/<ID>/screen.md` (contract, a board per state, tokens used), `design/hifi/<ID>/bindings.md` (data-binding map, `docs/templates/data-binding-map.md`), the boards | Hi-fi approval, per screen |
| 5 | Screenshot direction | Approved hi-fi screens | `design/screenshots/direction.md`, 2 or 3 directions for the first 3 screenshots | Screenshot direction |

The templates for each output are in `docs/templates/` (`brand-brief.md`, `design-system.md`, `lofi-screens.md`,
`hifi-screen.md`, `screenshot-direction.md`). The scaffold is `templates/app/design/`.

**D2. The files are the source.** A board may be drawn in any tool or a hosted canvas, but its source or an export
is saved under `design/`, so the design is versioned with the code and an agent can read it. A link alone is not
an output.

**D3. The screen list is the contract of what exists.** `design/lofi/screens.md` names every screen with a stable
ID (`S01`, `S02`, …), its states, its flows and its stage (`lofi`, `hifi` or `approved`, with the gate issue once
approved). Every screen lists at least `loading`, `empty`, `error` and `offline`, plus its own states (`ready`,
`first-run`, `paywall`…). A screen that is not in the list is not built.

**D4. Hi-fi is every screen in every state, on real-looking data.** Each state has a board. Every value on a
board comes from an example API response in `docs/api/examples/` that is valid for its endpoint, from local
state, or from the device; the data-binding map says which, field by field. A value no endpoint sends is a
contract change request first (`agents/orchestrator.md`, step 7), then a board. Every colour,
size and font on a board is a token from `tokens.source.json`, named in the screen's "Tokens used". Every string
on a board has a key and exists in en and zh-Hans; the `ready` board is also drawn in zh-Hans to catch overflow.
The paywall's hi-fi waits for the pricing gate.

**D5. No screen is built before its hi-fi gate.** No screen is built in `ios/` or `android/` until its row in
`design/lofi/screens.md` is `approved` with the gate issue. The orchestrator marks each screen task "blocked by"
that gate issue. Work that draws no screen (models, the API client, providers, navigation shell) may start
after the lo-fi gate.

**D6. Gates.** The orchestrator opens one `gate` issue per stage, with the options or the boards and the
checklist from `docs/checklists/design-gates.md`. Hi-fi may be gated in batches (one issue for a flow); each
screen passes or fails on its own. Only a human approves. The design worker then moves the stage forward in the
files (for hi-fi: the screen's row becomes `approved` with `#<gate issue>`) in its next PR.

**D7. A later design change runs design first.** A change to an approved screen is a design issue, then a new
hi-fi board for the changed states (the row goes back to `hifi`), then its gate, then the app change, blocked by
that gate. A fix that brings the app back to the approved board needs no design issue. A token change is a
design-system change: a design issue, new token values, and the review of every screen that uses them.

**D8. One screenshot direction for both stores.** Drawn from approved hi-fi screens and real-looking data.
The full sets then follow `docs/checklists/app-store-assets.md` and `google-play-assets.md`.

**D9. Design CI.** `node design/check.mjs` runs in the app's CI and fails when: the token source does not match
the shape `@botgumi/design-tokens` reads; a screen in the list lacks one of the four states or a wireframe; a
screen at `hifi` or `approved` lacks its folder, `screen.md`, `bindings.md`, a board for each listed state, or
names a token that is not in the source; an `approved` screen names no gate issue; a hi-fi folder is not in the
list. Once the token generators in `@botgumi/design-tokens` land, the same CI generates the CSS, Swift and
Kotlin outputs and builds them.

This amends ADR-0001, decision 15: the design gates close the stages above, in order.

## Consequences

- An app screen has one place to read before it is built: `design/hifi/<ID>/`, with its contract, boards,
  bindings and tokens. Review checks the code against it.
- App work on screens starts later than it would from lo-fi, and the contract is found incomplete earlier.
- Example API responses become a design input, so `docs/api/examples/` must exist and be validated against
  `docs/api/openapi.yaml` before hi-fi starts. That check belongs to the backend and docs tracks.
- A design change after approval costs a gate. That is the point: code never leads the design.
- `check.mjs` checks structure, not taste. The gates check taste.
- Follow-up: implement the token generators, then add generation to the design CI; a prototype builder that
  stitches `design/lofi/wireframes/` into one page, when the first app needs one.
