Skip to main content
Design/ux-writing

UX Writing

You need interface copy for product experiences – button labels, error messages, onboarding flows, empty states.

Use this when you need to write or review microcopy for a product interface -- button labels, error messages, empty states, tooltips, confirmation dialogs, onboarding sequences, or notification text. Produces copy that follows voice guidelines and considers the user's emotional state at each touchpoint.

Related skills: Pair with /design-review for full design feedback. Use /activation-optimization for onboarding flow strategy. Reference /persona-draft for user context.

Process

Step 1: Gather inputs

Ask the user to provide:

  1. What needs copy? -- specific screens, components, or flows that need interface text
  2. Product context -- what the product does, who uses it, current voice/tone (if any)
  3. Voice guidelines -- existing brand voice docs or tone preferences
  4. User state -- what is the user feeling or trying to do when they encounter this copy?
  5. Technical constraints -- character limits, variable data, text expansion budgets
  6. Localization scope (optional) -- will this copy be translated? To which languages? If yes, localization notes will be included with each copy element.

Step 2: Audit existing copy (if applicable)

If the user provides current copy to improve, evaluate against these criteria:

CriterionWhat to check
ClarityCan the user understand what to do in under 3 seconds?
Action orientationDoes the copy tell the user what happens next?
Tone matchDoes the copy match the user's emotional state in this moment?
ConsistencyAre similar actions described the same way across the product?
BrevityCan you say it in fewer words without losing meaning?
JargonDoes the copy use the user's language, not internal terminology?

Step 3: Write the copy

For each copy element, provide:

### {{Screen or component name}}

**Context:** (What the user is doing and feeling when they see this)
**Current copy:** (If exists -- what it says now)

#### Recommended copy

| Element | Copy | Notes | Localization notes (if applicable) |
|---------|------|-------|-------------------------------------|
| Heading | (text) | (why this wording) | (text expansion impact, cultural tone considerations) |
| Body | (text) | (why this wording) | (string concatenation risks, gender/plural form needs) |
| Primary CTA | (text) | (why this verb) | (max char budget for longest locale) |
| Secondary action | (text) | (alternative path) | (adaptation notes) |

Step 4: Write state-specific copy

For each screen or flow, write copy for all relevant states:

StateCopy patternExample
Empty stateExplain what will appear + guide to first action"No projects yet. Create your first project to get started."
LoadingSet expectations for wait time if > 2 seconds"Loading your dashboard..."
Error (user)Say what went wrong + how to fix it. No blame."That email is already registered. Try signing in instead."
Error (system)Acknowledge the problem + what happens next"Something went wrong on our end. We're looking into it."
SuccessConfirm what happened + suggest next step"Project created. Invite your team to start collaborating."
Permission requestExplain why you need it + what the user gets"Allow notifications to get updates when teammates comment."
Destructive actionState what will happen, make it reversible if possible"Delete this project? All files will be moved to trash for 30 days."

Step 5: Review and iterate

Present the copy and ask:

  • Does this sound like your product? Does the tone feel right?
  • Are there states or screens I missed?
  • Any character limits I should know about?
  • Does the copy work for your non-English users? (Localization considerations)

Output location

Present the copy as formatted text in the conversation. For implementation, the copy can be extracted into a copy deck spreadsheet or component-level documentation.

Example Output

Input

  • What needs copy? Deletion flow for saved reports, empty state for the reports dashboard, and the error state when a report fails to generate
  • Product context: Meridian Analytics — a B2B data platform used by operations and finance teams at mid-market companies. Users build and save custom reports from warehouse data. Current copy is inconsistent and leans heavily on technical jargon ("query execution failed," "null result set").
  • Voice guidelines: Confident but not arrogant. Straightforward, no fluff. Treat users as competent professionals — don't over-explain, don't be cutesy. Avoid exclamation points.
  • User state: Deletion — cautious, wants to confirm before committing. Empty state — new user, slightly uncertain, wants to see value quickly. Error — frustrated, mid-workflow, needs a clear path forward.
  • Technical constraints: Dialog heading max 48 characters. CTA buttons max 24 characters. Report names are dynamic variables (e.g., {{report_name}}).

Output (abbreviated)

UX Copy — Meridian Analytics: Reports


Delete Report Dialog

Context: User clicked "Delete" on a saved report from the reports list. They're pausing to confirm — cautious, possibly second-guessing. The report may have taken significant time to build.

Current copy: "Are you sure you want to delete this report? This cannot be undone."

Recommended copy

ElementCopyNotes
HeadingDelete "{{report_name}}"?Uses the actual report name so users confirm the right item. Stays under 48-char budget for typical names.
BodyThis report and its scheduled runs will be permanently deleted. Shared links will stop working.Surfaces the non-obvious consequences (scheduled runs, shared links) without blame or drama. Skips "are you sure" — the dialog itself asks that.
Primary CTA (destructive)Delete reportMirrors the action label exactly. Avoids vague "Yes" or alarming "Permanently delete." Under 24 chars.
Secondary actionKeep reportPositive framing vs. "Cancel" — reinforces that they're keeping something, not cancelling a task.

State-specific note: If the report is shared with 3+ team members, add one line below the body:

3 people have access to this report. No additional friction — just information.


Reports Dashboard — Empty State

Context: User has just set up their account or cleared all saved reports. Slightly uncertain, wants to understand what this space is for and how to get value from it.

Current copy: "No reports found."

Recommended copy

ElementCopyNotes
HeadingNo saved reports yet"Yet" signals this is a temporary, fixable state — not an error. Removes the passive "found."
BodyBuild a report from any connected data source, then save it here to run again or share with your team.Explains the value loop (build → save → reuse/share) in one sentence. Skips generic "get started" phrasing.
Primary CTABuild your first report"First" is appropriate only on true first-time empty state. Use Build a report for post-deletion empty state.

Report Generation — Error State

Context: User triggered a report run and it failed. They're mid-workflow, likely time-pressured. The current copy ("Query execution failed — null result set returned") blames the system in technical terms and offers no resolution path.

Current copy: "Query execution failed — null result set returned."

Recommended copy

ElementCopyNotes
HeadingThis report couldn't be generatedPassive construction intentional — avoids "we failed" and avoids blaming the user. Clear, under 48 chars.
BodyThere was a problem reading data from {{source_name}}. This is usually caused by a connection timeout or a schema change in the source table.Names the likely causes so technical users can self-diagnose. {{source_name}} surfaces which connection failed — critical when users have multiple sources.
Primary CTATry againSimple re-trigger. Appropriate when the issue is likely transient.
Secondary actionEdit report filtersOffers an alternate resolution path if the schema has changed and the report needs updating.
Support link (inline)Still failing? Contact support →Only surfaces after a second failure (conditional display). Avoids prematurely routing users away from self-service.

State Coverage Summary

StateScreenCopy status
Destructive actionDelete dialog✅ Written
Empty state (first-time)Reports dashboard✅ Written
Empty state (post-deletion)Reports dashboard✅ Variant noted
Error (system)Report generation✅ Written
Error (repeat)Report generation✅ Conditional support link noted
Success (report saved)Report builder⚠ Not yet written — recommend covering next
Loading (>2s run time)Report generation⚠ Not yet written — flag if reports can take >3 seconds

Next steps: Does the tone feel right — particularly the error state? The current copy skews more technical than some finance personas prefer. Happy to write a warmer variant if the user base includes less-technical ops managers alongside data engineers.