User journey · verified · create → update → publish

The Creative Loop

A user has an idea. How do they turn it into a published page — and what are all the ways they can mess with it in between?

Last verified 2026-04-18 against code
Slug creative-loop
Creation entry points 1 real · 7 loads
Update mechanisms 20

§1 The editor surface

The whole editor is a single page. Three tabs on the left drive everything on the right.

https://fuzzycode.dev/
Create
Update
Save / Load / Share
Sample prompt
<sample-dropdown> ▾
Prompt
Fuzzy Code It!
(only real entry point)
Userparent@…
Tools🎮🧩</>📋📸
Version📜v5 ▾diff

Left: three tabs. Right: toolbar + live preview iframe. Evidence: FuzzyCode/templates/index.html:207-535.

§2 Creation entry points — one real, seven loads

Despite appearances, there is only one in-editor "create" affordance: the "Fuzzy Code It!" button. Everything else loads existing HTML from somewhere.

flowchart LR classDef real fill:#fff460,stroke:#683c06,color:#111,stroke-width:2px classDef load fill:#eaf3ff,stroke:#1d58b1,color:#111 classDef auto fill:#f1eee7,stroke:#6b6455,color:#333 classDef target fill:#edd9c0,stroke:#683c06,color:#111 R[Fuzzy Code It!
Create tab button
POST /prompt_to_code]:::real L1[Paste clipboard
HTML or URL]:::load L2[URL params
?fromURL= / ?create_prompt=
/ ?action_prompt=]:::load L3[Load from Pages
/api/pages/import/<hash>]:::load L4[Local History
from IndexedDB
/local_recent_history]:::load L5[Tab-state restore
on refresh]:::auto L6[Level Editor
postMessage apply
existing project only]:::auto S1[Sample dropdown
fills textarea, doesn't submit]:::load R --> V[(projectVersionHistory
currentProjectId)]:::target L1 --> V L2 --> V L3 --> V L4 --> V L5 --> V L6 --> V S1 -.-> R V --> I[#responseIframe
live preview]:::target
No "New Project" button. Starting a second project from the same session requires pasting or loading, or you'll hit a confirmActionMode(..., "CREATE") dialog because typing a create-style prompt in an existing project is detected as an intent mismatch (script.js:1874-1876).

§3 Once a project exists — 20 ways to update

The #responseIframe is a reflection of projectVersionHistory[projectId][currentVersion]. You can't edit it directly. Every change flows through saveVersion(), which creates a new version entry.

5 Swipe button directions

  • center — make change (default)
  • up — fast change
  • down — super fast change
  • left — custom actionType
  • right — major / meticulous (SweetAlert confirm on large projects)

3 AI Suggest engine

  • Fixes tab — automated problem detection
  • Improve tab — quality suggestions
  • Features tab — new-feature suggestions
  • Cards are pre-cached per category; clicking one fires /suggest_actions/apply_action

5 Fix-error swipe (auto-show on iframe error)

  • fast, hard, custom, investigate, default variants
  • Separate error container with prev/next error nav
  • Fires /apply_action[_fast] with error context

1 Touchpad Fast Change

  • Tools Island button #touchpadFastChangeBtn
  • Server-supplied prompt + agent BIG_FAST_REASONER
  • Bypasses the large-project confirm dialog

1 Direct HTML edit

  • #editorButton → popup code editor
  • PII cleanliness check via /api/html/verify-cleanliness before save
  • Can fail silently if the caller doesn't handle the error

1 Level Editor

  • Gamepad icon opens /level_editor in popup
  • postMessage applyLevelChanges creates version with lastAction level_editor_apply

1 Metadata editor

  • Puzzle icon #openMetadataBtn/metadata_page
  • Saves as update_metadata version
  • SweetAlert2 "save/discard" on unsaved close

1 Paste over current

  • Tools Island #pasteCodeBtn
  • No AI — saves clipboard as new version directly
  • If no project yet: paste_as_new_project

3 Navigation (no new version)

  • Prev / Next — swap currentVersion
  • Version dropdown — jump to any
  • Refresh iframe / Diff / Fullscreen
  • ⚠ editing an older version → silent branch (see §6)

1 Screenshot attach (next-request context)

  • Tools Island camera / Save tab screenshot
  • Opens modal with #sendWithNextRequest checkbox
  • Sent only on the NEXT AI request if checked

4 Project / context settings

  • Project name + #refreshProjectNameBtn
  • Visibility toggle (legacy + publishVisibilitySelect)
  • AI model dropdown (60+ entries for admins)
  • Ask modal (admin-only streaming SSE)

§4 The swipe button — up/down/left/right/center

Five distinct actions behind one UI element. Hidden affordance — new users rarely discover all five.

▲ Up
Fast change
/apply_action_fast
◀ Left
Custom
/apply_action w/ actionType
● Center
Make change
default
auto-fast if large
▶ Right
Major / meticulous
SweetAlert confirm
▼ Down
Super fast
size-routed

§5 The typical creative loop

sequenceDiagram autonumber participant U as 👤 User participant E as Editor
(script.js) participant AI as Quart
core_ai.py participant IF as Iframe
preview participant T as Redis
/temp_page participant P as Pages
service Note over U,E: CREATE U->>E: types prompt, clicks "Fuzzy Code It!" E->>AI: POST /prompt_to_code AI-->>E: { html, description } E->>E: saveVersion('send', html) E->>IF: render v1 E->>T: POST /temp_page (preview URL) IF-->>U: sees rendered page Note over U,E: ITERATE (20 ways, mostly swipe button) loop several iterations U->>E: swipe center / left / right / tap a suggestion E->>AI: POST /apply_action[_fast] AI-->>E: { html, description } E->>E: saveVersion('apply_action_*', html) E->>IF: render vN+1 end Note over U,E: FIX ERRORS (if child iframe reports) opt on iframe error IF-->>E: ugc_asset_progress_child.js error event E->>U: show error-swipe button U->>E: Fix Error swipe E->>AI: POST /apply_action with error context AI-->>E: { html } E->>E: saveVersion('error_fix', html) end Note over U,E: PUBLISH U->>E: set name, visibility, press Publish E->>E: ensureHtmlCleanBeforeVersionSave (PII) E->>E: POST /api/pages/attest-publish (HMAC) E->>P: POST fuzzycode.dev/@pages/submit P-->>E: 200 { url } · or 202 pending · or 409 duplicate warning E-->>U: showPublishOutcomeModal

§6 Version history is a tree, UI is a dropdown

The version dropdown looks like a linear list. It is not — it's a flat rendering of a branching tree. Jumping to an older version and making a new change creates a new version whose referenceVersion points back to the older one. This is the undo/redo/branch mechanism, and it happens silently.

v1 send← initial create
└─v2 apply_action (fast)← iterated
└─v3 apply_action← iterated again
└─v4 error_fix← fixed an error
└─v5 apply_action⚠ branched — user jumped back to v2 then edited
└─v6 apply_action ← currently selected
Silent branching. The UI shows a flat list v1, v2, v3, v4, v5, v6. It doesn't visualize that v5 branched off v2 instead of continuing from v4. Users who "go back to try something different" create a divergent history without realizing it — and if they navigate back to v4, v5/v6 are still there but disconnected from their current line.

§7 Publish outcomes

One click, three distinct outcome dialogs. Worth knowing because two of them look like failure when they're not.

✓ Success · Private
HTTP 200

URL returned · optional share URL · published_timestamp stamped. User is handed a link to share.

⏳ Pending parent approval
HTTP 202

User selected Public. Row is stored as private with link_status=false and an approval request is opened. "Public" in the UI means "request approval" — stays private until a parent acts.

⚠ Duplicate hash warning
HTTP 409

Response has matching_pages[] instead of url. Modal shows the user their matches and lets them choose update vs duplicate. Silent failure if the modal is dismissed.

§8 What persists — a quick survival note

Full persistence map in its own diagram. Short version:

EventprojectVersionHistory (memory)sessionStorageIndexedDBServer (/temp_page, @pages)
Tab refreshlostrestoredsurvivessurvives
Browser close + reopenlostlostsurvivessurvives
Clear site datalostlostlost/temp_page 30d · pages forever
Different devicen/an/an/a/user_projects (Redis) 30d
Parent → Child context switchcleared per-childclearedper-child key spaceper-child

§9 Gotchas the UX hides

Sample dropdown doesn't submit. Selecting a sample fills the textarea but does not fire the request. Users often expect it to.
"Public" means "request parental approval." Even if visibility is set to Public, the row stores as private and stays non-servable until a parent approves. No client-side banner warns about this.
Large-project confirm dialog blocks center-swipe above a token threshold. Fast, super-fast, touchpad all bypass.
AI generation is NOT streamed (only admin Ask is). Users wait for a spinner until full HTML arrives. A 90-second request returns all at once.
Publish dedupe 409 looks like failure. If the modal's dismissed, the user has no idea the server returned matching pages.
PII check can block a save silently on direct HTML edit unless caller surfaces the error toast.
ServiceWorker is unconditionally unregistered on every load (index.html:46-72). No offline support; Cloudflare is the only cache.
Metadata "edit" is really a second save. Every metadata change creates a new version with lastAction=update_metadata.

§10 Verification pointers