Tailwind CSS in Production · Capstone Case Studies
Capstone: A Tailwind Design System for Three Products
A company with three web apps (React, Vue and Laravel Blade) wants one consistent, accessible look built on Tailwind v4. Design the system.
Scenario
Example company: a 120-person software company sells three products with separate front ends: a React dashboard, a Vue customer portal and a Laravel marketing site. Each team styles independently with Tailwind; colours, buttons and spacing differ, dark mode exists in one product only, and an accessibility audit found contrast and focus problems everywhere. A rebrand is planned in six months.
Requirements
- One source of truth for design tokens, usable from all three stacks.
- Shared components where practical, consistent where not.
- Dark mode in every product, without a flash on load.
- Accessibility (WCAG 2.2 AA) built in, not bolted on.
- The rebrand must be a token change, not a rewrite.
Deliverables
- Token design and distribution.
- Component strategy across React, Vue and Blade.
- Dark mode and theming.
- Accessibility guardrails.
- Governance: preventing drift and upgrading safely.
Hints
- Tokens in
@themeare plain CSS, so every stack can import the same file. - Variants with complete class strings scale better than class concatenation.
- Make the right thing the easy thing: lint rules, templates and examples.
Draft each deliverable before revealing the model answer and rubric.
Further reading: Theme variables · Dark mode
Deliverables
Token design and distribution.
Model answer
A shared npm package (also vendored into the Laravel repo) exports tokens.css: an @theme block with semantic tokens (--color-primary, --color-surface, --color-text-muted, --color-danger, radii, shadows, fonts) built from a primitive palette. Each app's CSS does @import "tailwindcss"; @import "@acme/tokens/tokens.css";. Semantic names make the rebrand a change to primitive values only. Dark values live in the same file under a .dark selector overriding the CSS variables.
Rubric
Full marks: semantic tokens on top of primitives, one CSS file consumed by all stacks, dark values as variable overrides.
Component strategy across React, Vue and Blade.
Model answer
Define each component once as a class recipe: variants and sizes mapped to complete class strings (for example with cva-style objects in a shared JS package), consumed by thin React and Vue components; Blade components copy the same recipes (generated from the shared package at build time). Accessible behaviour comes from headless libraries (Radix/React Aria for React, Headless UI or Reka UI for Vue). A living style guide (Storybook) shows every variant with screenshots.
Rubric
Full marks: single source for variant classes, framework-specific thin wrappers, headless behaviour libraries, documented catalogue.
Dark mode and theming.
Model answer
Class-based dark mode via @custom-variant dark (&:where(.dark, .dark *)); so users can choose; an inline head script (or server-rendered class from a cookie) sets the theme before first paint; color-scheme set accordingly. Because components use semantic tokens (bg-surface, text-muted), most need no dark: classes at all; the variables change underneath.
Rubric
Full marks: user choice without flash, semantic tokens that switch values instead of duplicating every class.
Accessibility guardrails.
Model answer
Token palettes checked for contrast (text tokens at least 4.5:1 on their surfaces); a standard focus-visible ring in the button and link recipes; outline-hidden instead of outline-none when replacing outlines; motion-safe: for animations; sr-only labels for icon buttons enforced in components; axe checks in Storybook and CI; a keyboard test in the definition of done.
Rubric
Full marks: contrast verified at the token level, focus and motion built into recipes, automated and manual checks.
Governance: preventing drift and upgrading safely.
Model answer
Lint rules against arbitrary colours and fragment-built class names; Prettier's Tailwind plugin for class order; visual regression tests of the component catalogue; a design-system team owning the tokens package with semantic versioning and changelogs; Tailwind upgrades done in the shared package first (with the upgrade tool and screenshot diffs), then rolled out app by app.
Rubric
Full marks: automated enforcement, ownership and versioning, staged upgrades with visual checks.
Open in the app to mark lessons complete, take notes and track your progress.