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-reviewfor full design feedback. Use/activation-optimizationfor onboarding flow strategy. Reference/persona-draftfor user context.
Process
Step 1: Gather inputs
Ask the user to provide:
- What needs copy? -- specific screens, components, or flows that need interface text
- Product context -- what the product does, who uses it, current voice/tone (if any)
- Voice guidelines -- existing brand voice docs or tone preferences
- User state -- what is the user feeling or trying to do when they encounter this copy?
- Technical constraints -- character limits, variable data, text expansion budgets
- 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:
| Criterion | What to check |
|---|---|
| Clarity | Can the user understand what to do in under 3 seconds? |
| Action orientation | Does the copy tell the user what happens next? |
| Tone match | Does the copy match the user's emotional state in this moment? |
| Consistency | Are similar actions described the same way across the product? |
| Brevity | Can you say it in fewer words without losing meaning? |
| Jargon | Does 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:
| State | Copy pattern | Example |
|---|---|---|
| Empty state | Explain what will appear + guide to first action | "No projects yet. Create your first project to get started." |
| Loading | Set 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." |
| Success | Confirm what happened + suggest next step | "Project created. Invite your team to start collaborating." |
| Permission request | Explain why you need it + what the user gets | "Allow notifications to get updates when teammates comment." |
| Destructive action | State 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
| Element | Copy | Notes |
|---|---|---|
| Heading | Delete "{{report_name}}"? | Uses the actual report name so users confirm the right item. Stays under 48-char budget for typical names. |
| Body | This 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 report | Mirrors the action label exactly. Avoids vague "Yes" or alarming "Permanently delete." Under 24 chars. |
| Secondary action | Keep report | Positive 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
| Element | Copy | Notes |
|---|---|---|
| Heading | No saved reports yet | "Yet" signals this is a temporary, fixable state — not an error. Removes the passive "found." |
| Body | Build 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 CTA | Build 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
| Element | Copy | Notes |
|---|---|---|
| Heading | This report couldn't be generated | Passive construction intentional — avoids "we failed" and avoids blaming the user. Clear, under 48 chars. |
| Body | There 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 CTA | Try again | Simple re-trigger. Appropriate when the issue is likely transient. |
| Secondary action | Edit report filters | Offers 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
| State | Screen | Copy status |
|---|---|---|
| Destructive action | Delete 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.