---
name: "ux_writing"
description: "Write and fix product UI text: microcopy patterns for buttons, error messages, empty states, form labels and helper text, confirmations, toasts, and onboarding, with a voice and tone matrix and before-and-after pattern libraries. Use when writing or reviewing in-product copy, UI strings, error text, button labels, empty states, or a product voice guide, or when interface copy is vague, blaming, or inconsistent."
---

# UX Writing

## Purpose

Write the words inside a product so a person mid-task can act without stopping to decode them. This skill is for interface strings, not marketing pages. It ships pattern libraries with before-and-after examples, a tone matrix keyed to the user's emotional state, and a lint tool that catches vague, blaming, or generic strings before they ship. For landing pages and sales emails, use copywriting instead.

## Workflow

### 1. Inventory the strings before writing new ones

List every string in scope by type: button, link, field label, helper text, placeholder, validation error, system error, empty state, confirmation, toast, loading state, permission prompt, onboarding step. Note the screen, the user's goal on that screen, and what happens next if they act. A string written without its context will be generic, because generic is what context-free writing produces.

Flag terminology drift in the inventory: the same object or action named two ways (folder vs collection, remove vs delete, settings vs preferences). Pick one term per object and one verb per action, record them in a short word list, and use only those terms from here on.

### 2. Set voice once, then tone per moment

Voice is the product's personality and stays constant. Define it as 3 to 5 traits, each with a limit: plainspoken but not dumbed down, direct but not cold, confident but not arrogant. The limit is the part that does work in reviews.

Tone shifts with the user's state, not with the channel:

| User state | Tone | Copy moves |
|---|---|---|
| Doing routine work | Neutral, brief | Label the action, get out of the way |
| Learning or first run | Warm, patient | Explain the value, name the first step |
| Confused | Plain, reassuring | Restate in simpler words, offer one clear path |
| Blocked by an error | Calm, concrete | What happened, exact fix, no humor, no blame |
| Facing data loss or payment | Serious, precise | Name the consequence and what cannot be undone |
| Succeeded | Warm, short | Confirm what happened, suggest the next step if there is one |

Full matrix with examples: [references/pattern-library.md](references/pattern-library.md), section 1.

### 3. Apply the three priorities in order

1. Clarity: a first-time user understands it on one read, with no surrounding context.
2. Concision: every remaining word does work. Cut politeness padding, restated labels, and modifiers that add no information.
3. Character: voice shows through word choice only after the first two pass.

Never trade down. A clever label that needs a second read fails, however well it matches the brand.

Pick the string's job before drafting: inform (state what is true or what happened), influence (help a choice at a decision point), or interact (label an action so its result is predictable). A string trying to do all three usually does none.

### 4. Write by component, from the pattern library

Use the patterns in [references/pattern-library.md](references/pattern-library.md). The core rules:

- Buttons and links: verb plus object naming the outcome. Save changes, Create account, Delete message, Download PDF. Never OK, Submit, Yes, or Click here alone for a consequential action. In a confirmation dialog, the buttons repeat the action: Delete project and Keep project, not Yes and Cancel.
- Destructive actions: name the destruction and the count or object. Delete 5 photos, not Delete selected. Use delete when it is permanent and remove when the item can be restored or re-added, and never mix the two for the same action.
- Headings and page titles: describe the task or the content in sentence case, front-load the key word. Payment details, not Details about your payment information.
- Links: name the destination or the thing the reader will get. Read the refund policy, not Learn more.

### 5. Write errors as recovery instructions

Every error answers three questions, in this order:

1. What happened, in plain language, specific to this field or action.
2. Why, only if the reason helps the user fix it.
3. What to do next, as a concrete step or a button.

Rules:

- Name the field and the constraint: Enter an email address like name@example.com. Password needs at least 8 characters and one number.
- State what to do, not only what is wrong. Avoid invalid, illegal, and wrong as labels for the user's input.
- Never blame, never expose error codes, stack details, or internal names. Log the technical detail, show the human version, offer a support code only when support will actually ask for it.
- Match the wording of the field label. If the label says Email, the error says email.
- Place the message next to the problem. For form submissions, also show a summary at the top that links to each problem field and uses the same wording as the field-level messages.
- No humor in errors people may see repeatedly. No exclamation points in error, warning, or data-loss copy.
- Distinguish failure types, because the fix differs: format, missing value, permission, network, server, conflict (already exists), limit reached. Templates for each: pattern library section 3.

### 6. Treat empty states as three different problems

- First-run empty: nothing exists yet. Say what belongs here, why it is useful, and give the first action. No projects yet. Projects group related tasks in one place. Button: Create project.
- No-results empty: something exists, the filter or search hid it. Name the query or filter and how to widen it. No results for "harbor". Check the spelling, or clear the date filter.
- Error empty: content failed to load. Say so plainly and offer retry. We could not load your messages. Button: Try again.

Never ship a bare No items, Nothing here, or an illustration with no action.

### 7. Write forms so errors rarely happen

- Labels stay visible above the field. Never use the placeholder as the only label; it disappears while typing.
- Helper text states the constraint before the mistake: Must be 8 or more characters. Use it for format, limits, and where to find the information asked for.
- Placeholder text, when used, is an example of the format: name@example.com, not Enter your email here repeating the label.
- Mark optional fields as optional. Do not make the user guess which fields are required, and do not mark every required field with clutter when optional-marking does the same job.
- Instructions go before the field or form, not in a paragraph after the submit button.

### 8. Confirmations, toasts, loading, and success

- Confirmation dialogs: title names the action and object (Delete "Spring launch" project?), body states the consequence and what cannot be undone, buttons repeat the verb. Never title a dialog Are you sure? with no context.
- No confirmshaming: the decline option stays neutral. Keep my plan, not No, I hate saving money.
- Toasts and success messages: say what succeeded, with the object named, and stop. Invoice sent to Maya Chen. Not Success! or Done. Auto-dismiss low-stakes confirmations; keep failures visible until dismissed.
- Loading: say what is loading if the wait is more than a moment, and what will happen if it takes long or runs in the background. Generating your report. We will email you when it is ready.

### 9. Check mechanics, accessibility, and localization

- Sentence case for buttons, headings, labels, and menu items is the default in this skill. If the product already uses a different consistent style, match the product and record the choice.
- Active voice, present tense, short sentences. Front-load the important word; screen readers and scanners both start at the beginning.
- Use numerals for counts and amounts in UI strings: 3 items, not three items, when space is tight and the product style allows it.
- Do not put critical information only in a tooltip, only in color, or only in an icon label.
- Avoid idioms, jokes that depend on wordplay, and ambiguous pronouns. Leave room for translated text to grow; a label that exactly fills its button in English will overflow in many other languages.
- Read each string aloud. If it sounds like a log file or a legal notice, rewrite it. If it sounds like two different products wrote two adjacent strings, fix the drift.

### 10. Lint and audit before shipping

Run the bundled linter on any string list:

    python3 ~/workspace/skills/ux-writing/bin/lint_microcopy.py strings.txt

Input format: one string per line as `kind: text`, for example `button: Save changes` or `error: Enter your email address`. The linter flags generic button labels, blame words, vague errors, click-here links, all-caps shouting, and error strings with no recovery verb. It reports warnings; it does not rewrite. Fix or explicitly justify each flag.

Then run [references/audit-checklist.md](references/audit-checklist.md) on the full set. Terminology consistency and tone fit are human checks; the linter cannot see them.

## Output Contract

When asked to write or revise UI text, return:

1. A string table: location or component, kind, final text, and for revisions the before text and a one-line reason per change tied to a rule in this skill.
2. The word list: the chosen term for each object and verb for each action touched, so the next screen stays consistent.
3. Tone notes: any place tone shifts (error, data loss, success) and why.
4. Lint results: the command run and its output, or a plain statement that no string file was supplied and the check was done by reading.
5. Open risks: strings written without screen context, untested assumptions about the user's vocabulary, and any place the product's existing style conflicts with this skill.

## Operating Rules

1. Clarity first, concision second, character last. Never trade down.
2. Buttons and links name the outcome with a verb plus object. No generic labels alone for consequential actions.
3. Every error states what happened and the exact next step. No blame, no codes, no vague failures except a plain server-fault message that offers retry or support.
4. Every empty state orients and offers an action. No dead ends.
5. One term per object, one verb per action, everywhere. Record choices in the word list.
6. Voice stays constant; tone follows the user's state. Serious moments get plain copy, not brand jokes.
7. Helper text prevents errors; error text repairs them. Write both, not only the error.
8. No invented research claims. Do not cite conversion lifts, reading statistics, or study results unless a primary source was checked in this task and is named in the output.
9. Match the product's established voice and style when the user supplies them. Product-specific vocabulary is not jargon to its own users.
10. Never half-ship a string set: if context for a string is missing, mark it as needing the screen or flow, do not guess its action.

## References

- [Pattern library](references/pattern-library.md): tone matrix with examples, and before-and-after patterns for buttons, errors by failure type, empty states, forms, confirmations, toasts, loading, permissions, and onboarding.
- [Audit checklist](references/audit-checklist.md): yes and no checks for a full string set before release.
- Linter: `bin/lint_microcopy.py`, flags generic, blaming, vague, and recovery-free strings in a `kind: text` list.
