microcopy-component-writer
Paste into Claude Code, Claude.ai, the desktop app, or the browser extension — ⌘/Ctrl+V. ✓ Copied. Switch to Claude and paste — ⌘/Ctrl+V.
Microcopy Component Writer
Generate consistent, on-brand microcopy for every UI state a component can reach: idle, loading, error, success, empty, disabled, and confirmation. Output is structured as a Microcopy Sheet — one row per string — so it can be dropped into Figma, a design system doc, or a CMS Dictionary without reformatting.
Usage
/microcopy-component-writer <component list or spec file>
[--page <page-name>]
[--voice <voice-guide-file>]
[--cms sitecore|optimizely|umbraco|headless]
[--format sheet|json|xliff]
Examples:
/microcopy-component-writer --page checkout --cms sitecore/microcopy-component-writer components/search.md --voice docs/brand-voice.md --format json/microcopy-component-writer "sign-up form, nav, global toast" --cms umbraco
Phase 1 — Component inventory
Parse the component list or spec file. For each component, identify:
- Component name and its UI states (list defaults below; user can override)
- Character limit per string (ask if not supplied; fall back to limits in
reference.md) - Platform constraints for the target CMS
If given a spec file, read it and extract component names and any existing strings. If given a free-text list, enumerate the components as named items.
Default UI states to cover for every component (unless overridden):
- Idle / default
- Active / focused
- Loading / in-progress
- Success
- Error / validation failure
- Empty state (where applicable — lists, search, dashboards)
- Disabled
- Confirmation / destructive action (where applicable — delete, submit)
Phase 2 — String generation rules
Global rules (apply to all strings)
- Short is always better — every character must earn its place.
- Human before functional — "Something went wrong" is warmer than "Error 500".
- Tell users what to do next, not just what failed.
- Never blame the user — "Invalid email" not "You entered an invalid email".
- Match the brand tone — formal brands keep full stops; casual brands may omit.
- Be specific where possible — "Save changes?" beats "Are you sure?".
- Avoid double negatives in confirmation dialogs.
- Preserve inclusivity — avoid gendered language; prefer "they/their".
CTA rules
- Lead with an imperative verb that describes the outcome: "Save changes", "Send message", "Download report" — not "Click here", "Submit", "OK".
- If space is tight (< 20 chars), drop articles: "Add item" not "Add an item".
- Pair primary and secondary CTAs so they contrast clearly: "Delete account" / "Keep account" not "Confirm" / "Cancel".
- Destructive CTAs must name the action: "Delete post" not "Yes" or "Confirm".
Error message rules
Structure: [What happened] + [Why] + [What to do]
- What happened: plain statement, present tense — "Your password is too short."
- Why (optional): only include if genuinely useful — "Passwords need at least 10 characters."
- What to do: actionable — "Try again with a longer password."
- Field-level errors: co-locate with the field; 60–80 chars max.
- Form-level summary errors: link to each invalid field by label name.
Empty state rules
Structure: [Headline] + [Explanation] + [CTA]
- Headline: 3–8 words, present tense — "No results found" not "Nothing to show here".
- Explanation: 1–2 sentences; clarify what users can do — "Try a different search term or browse by category."
- CTA: optional but preferred; guide the next action.
- First-use empty states: celebrate the blank slate — "Your dashboard is ready. Add your first project to get started."
- Error-caused empty states: explain and offer a recovery action.
Toast / status message rules
| Type | Tone | Max length | Behaviour |
|---|---|---|---|
| Success | Warm, confirmatory | 60 chars | Auto-dismiss 4–6 s |
| Error | Calm, helpful | 80 chars | Persist until dismissed |
| Warning | Neutral, advisory | 80 chars | Persist or auto-dismiss depending on severity |
| Info | Neutral, informative | 100 chars | Auto-dismiss 5–8 s |
Do not use "Successfully" as a lead word in success messages — it's redundant ("Your changes have been saved" is cleaner than "Successfully saved your changes").
Placeholder text rules
- Describe the format, not the field name: email field → "name@company.com" not "Email address".
- For search inputs: "Search [noun]…" — specific to the content type, not just "Search…".
- Never use placeholder text as the sole label — it disappears on focus (accessibility failure).
Confirmation dialog rules
- Title: specific action — "Delete this post?" not "Are you sure?"
- Body: state the consequence — "This will permanently delete 'My draft post' and cannot be undone."
- Confirm button: mirrors the action verb — "Delete post"
- Cancel button: reverse of the action — "Keep post" or "Cancel"
Phase 3 — Output formats
Format: sheet (default)
Produces a Markdown table — one row per string.
## [Page / Component Set] — Microcopy Sheet
Generated: [date] | CMS: [cms] | Voice: [preset or file]
| Component | State | String key | Copy | Chars | Limit | Status |
|---|---|---|---|---|---|---|
| Sign-up form | Error — email invalid | `form.email.error.invalid` | "That doesn't look like a valid email address." | 47 | 80 | PASS |
| Sign-up form | Error — email taken | `form.email.error.taken` | "An account with this email already exists. Sign in instead?" | 58 | 80 | PASS |
Format: json
Produces a flat i18n JSON file keyed by component and state.
{
"locale": "en",
"generatedAt": "[ISO-8601]",
"strings": {
"form.email.error.invalid": "That doesn't look like a valid email address.",
"form.email.error.taken": "An account with this email already exists. Sign in instead?",
"form.submit.label": "Create account",
"form.submit.loading": "Creating your account…"
}
}
Format: xliff
Produces an XLIFF 1.2 file for TMS handoff or Sitecore Translation Provider import.
<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="en" datatype="plaintext"
original="[component-set]">
<body>
<trans-unit id="form.email.error.invalid">
<source>That doesn't look like a valid email address.</source>
<note>Field-level error — shown inline beneath the email input</note>
</trans-unit>
</body>
</file>
</xliff>
Phase 4 — CMS Dictionary mapping
When targeting a CMS, append a Dictionary Map section to the sheet.
Sitecore XM Cloud — Dictionary items
/sitecore/content/[Site]/Dictionary/Forms/EmailInvalidError
Key: Forms.EmailInvalidError
Value: "That doesn't look like a valid email address."
Flag strings that exceed 500 chars — Sitecore Dictionary values have no enforced limit but long values should be Rich Text fields instead.
Optimizely CMS — Language file keys
Map to [LangFolder]/[lang].xml or JSON resource files:
{
"/forms/emailinvaliderror": "That doesn't look like a valid email address."
}
Umbraco — Dictionary items
Dictionary key: Forms.Email.Error.Invalid
Value (en): "That doesn't look like a valid email address."
Umbraco Dictionary items are translated per language in the Backoffice — include a localization note column in the sheet for translator context.
Quality checklist
- Every error message tells the user what to do next
- No "Submit" or "OK" CTAs remain — all are descriptive action verbs
- No placeholder text doubles as a label (accessibility)
- All strings within character limits for the target CMS
- No "Successfully" lead word in success messages
- Destructive actions named in both the dialog title and confirm button
- Empty states include a recovery CTA where applicable
- String keys follow the convention:
component.element.statein camelCase
Reference
See reference.md for:
- Full character limit table by CMS and component type
- String key naming conventions for Sitecore, Optimizely, Umbraco, and i18next
- Example microcopy sheets for common component sets (checkout, search, auth forms)
Technical details
- Plugin
- copy-localization-generator
- Author
- Dakota Smith
- Skill name
microcopy-component-writer- Maturity
- experimental
- Security review
- No security review
- Owners
-
- design
- strategy
- Argument hint
<component list or spec file> [--page <page-name>] [--voice <voice-file>] [--cms sitecore|optimizely|umbraco|headless] [--format sheet|json|xliff]- Allowed tools
-
ReadWriteEditBash(find *)Bash(ls *)Bash(cat *)Bash(grep *)
- Source
plugins/copy-localization-generator/skills/microcopy-component-writer/SKILL.md
Edit this skill on GitHub — opens GitHub's web editor. No git knowledge needed.