# Logic prototype

One self-contained HTML file that lets anyone drive a state model by clicking buttons. Use it when
the question is about **business logic, state transitions, or data shape**: the kind of thing that
reads fine on paper and only feels wrong once real cases run through it.

Because it is one file with nothing to install, it can go to a non-developer, a project manager, or a
domain expert, and let them feel the model themselves. So it speaks their language, not the code's.

Where the question is what something should look like, this is the wrong branch. Use [UI.md](UI.md).

## 1. State the question

Before any code, write down the model and the question, one paragraph, **visible at the top of the
demo** rather than buried in a comment. A logic prototype that answers the wrong question is pure
waste, and the visible statement is what lets anyone check later that it answered the right one.

## 2. Isolate the logic in a liftable module

Put the logic answering the question in a single `<script>` block, written as a small pure module
that could be lifted out and dropped into the real codebase. The page around it is throwaway; **this
module is not.**

Pick the shape that fits the question, not the one easiest to wire to a page:

| Shape | Fits when |
|---|---|
| A pure reducer, `(state, action) => state` | Actions are discrete events and state is one value |
| An explicit state machine | "Which actions are even legal right now" is part of the question |
| A set of pure functions over a plain type | There is no implicit current state, just transformations |
| A module with a clear method surface | The logic genuinely owns ongoing internal state |

Keep it pure: no DOM, no `document`, no handlers reaching inside it. The page calls in; nothing flows
back out. That purity is what makes the prototype useful past its own lifetime, because once the
question is answered the validated module lifts straight into the real code.

## 3. Build the file

One file, plain HTML, CSS, and JS. No framework, no bundler, no server, everything inline, so it
opens on a double-click and survives being emailed around.

Write it for a non-developer. Every label is in **domain language**: buttons and state read like the
business, not like the reducer.

Lay it out top to bottom:

1. **Title and the question** from step 1, in one line of plain English.
2. **Current state**, as a readable labelled panel rather than a JSON dump, re-rendered after every
   click. Call out what just changed where that helps someone follow.
3. **Free-play buttons**, one per action, always available, so anyone can poke at the model in any
   order.
4. **Guided walkthroughs**, one scenario per tab. Each tab carries a short plain-language description
   of the situation and what to watch for, then the ordered buttons to press. Each step is a real
   button: clicking performs the action and advances. Starting a walkthrough resets to a known
   initial state so it runs the same way every time.

Choose scenarios that demonstrate the awkward cases: the happy path, a genuinely tricky edge case,
and an attempt at something that should be illegal.

Keep it beautiful but restrained. Clean typography, generous spacing, one accent colour. No
animations and no gimmicks, since nothing should compete with the state and the buttons.

## 4. Hand it over and stop

Send the file or open it. The interesting moments are *"wait, that shouldn't be possible"* and *"huh,
I assumed X would be different"*. Those are bugs in the **idea**, which is the entire point. New
actions or scenarios on request: prototypes evolve.

## 5. Capture

The validated reducer, machine, or function set lifts into the real module. The HTML shell rides
along to the `prototype/<name>` branch, where being one self-contained file keeps it trivially
re-runnable as a primary source.

## Anti-patterns

- **Tests.** A prototype that needs tests is no longer a prototype.
- **Wiring it to the real database.** In-memory, unless persistence *is* the question.
- **Generalising.** No "what if we wanted to support X later". One question.
- **Blurring the logic into the page.** A module referencing the DOM is no longer liftable, which
  throws away the durable half.
- **Reaching for a framework, bundler, or server.** A React app defeats "one file they double-click".
- **Shipping the HTML shell.** The page is for clicking through by hand. The module behind it is the
  part worth keeping.
