copywriting — copy is design
Stage: Phase 8 — Voice (consulted during every Phase 6 section build) - Reads: design/BRIEF.md (tone words, audience, offer), design/DIRECTION.md (archetype), design/SITEMAP.md part 2 (density budgets) - Writes: §Voice appended to design/DIRECTION.md + every string in components
Standard
Every string is written for THIS brief in a defined voice. Headlines survive the swap test: paste one onto a competitor's site — if it still works, it says nothing and fails. Microcopy gets the same care as heroes; alt text and aria-labels are copy too. A string that could have been generated without reading the brief is a defect, not a draft. Body copy is scannable, not a wall: readers scan in an F-pattern and rarely pass a paragraph's first two sentences, so front-load the point and break three-plus supporting clauses into a list rather than a subordinate-clause pile-up — the ≤45-word body limit below is the ceiling, not the target (long-form technical prose is exempt).
Voice definition (always first)
- Take the 3 tone words from
design/BRIEF.md and score them onto the Voice Matrix — four orthogonal 1–5 sliders: Formal↔Casual, Serious↔Playful, Plain↔Expressive, Reserved↔Bold. Then write one "sounds like" and one "never sounds like" sentence pair per tone word — six sentences total. The four numbers are the drift detector: every later string batch (hero, nav, footer, errors) gets a one-line check against them, so a witty hero can't sit beside a corporate-flat footer undetected.
- German register (de-DE — decide before any German string): the Formal↔Casual slider made grammatical. Record Sie or Du plus a one-line brand rationale in
design/BRIEF.md, then hold it across nav, forms, errors, confirmations, and transactional email. Sie for B2B, regulated, or trust-coded builds (Ledger & Lane; the Deutsche Bahn / Sparkasse convention); Du for D2C, playful, or modern ones (Loop & Thread, Framewalk; N26's deliberate break from bank convention). gate-content flags any mixed-register string the way it flags dead copy.
- Fix 5 mechanics: person (we/you/it), contraction policy, sentence-length ceiling in words, jargon policy (which domain terms are in, which are out), humor policy (none / dry / warm — never wacky).
- Write 3 calibration strings — one hero headline, one button, one error message — and check each against every pair from step 1 and the matrix scores. These are the tuning fork for every later string.
- Append the result as
## Voice to design/DIRECTION.md. Phase 6 agents draft against it; Phase 8 rewrites in it.
Headline formulas (rotate — no two adjacent sections share one)
| Formula |
Shape |
Example |
| Plain claim |
concrete outcome, declarative |
"Your books, closed in three days." |
| Named enemy |
attack the pain, not praise the product |
"Spreadsheets were never meant to run payroll." |
| Specific number |
a real figure carries the line |
"14 grams. 40 hours. Zero cables." |
| Category reframe |
deny the expected category |
"Not a CRM. A memory." |
| Reader mid-action |
second person, already in the scene |
"You hit publish. We handle the rest." |
| Verb-first |
imperative with a concrete verb |
"Ship the update. Skip the meeting." |
Rules: every headline contains ≥1 concrete noun; abstract -ify/-ize verbs (simplify, optimize, revolutionize) never carry the sentence; run the swap test on every H1 and H2.
Length limits (hard)
| String |
Limit |
| Hero H1 |
≤8 words |
| Hero subhead |
≤20 words, one sentence |
| Section H2 |
≤8 words |
| Body paragraph |
≤3 sentences, ≤45 words |
| Button / CTA |
≤3 words |
| Nav label |
1–2 words |
| Testimonial pull quote |
≤30 words |
| Error message |
≤2 sentences |
| Meta title |
≤60 chars; meta description 140–160 chars |
| Kinetic-reveal beat (only if a reveal is selected) |
≤6–8 words; German ≤5–6 |
Density budgets in design/SITEMAP.md part 2 override these downward, never upward. When a kinetic-type reveal is on, split any line longer than one beat into multiple reveal beats with pauses (40–80ms stagger) — never shrink the font to fit; the prefers-reduced-motion fallback shows the full string at once.
Banned phrases (taste list, expanded — grep for every one)
From taste, absolute: "Welcome to", "Elevate your", "Unlock the power of", "Seamlessly", "Empower".
Expanded, same status: "Supercharge", "Revolutionize", "Streamline your", "Effortlessly", "Take your ... to the next level", "All-in-one platform", "Built for the modern", "Blazingly fast", "Game-changer", "Cutting-edge", "Next-generation", "Best-in-class", "World-class", "Say goodbye to", "Say hello to", "In today's fast-paced world", "We've got you covered", "Look no further", "Unleash", "Leverage" as a verb, "your journey", "It's that simple", "Made simple", "Discover the difference", "robust" and "innovative" as praise, "solutions" unattached to a named problem.
No emoji in production copy (✨🚀🎉 — taste ban). Max 1 exclamation point per page; 0 in error messages.
Microcopy standards
- Buttons: ≤3 words, verb-first, name the outcome — "Start free trial", "See pricing", "Book a call". Banned as defaults: "Submit", "Click here", "Learn more" (try a specific label first: "Read case study").
- Errors: what happened + how to fix, in that order, in the voice — "Card declined. Check the number or try another card." Never "Oops!", never "Something went wrong" without a next step, never blame ("You entered an invalid email" → "That email is missing an @").
- Empty states: state + action — "No projects yet. Create your first." Never a bare "No data".
- Success: confirm the specific thing — "Message sent — we reply within one business day." Not "Success!".
- Form labels and hints: labels are nouns, always visible (forms owns the layout); hints state the format before the error can happen ("8+ characters"), and validation errors follow the error rule above.
- Loading: name the work when it exceeds ~1s ("Generating preview…"); below that, the spinner speaks alone.
Process
- Define the voice (above) if
## Voice is not yet in DIRECTION.md.
- Inventory every string: grep components for JSX text,
aria-label, alt, metadata objects, and server-action error returns. Nothing user-visible escapes the inventory.
- Rewrite headlines first, in page order. Then read every H1→H2 aloud as a sequence — it must argue the page's conversion goal on its own (
gate-content checks exactly this).
- Rewrite microcopy: every button, error, empty, success, hint, and loading string against the standards above.
- Sweep: grep the codebase for each banned phrase; fix all hits. Verify the hard limits on hero H1, H2s, and buttons by counting.
- Read each full page aloud once. Any string you stumble on, rewrite shorter.
Anti-patterns
- "Welcome to [Product]" as a hero — announces nothing (grep: "Welcome to")
- A headline that is the company's mission statement instead of the reader's outcome
- "Learn more" four times on one page (grep: "Learn more")
- "Submit" on any form (grep: ">Submit<")
- "Oops" or "Something went wrong" with no recovery path (grep: "Oops", "went wrong")
- Title Case On Every Headline Word — default to sentence case; if DIRECTION.md decides otherwise, keep it consistent site-wide
- Lorem ipsum or draft markers surviving into Phase 8 (grep: "lorem", "ipsum", "TBD")
- Body copy that re-explains the headline directly above it — say it once
- A marketing paragraph that buries its point in a subordinate-clause pile-up — lead with the conclusion, list the rest
- Mixed German register — Sie in checkout, Du in a toast confirmation (decide once in BRIEF.md, hold everywhere)
- A kinetic-reveal line too long to read before the stagger finishes — split into beats, never shrink the font
- Alt text like "image" or "photo" — describe what the image argues, or mark it decorative
Worked example — Kaffeewerk Ost, roastery shop voice + hero copy
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: copywriting3description: Voice definition and every string on an ultraweb site — derives a written voice spec from the brief's tone words, then writes headlines (hero H1 ≤8 words via named non-slop formulas), CTAs, microcopy, error/empty/success text, alt text, and metadata, enforcing an expanded banned-phrase list against dead startup copy. Invoke in Phase 8 (Voice) of the pipeline and whenever a Phase 6 section ships with draft strings; also when the user says "write the copy", "the headline is weak", "this sounds like AI", "fix the button text", "better error messages", or asks for taglines, CTAs, or microcopy.4---56# copywriting — copy is design78**Stage:** Phase 8 — Voice (consulted during every Phase 6 section build) - **Reads:** design/BRIEF.md (tone words, audience, offer), design/DIRECTION.md (archetype), design/SITEMAP.md part 2 (density budgets) - **Writes:** §Voice appended to design/DIRECTION.md + every string in components910## Standard1112Every string is written for THIS brief in a defined voice. Headlines survive the swap test: paste one onto a competitor's site — if it still works, it says nothing and fails. Microcopy gets the same care as heroes; alt text and aria-labels are copy too. A string that could have been generated without reading the brief is a defect, not a draft. Body copy is scannable, not a wall: readers scan in an F-pattern and rarely pass a paragraph's first two sentences, so front-load the point and break three-plus supporting clauses into a list rather than a subordinate-clause pile-up — the ≤45-word body limit below is the ceiling, not the target (long-form technical prose is exempt).1314## Voice definition (always first)15161. Take the 3 tone words from `design/BRIEF.md` and score them onto the **Voice Matrix** — four orthogonal 1–5 sliders: Formal↔Casual, Serious↔Playful, Plain↔Expressive, Reserved↔Bold. Then write one "sounds like" and one "never sounds like" sentence pair per tone word — six sentences total. The four numbers are the drift detector: every later string batch (hero, nav, footer, errors) gets a one-line check against them, so a witty hero can't sit beside a corporate-flat footer undetected.172. **German register (de-DE — decide before any German string):** the Formal↔Casual slider made grammatical. Record **Sie** or **Du** plus a one-line brand rationale in `design/BRIEF.md`, then hold it across nav, forms, errors, confirmations, and transactional email. Sie for B2B, regulated, or trust-coded builds (Ledger & Lane; the Deutsche Bahn / Sparkasse convention); Du for D2C, playful, or modern ones (Loop & Thread, Framewalk; N26's deliberate break from bank convention). `gate-content` flags any mixed-register string the way it flags dead copy.183. Fix 5 mechanics: person (we/you/it), contraction policy, sentence-length ceiling in words, jargon policy (which domain terms are in, which are out), humor policy (none / dry / warm — never wacky).194. Write 3 calibration strings — one hero headline, one button, one error message — and check each against every pair from step 1 and the matrix scores. These are the tuning fork for every later string.205. Append the result as `## Voice` to `design/DIRECTION.md`. Phase 6 agents draft against it; Phase 8 rewrites in it.2122## Headline formulas (rotate — no two adjacent sections share one)2324| Formula | Shape | Example |25|---|---|---|26| Plain claim | concrete outcome, declarative | "Your books, closed in three days." |27| Named enemy | attack the pain, not praise the product | "Spreadsheets were never meant to run payroll." |28| Specific number | a real figure carries the line | "14 grams. 40 hours. Zero cables." |29| Category reframe | deny the expected category | "Not a CRM. A memory." |30| Reader mid-action | second person, already in the scene | "You hit publish. We handle the rest." |31| Verb-first | imperative with a concrete verb | "Ship the update. Skip the meeting." |3233Rules: every headline contains ≥1 concrete noun; abstract -ify/-ize verbs (simplify, optimize, revolutionize) never carry the sentence; run the swap test on every H1 and H2.3435## Length limits (hard)3637| String | Limit |38|---|---|39| Hero H1 | ≤8 words |40| Hero subhead | ≤20 words, one sentence |41| Section H2 | ≤8 words |42| Body paragraph | ≤3 sentences, ≤45 words |43| Button / CTA | ≤3 words |44| Nav label | 1–2 words |45| Testimonial pull quote | ≤30 words |46| Error message | ≤2 sentences |47| Meta title | ≤60 chars; meta description 140–160 chars |48| Kinetic-reveal beat (only if a reveal is selected) | ≤6–8 words; German ≤5–6 |4950Density budgets in `design/SITEMAP.md` part 2 override these downward, never upward. When a kinetic-type reveal is on, split any line longer than one beat into multiple reveal beats with pauses (40–80ms stagger) — never shrink the font to fit; the `prefers-reduced-motion` fallback shows the full string at once.5152## Banned phrases (taste list, expanded — grep for every one)5354From taste, absolute: "Welcome to", "Elevate your", "Unlock the power of", "Seamlessly", "Empower".55Expanded, same status: "Supercharge", "Revolutionize", "Streamline your", "Effortlessly", "Take your ... to the next level", "All-in-one platform", "Built for the modern", "Blazingly fast", "Game-changer", "Cutting-edge", "Next-generation", "Best-in-class", "World-class", "Say goodbye to", "Say hello to", "In today's fast-paced world", "We've got you covered", "Look no further", "Unleash", "Leverage" as a verb, "your journey", "It's that simple", "Made simple", "Discover the difference", "robust" and "innovative" as praise, "solutions" unattached to a named problem.56No emoji in production copy (✨🚀🎉 — taste ban). Max 1 exclamation point per page; 0 in error messages.5758## Microcopy standards5960- **Buttons:** ≤3 words, verb-first, name the outcome — "Start free trial", "See pricing", "Book a call". Banned as defaults: "Submit", "Click here", "Learn more" (try a specific label first: "Read case study").61- **Errors:** what happened + how to fix, in that order, in the voice — "Card declined. Check the number or try another card." Never "Oops!", never "Something went wrong" without a next step, never blame ("You entered an invalid email" → "That email is missing an @").62- **Empty states:** state + action — "No projects yet. Create your first." Never a bare "No data".63- **Success:** confirm the specific thing — "Message sent — we reply within one business day." Not "Success!".64- **Form labels and hints:** labels are nouns, always visible (forms owns the layout); hints state the format before the error can happen ("8+ characters"), and validation errors follow the error rule above.65- **Loading:** name the work when it exceeds ~1s ("Generating preview…"); below that, the spinner speaks alone.6667## Process68691. Define the voice (above) if `## Voice` is not yet in DIRECTION.md.702. Inventory every string: grep components for JSX text, `aria-label`, `alt`, metadata objects, and server-action error returns. Nothing user-visible escapes the inventory.713. Rewrite headlines first, in page order. Then read every H1→H2 aloud as a sequence — it must argue the page's conversion goal on its own (`gate-content` checks exactly this).724. Rewrite microcopy: every button, error, empty, success, hint, and loading string against the standards above.735. Sweep: grep the codebase for each banned phrase; fix all hits. Verify the hard limits on hero H1, H2s, and buttons by counting.746. Read each full page aloud once. Any string you stumble on, rewrite shorter.7576## Anti-patterns7778- "Welcome to [Product]" as a hero — announces nothing (grep: "Welcome to")79- A headline that is the company's mission statement instead of the reader's outcome80- "Learn more" four times on one page (grep: "Learn more")81- "Submit" on any form (grep: ">Submit<")82- "Oops" or "Something went wrong" with no recovery path (grep: "Oops", "went wrong")83- Title Case On Every Headline Word — default to sentence case; if DIRECTION.md decides otherwise, keep it consistent site-wide84- Lorem ipsum or draft markers surviving into Phase 8 (grep: "lorem", "ipsum", "TBD")85- Body copy that re-explains the headline directly above it — say it once86- A marketing paragraph that buries its point in a subordinate-clause pile-up — lead with the conclusion, list the rest87- Mixed German register — Sie in checkout, Du in a toast confirmation (decide once in BRIEF.md, hold everywhere)88- A kinetic-reveal line too long to read before the stagger finishes — split into beats, never shrink the font89- Alt text like "image" or "photo" — describe what the image argues, or mark it decorative9091## Worked example — Kaffeewerk Ost, roastery shop voice + hero copy9293Moved to `references/example.md` — read only when this build's case is genuinely ambiguous; the sections above are the decision material.9495## Composes with9697Moved to `references/composes.md` — the handoff map; load it when orchestrating this skill against its neighbors.