handoff — the owner's manual
Stage: Phase 12 — Ship (after ship) - Reads: design/BRIEF.md, DIRECTION.md, SYSTEM.md, SITEMAP.md, QA.md, CONTEXT-HANDOFF.md, package.json, app/ tree - Writes: README.md
Standard
The README lets two people succeed without the original author: the owner changes a headline in under 5 minutes, and the next developer restyles the whole site by editing one token in one file. Every path, command, and version in it is verified against THIS repo this session — a README describing an ideal repo instead of the real one is worse than none. The create-next-app boilerplate README does not survive. No generic Next.js tutorial prose: every sentence is a fact about this site.
Process
- Kill the boilerplate. The string "bootstrapped with" must not survive in README.md.
- Stack map from package.json's real versions (read the file or
npm ls --depth=0) — exact numbers, never "latest". List backend pieces (Drizzle, Better Auth, Resend, Stripe) only if actually built. A DIRECTION-gated dependency gets a WHY on its line, not just a version: animejs reads "drives the " (+~19 KB gz, per STACK.md), so the day that moment is cut the maintainer can see the package leaves with it. A dependency whose reason isn't written down never gets removed.
- Run section:
npm install, npm run dev, npm run build && npm run start, plus env bootstrap — copy .env.example → .env.local and fill it; the per-key comments ship wrote say where each value comes from.
- Content map. For every page in design/SITEMAP.md, one table row: what the owner sees → the file that owns that string. Build it by opening the actual components — not from memory of what Phase 6 built.
- Token guide — the one-file promise. All styling flows from the
:root/.dark/@theme tokens in app/globals.css. Give 3 worked one-line recipes (accent color, radius, font swap). State the law: change the token or add a variant — never hardcode a value inside a component.
- design/ folder explained, one line per artifact: BRIEF (what and who for), DIRECTION (the aesthetic contract and its banned moves), SYSTEM (palette/type/motion rationale), SITEMAP (per-page blueprints), QA (gate history), CONTEXT-HANDOFF (the lessons the build sessions banked). Frame it as the site's memory — future changes start by reading these. Name
qa/ at the project root in the same breath and dispose of it: the build, prod, and gate logs there are evidence for one run, regenerated by the next, and nothing in design/ depends on them — design/ is the record, qa/ is the receipt.
- Gate re-run instructions:
npm run build (code gate), npx eslint . (next lint is removed in Next 16), and: with the ultraweb plugin installed, request changes via ultraweb:iterate — it re-runs only the affected gates and appends to design/QA.md.
- Deploy record (only if shipped): live URL, host, redeploy command, env keys the host needs — copied from ship's QA.md entry.
- Maintenance notes: the load-bearing decisions and how not to break them (see skeleton) — and fold every §Lessons block from
design/CONTEXT-HANDOFF.md into that list, one line each, deduplicated against the standing bullets and against each other. A lesson cost this build real debugging time; leaving it in a file the next maintainer never opens makes them pay for it twice.
- Verify before done: every file path named in the README exists (check each one), every command exits 0 — build already proven by ship; cite its QA.md line instead of re-running.
README skeleton
# <Site name>
<one sentence: what this site is and who it serves — from design/BRIEF.md>
## Stack
Next.js <16.x.y> (App Router, Turbopack) · Tailwind CSS <4.x> (CSS-first — all
tokens in app/globals.css; there is no tailwind.config.js) · shadcn/ui (restyled
primitives) · motion <13.x> (import from "motion/react") · lucide-react · zod v4
<+ animejs <4.x> ONLY if installed — with the DIRECTION moment it drives named on
the same line; cut that moment and this package goes with it>
<+ backend pieces actually built>
## Run it
npm install → npm run dev → localhost:3000. Production check: npm run build && npm run start.
Copy .env.example to .env.local and fill it — each key's comment says where it comes from.
## Edit content & copy
| You want to change… | Edit this file |
|---|---|
| Homepage headline | components/sections/hero.tsx |
| <one row per user-visible surface, real paths> | |
## Change the look — one file
Everything visual flows from tokens in app/globals.css:
- Accent color: edit --accent in :root AND .dark (both — dark mode is designed, not inverted)
- Corner rounding: the --radius-* tokens under @theme
- Fonts: swap the instance in lib/fonts.ts; the --font-* token name stays
Never hardcode a color or size in a component — change the token or add a variant.
## The design/ folder
BRIEF · DIRECTION · SYSTEM · SITEMAP · QA · CONTEXT-HANDOFF — <one line each>.
Read DIRECTION.md before any visual change: it names what this site will NOT do.
The qa/ folder at the project root is logs from the last gate run — disposable, safe to delete.
## Quality gates
npm run build must exit clean. Lint: npx eslint . (the next lint command no longer
exists). With the ultraweb plugin: make changes via ultraweb:iterate — it re-runs
the affected gates and logs results to design/QA.md.
## Deployed
<live URL> on <host>. Redeploy: <command>. Env keys the host needs: <list>.
## Don't break these
- One accent color. Wanting a second is a DIRECTION.md conversation, not a CSS edit.
- Dark mode is re-decided per surface — check both themes after any color change.
- prefers-reduced-motion paths must keep working; test with motion disabled.
- <if app/(studio)/ exists: the dev-only /studio dashboard. Deletable — one route group,
one folder, zero cleanup; nothing else imports it and it 404s in production anyway.>
- <one line per design/CONTEXT-HANDOFF.md §Lessons entry, deduplicated — the traps this
build already fell into, so the next change doesn't rediscover them>
- <demo builds only: list every UNVERIFIED-PROOF sample quote and its file — each
must be replaced with real proof before production; ship blocks on the tag>
Error monitoring — optional, and configured defensively
Only worth a section when the owner will actually watch it; an unwatched SDK is weight and a data liability, and the honest answer for most brochure sites is none. If it goes in, Sentry is the default — and for a DACH audience its defaults are wrong out of the box. Turn sendDefaultPii off, leave Session Replay off (it records the DOM, so it is personal-data processing that needs a legal basis and its own ultraweb:consent category — never a silent default), set the EU ingest region so nothing leaves the EEA, and keep tracesSampleRate low enough that the free tier holds. The README states which of those are on, where the DSN lives, and who holds the login; a monitoring account nobody owns outlives the site.
Anti-patterns
- "This is a [Next.js] project bootstrapped with create-next-app" — boilerplate survived
tailwind.config.js mentioned anywhere — v4 is CSS-first; the token story lives in globals.css
next lint in gate instructions — removed in Next 16; the ESLint CLI is the command
npx shadcn-ui in maintenance docs — dead package; it is npx shadcn@latest
- A content-map row pointing at a path that doesn't exist — step 10 exists to kill this
- Versions written as "latest" instead of package.json's pinned reality
- Generic framework tutorial prose ("Learn more about Next.js…") instead of facts about THIS site
Worked example — Aldermoor Trust, README for a volunteer-run site
Moved to references/example.md — read only when this build's case is genuinely ambiguous; the sections above are the decision material.
Composes with
Moved to references/composes.md — the handoff map; load it when orchestrating this skill against its neighbors.
1---2name: handoff3description: Write the closing README for a finished ultraweb site — stack map with the real installed versions, run/build commands, a verified file-by-file content-and-copy editing map, the one-file token guide (app/globals.css @theme), one-line explanations of every design/* artifact, gate re-run instructions, deploy record, and maintenance notes on what not to break. Invoke in Phase 12 of the ultraweb pipeline after ship, or whenever the user asks for docs, a README, a handoff, onboarding notes for another developer, or "how do I edit this myself later". Every path and command in the README is verified against the actual repo, never described from memory.4---56# handoff — the owner's manual78**Stage:** Phase 12 — Ship (after ship) - **Reads:** design/BRIEF.md, DIRECTION.md, SYSTEM.md, SITEMAP.md, QA.md, CONTEXT-HANDOFF.md, package.json, app/ tree - **Writes:** README.md910## Standard1112The README lets two people succeed without the original author: the owner changes a headline in under 5 minutes, and the next developer restyles the whole site by editing one token in one file. Every path, command, and version in it is verified against THIS repo this session — a README describing an ideal repo instead of the real one is worse than none. The create-next-app boilerplate README does not survive. No generic Next.js tutorial prose: every sentence is a fact about this site.1314## Process15161. **Kill the boilerplate.** The string "bootstrapped with" must not survive in README.md.172. **Stack map** from package.json's real versions (read the file or `npm ls --depth=0`) — exact numbers, never "latest". List backend pieces (Drizzle, Better Auth, Resend, Stripe) only if actually built. A DIRECTION-gated dependency gets a WHY on its line, not just a version: `animejs` reads "drives the <named DIRECTION moment>" (+~19 KB gz, per STACK.md), so the day that moment is cut the maintainer can see the package leaves with it. A dependency whose reason isn't written down never gets removed.183. **Run section:** `npm install`, `npm run dev`, `npm run build && npm run start`, plus env bootstrap — copy .env.example → .env.local and fill it; the per-key comments ship wrote say where each value comes from.194. **Content map.** For every page in design/SITEMAP.md, one table row: what the owner sees → the file that owns that string. Build it by opening the actual components — not from memory of what Phase 6 built.205. **Token guide — the one-file promise.** All styling flows from the `:root`/`.dark`/`@theme` tokens in app/globals.css. Give 3 worked one-line recipes (accent color, radius, font swap). State the law: change the token or add a variant — never hardcode a value inside a component.216. **design/ folder explained**, one line per artifact: BRIEF (what and who for), DIRECTION (the aesthetic contract and its banned moves), SYSTEM (palette/type/motion rationale), SITEMAP (per-page blueprints), QA (gate history), CONTEXT-HANDOFF (the lessons the build sessions banked). Frame it as the site's memory — future changes start by reading these. Name `qa/` at the project root in the same breath and dispose of it: the build, prod, and gate logs there are evidence for one run, regenerated by the next, and nothing in `design/` depends on them — `design/` is the record, `qa/` is the receipt.227. **Gate re-run instructions:** `npm run build` (code gate), `npx eslint .` (`next lint` is removed in Next 16), and: with the ultraweb plugin installed, request changes via `ultraweb:iterate` — it re-runs only the affected gates and appends to design/QA.md.238. **Deploy record** (only if shipped): live URL, host, redeploy command, env keys the host needs — copied from ship's QA.md entry.249. **Maintenance notes:** the load-bearing decisions and how not to break them (see skeleton) — and fold every §Lessons block from `design/CONTEXT-HANDOFF.md` into that list, one line each, deduplicated against the standing bullets and against each other. A lesson cost this build real debugging time; leaving it in a file the next maintainer never opens makes them pay for it twice.2510. **Verify before done:** every file path named in the README exists (check each one), every command exits 0 — build already proven by ship; cite its QA.md line instead of re-running.2627## README skeleton2829```markdown30# <Site name>31<one sentence: what this site is and who it serves — from design/BRIEF.md>3233## Stack34Next.js <16.x.y> (App Router, Turbopack) · Tailwind CSS <4.x> (CSS-first — all35tokens in app/globals.css; there is no tailwind.config.js) · shadcn/ui (restyled36primitives) · motion <13.x> (import from "motion/react") · lucide-react · zod v437<+ animejs <4.x> ONLY if installed — with the DIRECTION moment it drives named on38 the same line; cut that moment and this package goes with it>39<+ backend pieces actually built>4041## Run it42npm install → npm run dev → localhost:3000. Production check: npm run build && npm run start.43Copy .env.example to .env.local and fill it — each key's comment says where it comes from.4445## Edit content & copy46| You want to change… | Edit this file |47|---|---|48| Homepage headline | components/sections/hero.tsx |49| <one row per user-visible surface, real paths> | |5051## Change the look — one file52Everything visual flows from tokens in app/globals.css:53- Accent color: edit --accent in :root AND .dark (both — dark mode is designed, not inverted)54- Corner rounding: the --radius-* tokens under @theme55- Fonts: swap the instance in lib/fonts.ts; the --font-* token name stays56Never hardcode a color or size in a component — change the token or add a variant.5758## The design/ folder59BRIEF · DIRECTION · SYSTEM · SITEMAP · QA · CONTEXT-HANDOFF — <one line each>.60Read DIRECTION.md before any visual change: it names what this site will NOT do.61The qa/ folder at the project root is logs from the last gate run — disposable, safe to delete.6263## Quality gates64npm run build must exit clean. Lint: npx eslint . (the next lint command no longer65exists). With the ultraweb plugin: make changes via ultraweb:iterate — it re-runs66the affected gates and logs results to design/QA.md.6768## Deployed69<live URL> on <host>. Redeploy: <command>. Env keys the host needs: <list>.7071## Don't break these72- One accent color. Wanting a second is a DIRECTION.md conversation, not a CSS edit.73- Dark mode is re-decided per surface — check both themes after any color change.74- prefers-reduced-motion paths must keep working; test with motion disabled.75- <if app/(studio)/ exists: the dev-only /studio dashboard. Deletable — one route group,76 one folder, zero cleanup; nothing else imports it and it 404s in production anyway.>77- <one line per design/CONTEXT-HANDOFF.md §Lessons entry, deduplicated — the traps this78 build already fell into, so the next change doesn't rediscover them>79- <demo builds only: list every UNVERIFIED-PROOF sample quote and its file — each80 must be replaced with real proof before production; ship blocks on the tag>81```8283## Error monitoring — optional, and configured defensively8485Only worth a section when the owner will actually watch it; an unwatched SDK is weight and a data liability, and the honest answer for most brochure sites is none. If it goes in, Sentry is the default — and for a DACH audience its defaults are wrong out of the box. Turn `sendDefaultPii` off, leave Session Replay off (it records the DOM, so it is personal-data processing that needs a legal basis and its own `ultraweb:consent` category — never a silent default), set the EU ingest region so nothing leaves the EEA, and keep `tracesSampleRate` low enough that the free tier holds. The README states which of those are on, where the DSN lives, and who holds the login; a monitoring account nobody owns outlives the site.8687## Anti-patterns8889- "This is a [Next.js] project bootstrapped with create-next-app" — boilerplate survived90- `tailwind.config.js` mentioned anywhere — v4 is CSS-first; the token story lives in globals.css91- `next lint` in gate instructions — removed in Next 16; the ESLint CLI is the command92- `npx shadcn-ui` in maintenance docs — dead package; it is `npx shadcn@latest`93- A content-map row pointing at a path that doesn't exist — step 10 exists to kill this94- Versions written as "latest" instead of package.json's pinned reality95- Generic framework tutorial prose ("Learn more about Next.js…") instead of facts about THIS site9697## Worked example — Aldermoor Trust, README for a volunteer-run site9899Moved to `references/example.md` — read only when this build's case is genuinely ambiguous; the sections above are the decision material.100101## Composes with102103Moved to `references/composes.md` — the handoff map; load it when orchestrating this skill against its neighbors.