Content design — UX writing

mandatory

Voice, tone, vocabulary, and pattern guide for every user-facing string in Koder products. Material parity (`/foundations/content-design/style-guide/ux-writing-best-practices`). Extends `errors/user-facing-messages.kmd` (which covers error copy only) to all UI text — buttons, labels, hints, empty states, success messages.

Spec — Content design / UX writing

Facet *isual*do Koder Design. Material parity: https://m3.material.io/foundations/content-design/style-guide/ux-writing-best-practices.

Voice

Koder products speak as:

  • *nowledgeable but not condescending*— explain WHAT and (when

    helpful) WHY, never assume the user is wrong

  • *irect, not bossy*— "Save" not "You should save now"
  • *arm, not sappy*— friendly without faux-cheer ("Yay!" is out)
  • *pecific*— "Saved at 14:32" beats "Saved successfully"
  • *onfident*— declarative, present tense

Tone variants

Tone shifts by context but voice stays constant.

Context Tone Example
*uccess* Brief + specific "Profile updated."
*rror* Helpful + non-blaming "We couldn't reach the server. Check your connection and try again."
*mpty state* Inviting "No projects yet — create your first one to get started."
*nboarding* Encouraging + brief "Welcome to Koder Talk. Let's pick a wake word."
*estructive confirm* Serious + clear "Delete 12 messages? This can't be undone."
*oading* Quiet "Loading…" (avoid blank fluff like "Please wait while we…")

R1 — Lengths

Element Max chars (en-US baseline) Notes
Button label 24 Verb-first ("Save changes", "Delete")
Tab label 16 Noun ("Profile", "Activity")
Field label 32 Noun phrase ("Display name")
Hint text 80 Helpful one-liner
Error message 140 Brief + actionable (errors/user-facing-messages.kmd)
Section title 40 Noun phrase
Tooltip body 80 Brief reinforcement
Empty state body 200 Inviting + 1 CTA

pt-BR translations may run +30%; design for the longer language and truncate gracefully (no clipping).

R2 — Vocabulary

Canonical terms

Koder canonical Avoid
*ign in*(not "log in") "Login", "Log in"
*ign out* "Logout", "Log out"
*enant / workspace* "Account" (ambiguous with billing)
*ou*(second person) "User", "Users" (third person) in UI
*ave* "Submit" (for non-form workflows)
*ancel* "Discard", "Close" (use only for actually closing)
*elete* "Remove" (different semantics — remove from view, not data)
*ndo* "Cancel" (after the fact)
*end* "Post" (in non-social contexts)

Forbidden words

  • "Simply", "just", "easy" — they trivialize user effort
  • "Wrong", "invalid", "error" in body text — symbol + spec text per

    user-facing-messages.kmd

  • "Whoops", "oops" — friendly to a fault; use serious calm
  • "Click", "tap" — surface-neutral language ("Select", "Open")
  • "Awesome", "great", "perfect" as success acknowledgment — over-praise

R3 — Capitalization

*entence case*for everything except product names and proper nouns:

  • ✅ "Save changes"
  • ❌ "Save Changes"
  • ✅ "Sign in to Koder"
  • ❌ "Sign In To Koder"

Exception: company/product names retain Title Case ("Koder Design", "Koder Talk", "Koder Flow").

R4 — Punctuation

  • Period at end of complete sentences in body text
  • No period at end of short titles / buttons / labels / list items
  • Em dash with thin spaces: " — " (HTML entity )
  • Curly quotes for prose: " '
  • Straight quotes for code only
  • Oxford comma: yes (enUS convention; ptBR follows standard pt

    comma rules)

R5 — Numbers

  • Cardinal numerals < 10: spell out in prose ("nine items", "ten items")
  • ≥ 10: numerals ("10 items", "1,234 items")
  • Counts in UI labels: always numerals ("3 unread")
  • Time: 24h format in enUS ("14:32"); ptBR same
  • Dates: ISO 8601 in technical contexts; localized friendly form in UI

R6 — Internationalization

  • Strings in code: en-US source of truth
  • Translations: humantranslated for ptBR; machine fallback marked

    visibly until human pass

  • ICU keys per i18n/contract.kmd R6
  • Plurals: ICU {count, plural, one {1 file} other {# files}}
  • Variables in translations: {name}, never positional %s

R7 — Accessibility

  • Visible text MUST also be readable by screen readers (no

    CSS-tricks where the visible label differs from the semantic one)

  • Icononly buttons MUST have `arialabel`
  • Error text MUST be associated with the failing field

    (aria-describedby)

  • Section titles MUST use semantic headings (<h2>-<h6>, never

    styled divs)

R8 — Examples

Button label

Why
"OK" "Save" Verb-specific
"Click here to save" "Save" Concise + neutral
"SUBMIT" "Send message" Sentence case + specific verb

Error

"Invalid input" "Email must include @ — try name@example.com"
"Wrong password" "We couldn't sign you in. Check your password or reset it."
"Server error" "Couldn't save right now. Your changes are safe locally — we'll retry automatically."

Empty state

"No data" "No projects yet — create your first to get started."
"Empty" "You have no scheduled messages. Schedule one from any conversation."
  • errors/user-facing-messages.kmd — error message format
  • policies/language.kmd — ptBR / enUS per surface
  • i18n/contract.kmd — translation pipeline

Source: ../home/koder/dev/koder/meta/docs/stack/specs/foundations/ux-writing.kmd