The onboarding is one screen with two doors, and three bridges the server drives - #462
Draft
serenakeyitan wants to merge 11 commits into
Draft
The onboarding is one screen with two doors, and three bridges the server drives#462serenakeyitan wants to merge 11 commits into
serenakeyitan wants to merge 11 commits into
Conversation
…rver drives
Design: tdoc.dev/d/tdoc-onboarding-journey/v/4. The landing page and its CTA
are untouched; the CTA now opens "Create a free doc" — two doors instead of
a recipe. "Use my own agent" (the word carries its definition on hover:
Claude Code · Codex · Claude Cowork · ChatGPT Work) signs the person in, hands
over the one line, and waits. "Use tdoc's agent — coming soon" records a
waitlist and sends them to the example. "See an example" sits beside both.
The waiting is read off the server, not guessed. Every step the agent takes
is already a request: minting a token stamps agent_connected, the first
publish stamps published_first (and seeds one comment, signed tdoc, for a
journey that came through the door), a second version stamps revised, and
tdoc-pull's GET /api/comments — Bearer, or the version=all shape only the CLI
asks for — marks the doc read. The landing page's door polls the record and
leaves for the first doc on its own; the owner's comment card carries the one
instruction in the journey ("Read my tdoc comments and fix them" + Copy) and
flips waiting → reading → ✓ → new version as those requests land. Past five
minutes it asks the one question that resolves it. No daemon, no port, no
doctor state: the only failure mode is "nothing happened", and the fix is
always the same sentence.
A visitor with no session sees a Comment option that says what it will do —
Sign in to comment — instead of a mode picker with Read alone. On a revised
doc the owner gets the exit line, once, until they copy the link.
Every step is a timestamp on the account (account-onboarding:<id>), every
action the page saw is one event row, and resuming reads the first empty
step: a started, unfinished journey reopens its door on the next visit.
The pure helpers are shared with server.js and pinned by no-drift; the
local twin discovers the first doc on read, since it cannot see tdoc-new
write one.
Four static tests pinned the old dialog's shape (its details block, its
hosted-token probe, its identity-less mount); they now pin this one.
Refs tdoc.dev/d/tdoc-onboarding-journey/v/4
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PreviewOpen this: https://pr-462-tdoc-preview.jyshi1107.workers.dev/ — the homepage, this PR's code This link is unique to this PR. New commits update the same URL. It is not tdoc.dev. Preview has no Durable Object — concurrent comments use the KV fallback. Data expires in 14 days. |
… it inline Positioned from the word, the hover tip ran rightwards across the gap and sat on top of the other door, where it read as that door's description. It is anchored to the door now — left and right edges inside the card, under the title — so it can only ever describe the door it belongs to. A phone has no hover, so below 560px (and on any hover-less pointer) the same sentence sits under the title as a plain line, and the dotted underline that promised a hover goes with it. Measured at 375px: nothing overflows the viewport. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ough v2 Two testers walked the onboarding as strangers. The third came in through /me and got the bare recipe line: no wait, no arrival, no seeded comment, no exit, because the Docs Hub's "Build it with your agent" card rendered FirstDocRecipe on its own. It now opens OwnAgentDoor — one door, two entrances — with the definition of "agent" under the card title. The rest is what the two rounds found on the way: - a refused clipboard leaves the line selected and says so, on the door and on the fix line, and the wait starts anyway - the wait says how long it usually takes, nudges at 90s, asks at 5 min - arrival opens the seeded card with a toast; v2 arrival opens the person's own answered thread and shows resolved threads - a reply on the seeded card counts as the first gesture; the fix line shows only on the latest version, only after it - the agent-status carries replied_at, so the card says "Replied ✓" before v2 lands - the exit banner sits in the flow, stays as the confirmation after the link is copied, and does not close the open card - the landing shows "Your doc →"; an existing doc opens from the door instead of a silent jump; the local server shows the old-version strip Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Four things the round-4 stranger left, decided with the owner: - "v1 · current" read as "latest" from an old version. The menu now says "viewing" for where you are and "latest" for the newest, separately. - A person with a doc was handed "make my first doc" again. The door's second line is the ordinary way to make one, with a blank for what it is about; FIRST-DOC.md would only have built the same portrait twice. - A triple-click on a sentence beside an open card only closed the card, and the sentence had to be selected again. A multi-click selection now closes the card and is the next comment; a single click stays a dismissal, so `user-select: all` blocks do not open composers. - The wait had a pulsing dot a screenshot cannot show. A sweep runs under the status while the page is listening; reduced motion gets a still bar. And the card no longer claims "Replied ✓" for a thread the agent has not answered — the status is the doc's, so it says the agent is replying and the next version is on its way. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The agent answers thread by thread and publishes seconds later. A doc-level stamp taken at the first reply lit "Replied ✓" on a thread the agent had not answered yet (round-4 tester), and the true version of the sentence said nothing the next state did not say better. So the card goes waiting → reading → the next version arrives. A reply that comes without a version, a question, shows up in the thread on the next refresh. The replied_at field leaves agent-status on the worker and the local server with it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…s the bridge The two doors and the scattered bridge — a card line here, a banner there, a toast that was gone before the person looked — become one window that stays on the landing page and moves on its own. It asks the server every few seconds what the person's agent has done and steps forward: welcome, sign in, connect, your doc, send back, done. The doc opens in another tab; this window is the guide. Every step is read off the account's onboarding record, so a reload or a second device resumes in place. - Welcome draws the loop instead of describing it: the agent's terminal, the doc in a browser, the doc going one way and the comments back. - Sign-in runs in a small window (a POC of the cheap route: the same OIDC redirect, in a 480×640 pop-up that lands on /auth/done?popup=1, posts `tdoc:signed-in` to its opener and closes). A blocked pop-up falls back to the full-page redirect. Not yet exercised against the live provider. - The code a terminal shows is typed in this window, through the same lookup and approve routes /activate uses, with the terminal named before it is bound. - The hub's "Build it with your agent" card opens the same wizard at the connect step. The old door CSS goes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…e blue
The wizard's buttons were painting white on white: chrome.css's
`.tdoc-modal button` outranked the wizard's own rules, so every primary
was a blank box with a grey border (the owner's screenshots). Every
wizard rule now carries the element, and outranks it.
The rest is the owner's cut: sign-in is the site's own (the page leaves
and returns to the paste step) — the small-window POC goes; the pairing
code gets a step of its own instead of a field under the line; the doc
step is the comment ("Now comment on it." and one button); the Advanced
fold, the notes, the rows on the doc step and "Make another" all go;
every step can be skipped.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The subtitles, the explanations and the long labels go. What is left on each screen is the one thing to do, and a status line while the page waits: "Paste this into your agent." — the line — "Copy". The doc step says what the gesture is, not that there is one: "Highlight a sentence. Say what you think." Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
CodeQL on #462: one pass over `<[^>]+>` can leave a tag behind, and decoding `&` before `<` double-unescapes. The text is an anchor, never markup, but the order is what makes that true. Same body on both hosts, as no-drift requires. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The send-back step inherited the paste step's copy and showed its three rows before Copy was pressed (seen on the local-worker walk-through). The copy state resets on every step change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft — not for merging yet. Design: https://tdoc.dev/d/tdoc-onboarding-journey/v/4. The owner tests it by hand first, and a no-context agent walks the flow and grades it; this merges only when both are satisfied.
What it does
The landing page and its CTA are untouched. Create a free doc now opens one screen with two doors:
?onboard=own), states the one concept once ("Two windows: you read and comment here. Your agent writes and fixes."), hands over the line, and waits.Three bridges, no daemon
The waiting is read off the server. Every step the agent takes is already a request:
issueHostedToken→agent_connected/api/uploadfirst hosted publish →published_first+first_docGET /api/commentswith a Bearer, orversion=all(the shape onlytdoc-pullasks for) →doc-agent-read:<slug>/api/uploadv≥2 →revised;latest_versionon/api/doc/agent-statusBridge 2 is on the owner's comment card: the one instruction in the journey —
Read my tdoc comments and fix them+ Copy — then Waiting for your agent… → Your agent is reading this → ✓ → the new version. Past five minutes: Still waiting — did you paste it into your agent?The first doc of a journey that came through the door arrives with one comment already on it, signed tdoc (not a person): "First reader here. Which claim on this page would you defend least? Highlight it and say so." A CLI-first publisher who never opened the door gets nothing.
Record
account-onboarding:<account_id>—started · agent_connected · published_first · seeded_comment · commented · comments_read · revised · tagged · shared · waitlist · tour_seen, all timestamps, first writer wins.onboarding-event:<id>:<ts>— one row per action the page saw (door_own_agent,waitlist,example_opened,copy_clicked,fix_copy_clicked,timeout_shown,share_link_copied,tour_seen); the funnel is derived from these. Routes:GET /api/onboarding,POST /api/onboarding/event(unknown action → 400; onlywaitlistandexample_openedare open to a visitor with no account),GET /api/doc/agent-status.Resuming reads the record: a started, unfinished journey reopens its door on the next landing visit. Nothing in localStorage.
Also
cfg.signInToComment).tdoc-newwrite one); pure helpers pinned byte-identical byno-drift.Tests
test/onboarding-journey.test.js(11) — the pure helpers run, not grepped; the routes, stamps, doors, bridges, exit and resume pinned. Four static tests that pinned the old dialog's shape now pin this one. Offline suite 78/78. Shell rebuilt;server/runtimecommitted.🤖 Generated with Claude Code