Tailwind CSS in Production · Capstone Case Studies
Capstone: Postmortem — The Release That Broke Checkout Styling
Write the postmortem for a release in which payment buttons rendered unstyled and invisible on mobile for three hours.
Scenario
Example company: an online shop migrates its checkout to a new component library and upgrades Tailwind in the same release.
Timeline
- 10:00 Release deployed.
- 10:20 Conversion on mobile drops by 40%; desktop is normal.
- 11:30 Support reports "no Pay button" from phone users.
- 12:40 Root cause found; hotfix deployed at 13:05.
Facts
- The new
PayButtonbuilds classes as`bg-${brand}-600`from a theme prop. - The library's components live in
node_modules/@shop/ui, which Tailwind doesn't scan by default. - On mobile the button sat in a flex row with a long merchant name and was pushed off-screen.
- No visual tests at phone width; staging used a dev build with a broad safelist.
Deliverables
- Root causes and contributing factors.
- Why staging didn't catch it.
- Immediate fix.
- Long-term prevention.
Draft each deliverable before revealing the model answer and rubric.
Further reading: Detecting classes in source files · Upgrade guide
Deliverables
Root causes and contributing factors.
Model answer
- Fragment-built class names (
bg-${brand}-600) were never generated, so the button had no background (white text on white). 2) The UI library's source wasn't scanned (@sourcemissing), so other library classes were missing too. 3) On phones, a flex row withoutmin-w-0/shrink-0pushed the button off-screen. Contributing: two risky changes (library migration and Tailwind upgrade) in one release, no phone-width visual tests, and staging configured differently from production.
Rubric
Full marks: all three technical causes plus process factors.
Why staging didn't catch it.
Model answer
Staging ran a development build with a broad safelist that generated the missing classes, so it didn't match production. Tests ran on desktop widths only and checked functionality (clicks via test IDs), not visibility. The release combined changes, so the diff was too large to review visually.
Rubric
Full marks: environment parity, missing visual and mobile tests, batch size.
Immediate fix.
Model answer
Roll back (or hotfix): map brands to complete class strings, add @source "../node_modules/@shop/ui";, add min-w-0 to the merchant name and shrink-0 to the button; verify on real phones before re-deploying; monitor mobile conversion back to baseline.
Rubric
Full marks: restores service quickly and verifies on mobile.
Long-term prevention.
Model answer
Production-identical builds in staging (no safelist differences); visual regression tests of checkout at 360px and desktop; a CI check that fails when key elements are off-screen or have no computed background; lint against fragment-built classes; release library migrations and framework upgrades separately behind a feature flag with a canary; alert on per-device conversion drops.
Rubric
Full marks: parity, visual and mobile tests, lint, smaller releases with canaries, device-level alerting.
Open in the app to mark lessons complete, take notes and track your progress.