career/qwestly/2026-10-public-site-copy-and-design-system.md

Rebuilt the marketing site on the design system and shipped the approved homepage copy

Situation

qwestly.com is the top of the member funnel, and it had drifted from both the brand and the design system. The homepage still carried pre-pivot copy, and pages across the site hard-coded their own greys, shadows and fonts: 364 hex literals, 107 raw grey utilities and 54 bare white/black classes. The hero had two competing gold buttons, card headings used the display face the system reserves for page headings, and the company signup form on /hire showed white text on a light field, so hiring managers could not see what they typed.

What I did

  • Shipped the homepage copy Adam approved on October 1 (headline, five agent cards, an LLM comparison section, FAQ, SOC 2, metadata and a new share image), and matched the candidate signup page to it.
  • Aligned every public-site page to the design system: one gold action per page, card headings in the standard face, only shipped weights, semantic tokens instead of literals, library Card/Input components, and an open footer framed to the header's width. Ran four agents in parallel on disjoint page groups against one written brief, then reviewed and built the result myself.
  • Fixed the shared library at the source (qwestly-ui #88): a new --scrim token for modal backdrops across all four apps, plus three button and notice literals.
  • Deleted dead code (an unreachable /features page and its product components, four unused components) and recorded the copy problems on other pages in a ticket rather than rewriting copy without sign-off.
  • Updated the brand guide, copy instructions and DESIGN.md (counsel is live; font weights; the wide face).

PRs: public-site #166, candidate #1081, qwestly-ui #88. Asana: Homepage V1 update (1219043553720989); follow-up copy pass (1219091882809585).

  • Ran the rest of the October 1 copy across the app the same day it was approved: the second copy pass on both repos (candidate #1090, public-site #175), then the code that went with it, working Adam's 78-item code file against the code and answering his 16 open questions on the ticket (candidate #1094–#1098, #1101, #1102; public-site #178–#182; qwestly-agent #384, #385, #388; qwestly-ui pushed to main and pinned). Triage of all 78 items went to five read-only agents in parallel; each item came back done, held for Adam, or moved to another ticket, so no work was duplicated and 26 items turned out to be shipped already.
  • Replaced member-visible raw error text everywhere it appeared: a reply that fails or a dropped connection now shows approved words with a recovery button ("Edit your message" / "Reload the page"), and the member's text is kept; the agent sends an error code instead of the exception text (a contracts change first, then the pin). A failed document save now says so instead of showing a fabricated receipt. Fixed a red component test and the environment-dependent PostHog masking test that had been failing in other sessions' shells.
  • Filed the problems the triage found that were bigger than copy rather than fixing them quietly: the Preferences introductions switch not stopping introductions, nothing keeping a pitch from a member's current company, a dashboard pay read on the wrong timeout, a reply cut off at the output limit ending silently, and a missing Slack alert on support requests.

Result

Design-system adoption, measured on the merged branch (2026-10-02): hex literals 364 -> 316, raw grey utilities 107 -> 0, bare white/black 54 -> 1, and the ratchet baseline was lowered so they cannot creep back. What remains is illustration art, PostHog's survey defaults and third-party marks.

Funnel effect: pending until the release reaches production. The hero now has one gold action ("Join now"), and "Get my review" became the blue default, so watch both rates for a shift.

Metrics

Metric Baseline (date) Target Latest (date)
public-site literal hex colours 364 (2026-10-01) down, art only 316 (2026-10-02)
public-site raw grey ramp utilities 107 (2026-10-01) 0 0 (2026-10-02)
public-site bare white/black utilities 54 (2026-10-01) 0 1 (2026-10-02)
Homepage "Public site direct signup clicked" / homepage pageviews, 28 days to take at release hold or rise pending
Homepage "LinkedIn grade submitted" / homepage pageviews, 28 days to take at release hold or rise pending
/hire "Beta signup company success" per 28 days to take at release rise (form text was invisible) pending
candidate /signup "Signup completed" / /signup pageviews, 28 days to take at release hold or rise (sign-up screen copy changed) pending
Member-visible raw error text in chat 4 chat surfaces plus raw tool errors on /agent (2026-10-02) 0 0 in code (2026-10-02), unmeasured in production

How to measure

  • Token counts: in public-site on staging or main, run node packages/ui/scripts/check-token-adoption.mjs; it prints the three counts (scans src/, skips packages/, strips comments).
  • Funnel: PostHog (posthog skill), project public-site. For the 28 days before the production release and the 28 days after, count Public site direct signup clicked and LinkedIn grade submitted where $pathname is /, divided by $pageview on /. For /hire, count Beta signup company success. Exclude internal traffic as the existing dashboards do. Caveat: the copy and the button colours changed together, so the effect cannot be split between them.
  • Sign-up conversion (candidate app): PostHog, project candidate. Signup completed where $pathname is /signup, divided by $pageview on /signup, 28 days before and after the release that carries the new sign-up copy. Caveat: the same release also carries the chat error and receipt changes, so attribute the sign-up screen's words, not the whole release.
  • Raw error text: grep the four chat surfaces for a rendered error string (Error:, the SSE error message, Connection failed) on candidate and public-site staging; they render the shared notice instead. Spot-check in production by forcing a failure with the browser's network throttle (a dropped connection is the easy one).

Log

  • 2026-10-01: Baseline token counts taken; homepage copy implemented; site-wide alignment run.
  • 2026-10-02: public-site #166 and candidate #1081 merged to staging; qwestly-ui #88 merged. Token counts re-measured (316 / 0 / 1). Funnel baselines due at production release.
  • 2026-10-02: the rest of the October 1 copy and its code merged to staging across candidate, public-site, qwestly-agent, qwestly-ui and the contracts. Chat failure handling recorded as a first data point (raw error text on 4 surfaces in code, now 0); signup and homepage conversion baselines still due at the production release.