DOMAIN:CONTENT — UX WRITING & MICROCOPY¶
OWNER: jouke, dinand
ALSO_USED_BY: benjamin, joost, floris, floor (Frontend), dima (Intake — public-facing)
UPDATED: 2026-03-24
UX_WRITING:ERROR_MESSAGES¶
RULE: every error message answers THREE questions
1. What happened? (specific, not vague)
2. Why did it happen? (cause)
3. How to fix it? (actionable next 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 couldn't save your changes because your session expired. Sign in again to continue."
EXAMPLE (bad): "Error 403."
Error Message Rules¶
RULE: never blame the user — say "That email address isn't valid" not "You entered an invalid email"
RULE: never use technical jargon — no "500 Internal Server Error" in UI
RULE: never use ALL CAPS for errors — it reads as shouting
RULE: use sentence case for error text
RULE: keep errors under 2 sentences for inline validation
RULE: for complex errors, offer a "Learn more" link
RULE: error messages MUST be translatable — no string concatenation
Error Severity Tones¶
| Severity | Tone | Example Prefix |
|---|---|---|
| Validation | Helpful, immediate | "Enter a valid..." |
| Warning | Cautious, informative | "This will..." |
| Blocking | Empathetic, solution-focused | "We couldn't... Try..." |
| System error | Calm, reassuring | "Something's not working. We're looking into it." |
| Destructive | Serious, confirming | "This permanently deletes... This can't be undone." |
ANTI_PATTERN: "Something went wrong" with no context
FIX: specific message + error code + "Contact support with code X if this continues"
ANTI_PATTERN: "Oops!" or cutesy language on serious errors (payment failure, data loss)
FIX: match tone to severity — humor is never appropriate for money or data
ANTI_PATTERN: error message that differs between platforms (web vs. mobile)
FIX: single source of truth for copy — i18n JSON file, not hardcoded strings
UX_WRITING:EMPTY_STATES¶
RULE: every empty state has THREE elements
1. Illustration or icon (visual, not just text)
2. Explanation (what this area will show)
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 primary benefit, not the feature name
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
User-cleared (all items done/deleted)
- Tone: celebratory or neutral
- EXAMPLE: "All caught up! No new notifications."
- RULE: acknowledge the achievement if context allows
Error state (failed to load)
- Tone: honest, recoverable
- EXAMPLE: "Couldn't load your projects. Check your connection and try again."
- RULE: always provide retry action
ANTI_PATTERN: blank white screen with no explanation
FIX: every empty container has an empty state component
ANTI_PATTERN: empty state that just says "No data"
FIX: explain what data will appear AND how to create it
UX_WRITING:BUTTONS_AND_CTAS¶
RULE: button labels use verb + object format — "Create project", "Send invoice", "Download report"
RULE: never use generic labels — "Submit", "OK", "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 "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" |
ANTI_PATTERN: "Are you sure?" dialogs with "Yes" / "No" buttons
FIX: title = action question, buttons = specific action / "Cancel"
UX_WRITING:FORM_LABELS_AND_VALIDATION¶
Labels¶
RULE: labels are nouns or noun phrases — "Email address", "Password", "Company name"
RULE: labels are always visible — never rely on placeholder text alone
RULE: required fields marked with asterisk (*) — explain convention once at form top
RULE: optional fields marked with "(optional)" suffix — when most fields are required
Placeholders¶
RULE: placeholders show format hints — "name@example.com", "DD/MM/YYYY"
RULE: placeholders are NOT labels — they disappear on focus
RULE: placeholders use lighter text color (AA contrast not required but recommended)
Help Text¶
RULE: help text appears below the field, not in tooltip
RULE: help text explains constraints — "Must be at least 8 characters"
RULE: help text is always visible, not hidden behind an icon
Inline Validation Messages¶
RULE: validate on blur (not on every keystroke)
RULE: show success state for validated fields (green check)
RULE: error messages appear directly below the field
RULE: error message replaces help text (don't show both)
RULE: error message is specific — "Enter a valid email address" not "Invalid input"
ANTI_PATTERN: red field with no message explaining what's wrong
FIX: every invalid field has a visible text message
ANTI_PATTERN: validation that triggers while user is still typing
FIX: validate on blur or on submit, not on input
UX_WRITING:ONBOARDING_FLOW¶
RULE: progressive disclosure — show only what's 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"
Onboarding Copy Patterns¶
| Step Type | Copy Pattern | Example |
|---|---|---|
| Welcome | Greeting + value prop | "Welcome to [App]. Let's 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're all set! Here's your dashboard." |
ANTI_PATTERN: 10-step onboarding with no skip option
FIX: max 3-5 essential steps, defer the rest to contextual discovery
ANTI_PATTERN: "Welcome to [App]! [App] is a platform that..." (feature-first)
FIX: "Welcome to [App]. [What you can achieve]." (value-first)
UX_WRITING:NOTIFICATIONS¶
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 — user is already active |
| Complete, professional | Full paragraphs OK | Low — async | |
| SMS/text | Ultra-brief, urgent | <160 chars | Highest — reserved for critical |
RULE: push notifications state the fact + 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"
UX_WRITING:TONE_OF_VOICE¶
Nielsen Norman Group Four Dimensions¶
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 brand position on each dimension
RULE: create a voice matrix — map tone per scenario
Voice Matrix Template¶
| Scenario | Humor | Formality | Energy | Example |
|---|---|---|---|---|
| Success | Light OK | Casual | Enthusiastic | "Project created! Time to build." |
| Error (recoverable) | None | Neutral | Matter-of-fact | "Couldn't save. Check your connection." |
| Error (critical) | Never | Formal-ish | Calm | "Payment failed. Your card was not charged." |
| Onboarding | Light OK | Casual | Enthusiastic | "Let's get started!" |
| Destructive action | Never | Serious | Calm | "This permanently deletes all data." |
| Empty state | Light OK | Casual | Encouraging | "Nothing here yet. Create your first project." |
RULE: voice is constant (brand personality), tone adapts to context
RULE: humor scales DOWN with severity — never joke about money, data loss, security
RULE: document the voice in a 1-page Voice Chart with 3-5 adjectives
RULE: include "we are / we are not" pairs — e.g., "Helpful, not patronizing"
Building a Client Voice Guide¶
VOICE GUIDE TEMPLATE:
1. Brand personality (3-5 adjectives)
2. "We are / We are not" pairs (5-8 pairs)
3. Voice matrix (scenario × tone dimensions)
4. Word list (preferred terms, banned terms)
5. Example copy per scenario (success, error, empty, CTA)
6. Platform adaptations (web vs. mobile vs. email)
UX_WRITING:ACCESSIBILITY¶
STANDARD: WCAG 2.1 Level AA
RULE: write at 8th-grade reading level (Flesch-Kincaid)
RULE: avoid idioms, metaphors, and culturally-specific references
RULE: use plain language — "use" not "utilize", "start" not "commence"
RULE: front-load important information in sentences
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 — use text + color
RULE: aria-label on icon-only buttons — screen reader must know the action
TOOL: Hemingway Editor — readability scoring
TOOL: axe DevTools — 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)
FIX: "Click 'Delete project'" (relies on label)
ANTI_PATTERN: placeholder-only form fields (no visible label)
FIX: always pair visible label with input — placeholder is supplemental