How it works
How the tailess plugin enumerates every class your ss() calls can produce and hands the list to Tailwind through its own @source inline safelist.
What Tailwind can see
Tailwind v4 generates CSS by scanning your source for literal class strings. It never runs your code, so a prefix joined to a utility at runtime is something it cannot know about.
// Tailwind scans for literal class strings and never runs your code,// so this concatenation is invisible to it."md:" + "text-2xl"The class lands on the element and there is no rule behind it. Your element is simply unstyled, with nothing in the console and nothing in the build log — which is where every hand-rolled version of this idea quietly fails.
The pipeline
The plugin closes that gap without asking Tailwind to change how it works. It reads your source, enumerates every class your ss() calls can produce, and hands the list to Tailwind through its own @source inline(...) safelist.
your source tailess plugin Tailwind─────────── ────────────── ────────ss({ md: "text-2xl" }) ──▶ scan + enumerate "md:text-2xl" │ ▼ node_modules/.cache/…/tailess.css @source inline("md:text-2xl") ──▶ .md\:text-2xl { … } │ your app.css ──▶ @import "…/tailess.css" (injected)Nothing in that path depends on your code being executed, only on it being read. What the list contains is therefore bounded by what the scanner can see at your call sites — the literals it reads and the ones it cannot.
Why this is reliable
Three details make this reliable rather than merely clever.
The list goes in a separate file, not inline
Tailwind re-reads @source inline(...) only when it rebuilds its compiler, and it only rebuilds when one of its own build dependencies changes. Your .tsx files are not dependencies — but an @imported stylesheet is.
Writing the list to a sidecar file makes every change a guaranteed rebuild trigger, which is what lets a brand-new class work without restarting the dev server. A class you delete loses its CSS too, instead of lingering forever.
Injection is scoped to real Tailwind entries
The plugin only touches a stylesheet that Tailwind actually emits utilities into — directly, or through a chain of relative @imports. Every other CSS file in your build comes out byte-identical.
A marker proves it is wired up
The plugin declares a custom property on the root element. In dev, the first time the runtime builds a prefixed class it checks for that marker and, if it is missing, prints exactly which line of config you have not added.
:root { --tailess: 1; }Dev only