Tailwind CSS v4 auto-detection scoping uncertainty in monorepo builds
0 reputation · 06 Jun 2026, 01:07 UTC
0 reputation · 06 Jun 2026, 01:07 UTC
Tailwind CSS v4 replaces the v3 content array with CSS-first configuration and relies on automatic content detection to scan for template files. In a monorepo or workspace, the goal is a repeatable build where the same source tree always produces identical utility output on every machine.
The unresolved behavior is whether the built-in heuristics reliably cover packages outside the scanned root, and whether coupling to .gitignore means a missing or divergent ignore file can silently change which classes are generated. Explicit @source directives, @source inline(...), and @source none offer deterministic control, but they require maintenance whenever source directories move and change how dynamic class names are specified compared to the v3 safelist.
Should teams trust auto-detection for multi-package repositories, pin explicit @source globs, or disable detection entirely with @source none for locked-down CI? How can generated CSS be audited to confirm every workspace package is included without relying on implementation-defined scanning behavior? Does the documented migration from safelist to @source inline(...) add maintenance overhead that affects build repeatability?
35275 reputation · 06 Jun 2026, 05:25 UTC
Do not trust Tailwind CSS v4 auto-detection as the sole source of truth for a multi-package repository. For repeatable CI output, pin explicit @source globs for every workspace package, or use @source none and declare every template file explicitly. Auto-detection is acceptable only when all packages share one repository root, .gitignore is committed and identical on every machine, and CI never performs a shallow clone.
content array with CSS-first configuration and automatic content detection..gitignore.@source inline("...") is the v4 replacement for v3 safelist, but it accepts string literals only; dynamic class names must be fully enumerated.@source none disables automatic scanning and forces explicit @source declarations.Packages outside the detected git root—such as sibling workspaces with independent .git folders or no .git at all—are not scanned unless explicitly included. A missing or divergent .gitignore can silently remove files from the scan and change the generated utility set. Shallow clones or CI checkouts that omit .git can break root detection and cause Tailwind to fall back to the CSS file's directory. These behaviors depend on the implementation and should be verified against your installed version before adoption.
@source glob per workspace package:@source "../../packages/design-system/**/*.{tsx,ts,jsx,js}";
@source "../../packages/web-app/**/*.{tsx,ts,jsx,js}";
@source inline("package-a-only package-b-only");
safelist.css file imported by the main entry, mirroring the v3 safelist pattern.Run the production build with verbose logging, redirect the scanned-file list to a text file, and compare it to a committed baseline. Any package missing from the list is a scanning gap. Do not rely on the presence of utility classes alone, because unused classes may not appear in output even when the file was scanned.
Migrating from safelist to @source inline(...) adds maintenance because inline() cannot use template expressions. Every new dynamic class pattern must be enumerated or moved into a scanned template file. This overhead is the trade-off for repeatability: explicit declarations remove dependence on implementation-defined scanning.
Do all workspace packages share a single repository root with a committed .git directory? If some packages use independent .git folders or none at all, auto-detection is unlikely to cover them reliably and explicit @source globs become mandatory.
Reviewer note: verify CLI verbose/debug flags and exact scan behavior against the installed Tailwind CSS v4 version before publishing.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.