DOMAIN:CREATIVE — UX WRITING & MICROCOPY¶
OWNER: rick ALSO_USED_BY: jouke (Content), dinand (Content), floris (Frontend Alpha), floor (Frontend Beta), dima (Intake) UPDATED: 2026-03-28 PREREQUISITE: brand-voice.md (voice and tone framework applies to all microcopy)
PRINCIPLE: CLARITY OVER CLEVERNESS¶
RULE: every piece of interface text exists to help the user accomplish a task. If clever wording slows comprehension by even one second, replace it with plain language.
RULE: UX copy is not marketing copy. Marketing attracts. UX copy guides. The goals are different and the writing must reflect that.
RULE: read every string aloud. If a non-technical person cannot understand it instantly, rewrite it.
MENTAL_MODEL: UX writing is industrial design with words. Every word is a component. If a component does not serve the user's task, remove it.
UX_WRITING:ERROR_MESSAGES¶
RULE: every error message answers THREE questions. 1. What happened? (specific, not vague) 2. Why did it happen? (cause the user can understand) 3. What do I do next? (actionable recovery step)
Error Message Template¶
EXAMPLE (good): "Your password must be at least 8 characters. You entered 5. Add 3 more characters to continue." EXAMPLE (bad): "Invalid password." EXAMPLE (good): "We could not save your changes because your session expired. Sign in again to continue." EXAMPLE (bad): "Error 403." EXAMPLE (good): "This file is too large to upload. The maximum size is 10 MB. Compress the file or choose a smaller one." EXAMPLE (bad): "Upload failed."
Error Message Rules¶
RULE: never blame the user — "That email address is not valid" not "You entered an invalid email" RULE: never use technical jargon in the UI — no "500 Internal Server Error", no stack traces RULE: never use ALL CAPS for errors — it reads as shouting RULE: use sentence case for error text RULE: keep inline validation errors under 2 sentences RULE: for complex errors, offer a "Learn more" link to documentation RULE: include an error code for support reference — "Contact support with code E-4012 if this continues" RULE: error messages MUST be translatable — no string concatenation, no interpolated grammar
Error Severity Tone Map¶
| Severity | Tone | Opener Pattern | Example |
|---|---|---|---|
| Validation | Helpful, immediate | "Enter a valid..." | "Enter a valid email address." |
| Warning | Cautious, informative | "This will..." | "This will replace your current file." |
| Blocking | Empathetic, solution-focused | "We could not... Try..." | "We could not process your payment. Try a different card." |
| System error | Calm, reassuring | "Something is not working..." | "Something is not working. We are looking into it." |
| Destructive | Serious, confirming | "This permanently..." | "This permanently deletes your account. This cannot be undone." |
ANTI_PATTERN: "Something went wrong" with no context FIX: specific message + error code + recovery action
ANTI_PATTERN: "Oops!" or cutesy language on serious errors (payment failure, data loss) FIX: match tone to severity — humor is never appropriate for money, data, or security
ANTI_PATTERN: error message that differs between web and mobile for the same condition FIX: single source of truth for copy — i18n JSON file, not hardcoded strings
ANTI_PATTERN: showing raw API error responses to the user FIX: map every API error code to a human-readable message in a central error copy file
UX_WRITING:EMPTY_STATES¶
RULE: every empty state has THREE elements. 1. Visual — illustration or icon (not just text) 2. Explanation — what this area will contain once populated 3. Call to action — how to populate it
Empty State Types¶
First-use (onboarding) - Tone: encouraging, value-focused - EXAMPLE: "No projects yet. Create your first project to start building." - RULE: show the benefit, not the feature name - RULE: use a primary action button, not just a text link
No results (search/filter) - Tone: helpful, suggestive - EXAMPLE: "No results for 'xyz'. Try a different search term or remove filters." - RULE: suggest next actions — broaden search, clear filters, check spelling - RULE: never show a completely blank area — always provide guidance
User-cleared (all items completed or deleted) - Tone: celebratory or neutral depending on context - EXAMPLE: "All caught up. No new notifications." - RULE: acknowledge the achievement when appropriate
Error state (failed to load) - Tone: honest, recoverable - EXAMPLE: "Could not load your projects. Check your connection and try again." - RULE: always provide a retry button
Permission denied - Tone: informative, non-judgmental - EXAMPLE: "You do not have access to this workspace. Ask your admin for an invitation." - RULE: tell them WHO can help and HOW
ANTI_PATTERN: blank white screen with no explanation FIX: every container component has a corresponding empty state design
ANTI_PATTERN: empty state that says "No data" with no further guidance FIX: explain what data will appear AND how to create it
UX_WRITING:ONBOARDING_FLOWS¶
RULE: progressive disclosure — show only what is needed at each step RULE: lead with value — "Set up your workspace to start collaborating" not "Step 1 of 5" RULE: show progress — step indicator or progress bar RULE: allow skip where possible — "Skip for now, set up later" RULE: explain WHY you need information — "We use your timezone to schedule notifications correctly" RULE: max 3-5 essential steps; defer everything else to contextual discovery
Onboarding Copy Patterns¶
| Step Type | Copy Pattern | Example |
|---|---|---|
| Welcome | Greeting + value prop | "Welcome to [App]. Let us get you set up in 2 minutes." |
| Data collection | Why + what | "Add your company name. This appears on all invoices." |
| Feature intro | Benefit + action | "Invite your team to start collaborating in real time." |
| Completion | Achievement + next step | "You are all set. Here is your dashboard." |
Progressive Disclosure Principles¶
- First run: Show the 1-2 things the user MUST do to get value.
- Day 1-3: Surface features contextually as the user encounters them.
- Week 1+: Tooltips for advanced features only when the user approaches them.
- Never: Dump all features at once in a tour nobody asked for.
ANTI_PATTERN: 10-step onboarding with no skip option FIX: max 3-5 essential steps; everything else is deferred contextual guidance
ANTI_PATTERN: "Welcome to [App]! [App] is a platform that..." (feature-first) FIX: "Welcome to [App]. [What you can achieve]." (value-first)
ANTI_PATTERN: tooltip tour that fires automatically and blocks the interface FIX: user-initiated guidance ("Show me around" link) or contextual tips tied to first-time actions
UX_WRITING:BUTTONS_AND_CTAS¶
RULE: button labels use verb + object format — "Create project", "Send invoice", "Download report" RULE: never use generic labels — not "Submit", not "OK", not "Click here" RULE: destructive actions use specific labels — "Delete project" not "Delete" RULE: primary action is specific, secondary is generic — "Save changes" / "Cancel" RULE: button text is max 3-4 words RULE: use sentence case for buttons (not Title Case, not ALL CAPS)
Confirmation Dialogs¶
RULE: dialog title states the action — "Delete this project?" RULE: dialog body states consequences — "This permanently deletes the project and all its data." RULE: confirm button repeats the action verb — "Delete project" (not "Yes" or "OK") RULE: cancel button says "Cancel" or the safe alternative — "Keep project" (not "No")
| Pattern | Good | Bad |
|---|---|---|
| Save | "Save changes" | "Submit" |
| Delete | "Delete project" | "OK" |
| Navigate | "Go to dashboard" | "Click here" |
| Create | "Create account" | "Next" |
| Send | "Send message" | "Done" |
| Confirm | "Place order" | "Confirm" |
| Cancel | "Discard changes" | "No" |
| Upgrade | "Upgrade to Pro" | "Learn more" |
ANTI_PATTERN: "Are you sure?" dialogs with "Yes" / "No" buttons FIX: title = action question, buttons = specific action / "Cancel"
ANTI_PATTERN: CTA that says "Get started" on every page regardless of context FIX: CTA that matches the specific action — "Create your first project", "Import your data"
UX_WRITING:LOADING_STATES¶
RULE: if a loading state lasts more than 2 seconds, show a message. RULE: messages should set expectations — "Loading your projects..." is better than a spinner alone. RULE: for long operations (>5 seconds), show progress or explain what is happening. RULE: avoid "Please wait" — it adds no information.
Loading Copy Patterns¶
| Duration | Pattern | Example |
|---|---|---|
| <2 seconds | Skeleton / spinner only | No text needed |
| 2-5 seconds | Action description | "Loading your dashboard..." |
| 5-15 seconds | Action + context | "Generating your report. This usually takes about 10 seconds." |
| 15+ seconds | Action + progress + option | "Processing 2,450 records (67% complete). You can close this page — we will email you when it is done." |
| Background | Notification pattern | "Your export is being prepared. We will notify you when it is ready." |
ANTI_PATTERN: "Loading..." with no indication of what is loading FIX: name the thing being loaded — "Loading invoices..." or "Preparing your report..."
ANTI_PATTERN: spinner that runs indefinitely with no timeout message FIX: after 30 seconds, show "This is taking longer than expected. Try refreshing the page."
UX_WRITING:SUCCESS_AND_CONFIRMATION¶
RULE: confirm what happened, not just that something happened. RULE: include the next logical action. RULE: success messages should be brief — the user wants to move on.
Success Copy Patterns¶
| Action | Good | Bad |
|---|---|---|
| Save | "Changes saved." | "Success!" |
| Send | "Invoice sent to anna@example.com." | "Done." |
| Delete | "Project deleted." | "Item removed successfully." |
| Create | "Account created. Check your email to verify." | "Registration complete." |
| Upload | "3 files uploaded." | "Upload successful." |
| Payment | "Payment of EUR 49.00 received. Receipt sent to your email." | "Thank you for your purchase!" |
RULE: for destructive actions, confirm what was destroyed and note irreversibility. RULE: for email-dependent flows, tell them WHERE to look: "Check your inbox at j***@example.com" RULE: include undo option where technically possible: "Message archived. Undo."
ANTI_PATTERN: "Success!" toast with no detail FIX: "[What happened] + [what to do next or what to expect]"
ANTI_PATTERN: success message that disappears after 2 seconds before user can read it FIX: auto-dismiss after 5-8 seconds, or make it dismissible but persistent
UX_WRITING:TOOLTIPS_AND_HELPER_TEXT¶
RULE: tooltips supplement — they never replace visible labels or help text. RULE: helper text appears below the field, always visible. RULE: tooltips appear on hover/focus, for secondary information only. RULE: max tooltip length: 1-2 short sentences.
When to Use What¶
| Use | When |
|---|---|
| Visible helper text | The information is needed to complete the field correctly |
| Tooltip | The information is helpful but not essential |
| Inline link ("Learn more") | The explanation requires more than 2 sentences |
| Neither | The label is self-explanatory |
Helper Text Rules¶
RULE: explain constraints before the user hits them — "Max 50 characters" not after they exceed it. RULE: explain WHY when the reason is not obvious — "This appears on your public profile" RULE: use placeholder text for FORMAT hints only — "DD/MM/YYYY", "name@example.com" RULE: placeholders are NOT labels — they disappear on focus
ANTI_PATTERN: hiding critical information inside a tooltip that mobile users cannot hover over FIX: if the information is critical, it is visible helper text, not a tooltip
ANTI_PATTERN: tooltip that repeats the label — hovering over "Email" shows "Enter your email" FIX: tooltip should add NEW information — "We will send your receipt to this address"
UX_WRITING:NOTIFICATION_COPY¶
Tone Per Channel¶
| Channel | Tone | Length | Urgency |
|---|---|---|---|
| Push notification | Brief, actionable | <50 chars title, <100 body | High — interrupts user |
| In-app notification | Informative, contextual | 1-2 sentences | Medium |
| Complete, professional | Full paragraphs acceptable | Low — async | |
| SMS | Ultra-brief, urgent | <160 chars | Highest — reserved for critical |
RULE: push notifications state the event + action — "New comment on your project. View now." RULE: never use push for marketing — only transactional/actionable content RULE: in-app notifications are dismissible and have timestamps RULE: email subject lines are specific — "Invoice #1234 is ready" not "Update from [App]"
ANTI_PATTERN: push notification that says "You have a new notification" FIX: state WHAT happened — "Alex commented on your design"
ANTI_PATTERN: notification that provides no way to act on it FIX: every notification links to the relevant screen/action
UX_WRITING:CHARACTER_LIMITS_AND_CONSTRAINTS¶
Common Platform Limits¶
| Element | Recommended Max | Hard Limit | Notes |
|---|---|---|---|
| Page title | 60 chars | 70 chars (SEO) | Front-load keywords |
| Meta description | 155 chars | 160 chars | Include CTA |
| Button label | 3-4 words | ~25 chars | Verb + object |
| Toast/snackbar | 1-2 sentences | ~80 chars | Must be readable in 5 seconds |
| Tooltip | 1-2 sentences | ~150 chars | Essential info only |
| Push title | 40 chars | 50 chars (iOS) | Name the event |
| Push body | 80 chars | 178 chars (Android) | Include action |
| Form label | 2-4 words | — | Noun or noun phrase |
| Helper text | 1 sentence | ~80 chars | Constraint or explanation |
| Error message | 1-2 sentences | ~120 chars inline | What + why + fix |
| Email subject | 40 chars | 60 chars (mobile cutoff) | Specific, not clever |
| Email preview text | 40-90 chars | ~100 chars | Extends subject line |
RULE: write to the recommended max, not the hard limit. Shorter is almost always better. RULE: test on the smallest screen your users have. If it wraps awkwardly, trim it. RULE: never truncate mid-word. If space is tight, rewrite shorter.
DESIGN SYSTEM WRITING REFERENCES¶
Google Material Design Writing Guidelines¶
SOURCE: m3.material.io/foundations/content-design and m2.material.io/design/communication/writing.html
KEY PRINCIPLES: - Concise: short, scannable segments focused on a limited number of ideas - Clear: simple, direct language that is immediately understandable - Useful: text that helps the user complete their task - Address the user as "you" (second person). Use "I" / "my" only for user-owned content. - Sentence-style capitalization for titles, headings, labels, menu items - Skip unnecessary punctuation — periods in labels, colons after headers - Follow AP style for general language conventions
Shopify Polaris Content Guidelines¶
SOURCE: polaris.shopify.com
KEY PRINCIPLES: - Concise (Jenga test): what is the most you can remove before it breaks? - Actionable: start with verbs. "Add apps" not "You can add apps." - Direct: say it plainly. No hedging, no padding. - Human: read it aloud. Does it sound like something a person would say? - Merchant-first: put the user at the center and in control - Polaris provides per-component content guidelines (button text, banner copy, modal copy, etc.) - Each component doc includes "Best Practices" and "Content guidelines" sections
NN/g Four Dimensions of Tone¶
SOURCE: Nielsen Norman Group
Every piece of copy sits on four spectrums: 1. Funny <-> Serious — how much humor is appropriate 2. Casual <-> Formal — register and vocabulary level 3. Irreverent <-> Respectful — attitude toward conventions 4. Enthusiastic <-> Matter-of-fact — energy level
RULE: define the brand's position on each dimension and document it in the voice guide. RULE: map tone shifts per scenario type (see brand-voice.md for the full framework).
UX_WRITING:ACCESSIBILITY¶
STANDARD: WCAG 2.1 Level AA
RULE: write at 8th-grade reading level (Flesch-Kincaid Grade Level 8 or below) RULE: avoid idioms, metaphors, and culturally-specific references RULE: use plain language — "use" not "utilize", "start" not "commence", "buy" not "purchase" RULE: front-load important information in every sentence RULE: link text describes destination — "View billing settings" not "Click here" RULE: alt text for images describes function, not decoration RULE: screen readers read button labels — make them self-explanatory without visual context RULE: never convey meaning through color alone — always include text RULE: aria-label on icon-only buttons RULE: avoid directional language — "the button below" fails for screen readers, say "the Save button"
TOOL: Hemingway Editor — readability scoring TOOL: axe DevTools — automated accessibility testing TOOL: VoiceOver (macOS/iOS) / NVDA (Windows) — screen reader testing RUN: test every new screen with a screen reader before shipping
ANTI_PATTERN: "Click the red button" (relies on color + mouse interaction) FIX: "Select 'Delete project'" (relies on label)
ANTI_PATTERN: placeholder-only form fields (no visible label) FIX: always pair visible label with input — placeholder is supplementary
ANTI_PATTERN: "click here" or "learn more" as standalone link text FIX: "Read the pricing guide" or "View your account settings"
UX WRITING CHECKLIST (per screen)¶
- [ ] Every button uses verb + object format
- [ ] Every error message answers what / why / how-to-fix
- [ ] Every empty state has visual + explanation + CTA
- [ ] No placeholder-only form fields
- [ ] No jargon, no technical codes in user-facing text
- [ ] All copy tested at 8th-grade reading level
- [ ] All strings are in i18n files, not hardcoded
- [ ] Tested with screen reader (VoiceOver or NVDA)
- [ ] Tone matches severity (no humor on errors involving money/data)
- [ ] Character limits respected for all constrained contexts
REFERENCES¶
- Google Material Design 3 — Content Design: m3.material.io/foundations/content-design/overview
- Google Material Design 2 — Writing: m2.material.io/design/communication/writing.html
- Shopify Polaris — Content: polaris.shopify.com/content
- Kinneret Yifrah. Microcopy: The Complete Guide. 2017.
- Torrey Podmajersky. Strategic Writing for UX. O'Reilly, 2019.
- Nielsen Norman Group. "The Four Dimensions of Tone of Voice." nngroup.com.
- Scott Kubie. Writing for Designers. A Book Apart, 2018.