Why
Dependabot keeps opening bumps for Tailwind (e.g. #2998, v3.4.19 → v4.3.1) because /web is on a v3 major. v3 is in maintenance mode — new features land in v4 only — so the longer we sit on it, the bigger the eventual forced-migration cliff.
We are not merging the bare dependabot PR (#2998) because a v3→v4 bump touches the config model and CSS entry syntax, and a package.json-only bump can pass CI while silently breaking rendered styles.
What it buys us
- CSS-first config that fits our existing token system.
web/app/globals.css is already a wall of CSS custom properties (--paper, --ink, --indigo, --ochre, …). v4 @theme lets those tokens become Tailwind utilities automatically, collapsing the tailwind.config.ts + CSS-variables duplication into one source of truth.
- Faster builds (Oxide/Rust engine) — single-digit-second full builds, snappy dev-server startup.
- Smaller CSS output — more aggressive tree-shaking.
- Stop the dependabot nag and shed the future-debt cliff.
What the migration entails (do NOT just bump package.json)
- CSS entry — replace the removed v3 directives:
/* v3 (current in web/app/globals.css) */
@tailwind base;
@tailwind components;
@tailwind utilities;
/* v4 */
@import "tailwindcss";
- PostCSS plugin — swap from
tailwindcss (v3 PostCSS plugin) to @tailwindcss/postcss in web/postcss.config.mjs.
- Config — move
tailwind.config.ts content into @theme blocks in CSS, or keep a @config pointer during transition.
- Audit
@apply / @layer usage across web/app and web/components — most survives, but edge cases (custom utilities, @layer ordering) need a visual pass.
- Eyeball the rendered site — the build can be green while styles silently no-op. This is the "sneaky floorboard" risk; a visual regression check is the real gate, not CI.
Related
Why
Dependabot keeps opening bumps for Tailwind (e.g. #2998, v3.4.19 → v4.3.1) because
/webis on a v3 major. v3 is in maintenance mode — new features land in v4 only — so the longer we sit on it, the bigger the eventual forced-migration cliff.We are not merging the bare dependabot PR (#2998) because a v3→v4 bump touches the config model and CSS entry syntax, and a
package.json-only bump can pass CI while silently breaking rendered styles.What it buys us
web/app/globals.cssis already a wall of CSS custom properties (--paper,--ink,--indigo,--ochre, …). v4@themelets those tokens become Tailwind utilities automatically, collapsing thetailwind.config.ts+ CSS-variables duplication into one source of truth.What the migration entails (do NOT just bump package.json)
tailwindcss(v3 PostCSS plugin) to@tailwindcss/postcssinweb/postcss.config.mjs.tailwind.config.tscontent into@themeblocks in CSS, or keep a@configpointer during transition.@apply/@layerusage acrossweb/appandweb/components— most survives, but edge cases (custom utilities,@layerordering) need a visual pass.Related