Skip to content
Beta Multi-model support (OpenAI, Gemini, and more) launching soon.

microcopy-component-writer

Installable Ships in copy-localization-generator — or copy the raw skill below.
Open Claude.ai

Paste into Claude Code, Claude.ai, the desktop app, or the browser extension — ⌘/Ctrl+V.

ExperimentalNo security review

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)

  1. Short is always better — every character must earn its place.
  2. Human before functional — "Something went wrong" is warmer than "Error 500".
  3. Tell users what to do next, not just what failed.
  4. Never blame the user — "Invalid email" not "You entered an invalid email".
  5. Match the brand tone — formal brands keep full stops; casual brands may omit.
  6. Be specific where possible — "Save changes?" beats "Are you sure?".
  7. Avoid double negatives in confirmation dialogs.
  8. 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.state in 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
  • Read
  • Write
  • Edit
  • Bash(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.