Skip to content

refactor(web): rewrite UX copy for clarity and consistency - #456

Merged
driaug merged 1 commit into
nextfrom
copy/clarify-web-app
Aug 10, 2026
Merged

refactor(web): rewrite UX copy for clarity and consistency#456
driaug merged 1 commit into
nextfrom
copy/clarify-web-app

Conversation

@driaug

@driaug driaug commented Aug 10, 2026

Copy link
Copy Markdown
Member

The copy across the dashboard was written screen by screen, so the same concept was phrased several different ways and a lot of text explained things the UI already said. This is a pass over every user-facing string in apps/web against one standard, applied consistently.

Systemic patterns removed:

  • 25 confirmation dialogs opened with "Are you sure you want to...", then repeated the question the title already asked. Titles now name the object ("Delete john@acme.com?"), bodies state only the consequence, and buttons are verb + object. Cancel dialogs previously rendered [Cancel] [Cancel Campaign]; the dismiss button now reads "Keep sending".
  • 42 success toasts ended in "successfully". The toast is already green.
  • 87 "Failed to X" strings gave no cause and no next step. Most sites already surfaced error.message and only used these as a fallback, so the fallbacks now name what did not happen and what to do.
  • ~20 CardDescriptions restated their own CardTitle. Deleted. The ones carrying an actual rule were kept and sharpened instead.
  • BillingConsumption, BillingInvoices and QuickStart each wrote their header 3-4 times across loading/error/empty branches. Hoisted to one header per component.
  • 243 Title Case UI strings across 190 distinct labels moved to sentence case. The app previously shipped both "Send To" and "Send to".
  • Required-field markers used three different mechanisms. Now one.
  • Terminology: "API Credentials" and "API Keys" were the same card under two names; cancelled/canceled and .../… were both in use; the templates page title disagreed with its nav item.

Structural changes:

  • Removed the analytics "Performance Insights" card. It dispensed advice the product cannot substantiate ("above industry average" against no cited benchmark, "add more compelling calls-to-action") in a product positioned against exactly that tone. Replaced with two counters drawn from real data: events triggered and workflow runs started.
  • Subscription activation copy was ~75 words over two paragraphs. It is load-bearing (it prevents billing surprises), so it was restructured rather than cut: one summary line plus a "Why two charges?" disclosure.
  • Consolidated the DKIM instructions that appeared both above and below the DNS record table.
  • Trimmed the workflow active-executions notice and the HTML-to-visual editor warning to their load-bearing lists.

Deliberately untouched:

  • packages/shared/src/i18n/locales/* and the public subscribe, unsubscribe and manage pages. Their copy is translated into 16 locales and editing English there would desync 15 of them.
  • The onboarding flows and the dashboard greeting, whose copy is already the voice everything else was moved toward.
  • console.error strings, which are developer-facing.

PRODUCT.md replaces the legacy .impeccable.md, with the register made explicit and a terminology section recording that user-facing nouns (Contact, Event, Campaign, Workflow, Template, Segment) track the API.

Typecheck and production build pass.

The copy across the dashboard was written screen by screen, so the same
concept was phrased several different ways and a lot of text explained
things the UI already said. This is a pass over every user-facing string
in apps/web against one standard, applied consistently.

Systemic patterns removed:

- 25 confirmation dialogs opened with "Are you sure you want to...", then
  repeated the question the title already asked. Titles now name the
  object ("Delete john@acme.com?"), bodies state only the consequence,
  and buttons are verb + object. Cancel dialogs previously rendered
  [Cancel] [Cancel Campaign]; the dismiss button now reads "Keep sending".
- 42 success toasts ended in "successfully". The toast is already green.
- 87 "Failed to X" strings gave no cause and no next step. Most sites
  already surfaced error.message and only used these as a fallback, so
  the fallbacks now name what did not happen and what to do.
- ~20 CardDescriptions restated their own CardTitle. Deleted. The ones
  carrying an actual rule were kept and sharpened instead.
- BillingConsumption, BillingInvoices and QuickStart each wrote their
  header 3-4 times across loading/error/empty branches. Hoisted to one
  header per component.
- 243 Title Case UI strings across 190 distinct labels moved to sentence
  case. The app previously shipped both "Send To" and "Send to".
- Required-field markers used three different mechanisms. Now one.
- Terminology: "API Credentials" and "API Keys" were the same card under
  two names; cancelled/canceled and .../… were both in use; the templates
  page title disagreed with its nav item.

Structural changes:

- Removed the analytics "Performance Insights" card. It dispensed advice
  the product cannot substantiate ("above industry average" against no
  cited benchmark, "add more compelling calls-to-action") in a product
  positioned against exactly that tone. Replaced with two counters drawn
  from real data: events triggered and workflow runs started.
- Subscription activation copy was ~75 words over two paragraphs. It is
  load-bearing (it prevents billing surprises), so it was restructured
  rather than cut: one summary line plus a "Why two charges?" disclosure.
- Consolidated the DKIM instructions that appeared both above and below
  the DNS record table.
- Trimmed the workflow active-executions notice and the HTML-to-visual
  editor warning to their load-bearing lists.

Deliberately untouched:

- packages/shared/src/i18n/locales/* and the public subscribe,
  unsubscribe and manage pages. Their copy is translated into 16 locales
  and editing English there would desync 15 of them.
- The onboarding flows and the dashboard greeting, whose copy is already
  the voice everything else was moved toward.
- console.error strings, which are developer-facing.

PRODUCT.md replaces the legacy .impeccable.md, with the register made
explicit and a terminology section recording that user-facing nouns
(Contact, Event, Campaign, Workflow, Template, Segment) track the API.

Typecheck and production build pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@driaug
driaug force-pushed the copy/clarify-web-app branch from 3f2cc49 to a62001e Compare August 10, 2026 18:57
@driaug
driaug merged commit 15ecf58 into next Aug 10, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant