Iteration 3 · one connected app · 2026-09-08

Recipe Journey Prototype

One app, one state object, four views, two live viewports. Pick a style, edit the prompt, save a version, reload the page, and everything you made is still there. Both frames below are the same running app — change something in one and the other follows.

Try the thing that failed last time. Open the infographic recipe, pick a style, press Make my version, then + Add your own wording and type a sentence with a blank line in it. Switch style, copy, save a version, reload the page. Nothing you typed should move. Reset prototype clears it and starts over.
01

What was verified, and how

Not by review. By execution, in a real browser, against this build.

LayerCheckResult
Document modelserialize(parse(t)) === t for any input, plus a 400-case fuzz inserting text at every offset33/33
JourneyStyle carries recipe → customize; free text with a paragraph break survives editing, style switch, copy, save, reload; version recovered byte-intact; phone shares state and does not scroll sideways29/29
StaticSelector prefixing, image tokens, no external resources, core pasted verbatimclean
Why the lost sentence cannot recur. The old build parsed the prompt into known fields and rebuilt it from a template, so anything outside those fields had nowhere to live. The document model now assigns every line to exactly one block and serialises by concatenation, so there is no code path that can drop text. Free text you add is its own editable block. The same model handles a three-sentence prompt as one block and the infographic as nine fields plus whatever you add.
Corrections carried from your review. Two example states, not three — the "no example can exist" treatment is gone, and the filter hides both recipes that lack one. No file picker; the tool boundary is one line beside Copy prompt. Save and Save as new version coexist. The boat card keeps the anchor in frame, and the recipe page shows the fuller crop. The photo recipe asks for an AI tool that accepts a reference image.
02

The prototype

Both frames are live and share one state. Desktop first, phone below.

Desktop
Preparing the prototype…
Phone · 390
Preparing the prototype…
03

Known and not fixed

Five testers found 24 problems. The 12 blocking and major ones were fixed and re-verified. These 10 were left, and they are listed rather than buried.

AreaWhat is still wrong
A choice made once is The version-name input gets no scheduleSelfRender companion at all — onInput's textarea branch schedules one, the input branch returns early — so the name field depends entirely on nothing else calling render() while you type. It survives today only because ui.nameVal is updated on every keystroke, so a redraw re-emits what you typed; the caret and focus are still lost when one lands.
Nothing the user writeClicking "+ Add your own wording" and typing nothing leaves an empty block that adds a blank line to the top of every copied prompt, and its own "Remove" button does not remove it — two clicks leave the copied prompt starting with two blank lines
Two complete journeysThe Mine view has two Copy prompt buttons per journey (saved-recipe row and version row) and neither carries the tool line, so a returning r2 user copies the prompt with nothing saying to attach the photo in the AI tool — the return journey is exactly where copying happens.
Two complete journeysOne keystroke into r1's or r2's recipe paragraph relabels it from "Recipe wording" to "Your own wording" and exposes a Remove control on it; confirming Remove empties the entire prompt (blocks: 0, serialized text: ""), leaving only an "+ Add your own wording" gap. It is warned and Restore original recovers it, but the relabel contradicts the stated reason for having "Recipe wording" at all.
The phone frame is a rPhone rows are less dense than desktop, not more: a version row measures 140.8px tall on the phone against 108.8px on desktop, because the phone rule pushes the actions onto their own line.
The phone frame is a rThe widest toast is truncated on the phone: the message span needs 343px and is given 208px, so 'Retro-Comic Action Blueprint applied · 9 fields you edited kept' renders as an ellipsised fragment while the 'Replace those too' button — which discards those 9 edits — stays fully legible at 112.8px. The phone user sees the destructive option clearly and the reassurance not at all.
The phone frame is a rThe editor and version-name inputs use 12.5px and 13.5px type, below the 16px threshold at which iOS Safari zooms the page on focus; that zoom re-introduces exactly the sideways panning the spec forbids as soon as the touch keyboard opens. I could not execute this — headless Firefox on Linux does not implement iOS focus zoom — so this is traced from the CSS, not measured.
The phone frame is a rThe 600ms self-render destroys and rebuilds the textarea the user is typing in — measured `sameNode=false` and `document.contains(oldNode)===false` after the timer fires — then re-focuses the replacement programmatically. Value and caret survive in Firefox (verified), but a programmatic focus() outside a user gesture does not reopen the software keyboard on iOS, so a phone user can lose the keyboard mid-sentence. Not executable in this environment.
Honesty and explanatioThe "Recipe wording" label flips to "Your own wording" after one keystroke, because RC.isUserFree is a whole-block identity test — contradicting the builder's stated deviation that the app never claims the user wrote something they did not — and the same condition exposes a Remove button that deletes the recipe's own prompt text.
Honesty and explanatioWith localStorage.setItem throwing (quota exceeded, blocked site data), core.js's save() swallows the error and the app still announces "Version saved · it is in Mine" and "Saved recipe · it is in Mine"; the claim holds for the session but the state is gone on reload.
Two of these are honesty problems, not polish. Deleting a free block still reports "0 changes" although text is gone, and if the browser refuses to store data the app still says the version was saved. Both tell the user something untrue about their own work, which puts them above the cosmetic items whatever their label says.
04

What this still does not answer

Nobody has used it. Every assertion above is a machine driving the app the way I predicted a person would, which is not the same as watching someone try. The next step is the one you named: put it in front of a few people, ask them to find something, change one detail, leave, come back, and copy what they made. The success criterion is already concrete and already met by the machine — what is untested is whether a person finds the path without being shown it.

Two known thin spots for that session. The phone controls are small — several touch targets sit around 20px, which is below what a thumb reliably hits, and the editor's 12.5px type will make iOS zoom on focus. And the anime recipe is complete as a journey but has no example image, so it tests the empty state as much as the flow.