CodeVetter · Repo Unpack · System map
tailwindlabs/tailwindcss
The repo is a pnpm workspace (`pnpm-workspace.yaml`) orchestrated by Turborepo (`turbo.json`) layered over a Cargo workspace (`Cargo.toml`, `members = ["crates/*"]`). The compiler core lives in `packages/tailwindcss` and is pure TypeScript with no filesystem access — all IO is injected via `loadModule`/`loadStylesheet` callbacks. `@tailwindcss/node` is the Node IO adapter (enhanced-resolve + jiti + Lightning CSS), and `@tailwindcss/oxide` is the Rust scanner bridged through napi-rs. Six consumer packages (cli, postcss, vite, webpack, turbopack, browser, standalone) sit on top, and `@tailwindcss/upgrade` is a separate codemod CLI. There is no server or database; the storage layer is the filesystem plus in-memory LRU caches.
- `packages/tailwindcss/src/index.ts` exports the three public compiler entrypoints — `compile(css, opts)` (string→string), `compileAst(ast, opts)` (AST→AST, used by the PostCSS plugin), and `__unstable__loadDesignSystem` (used by IntelliSense and the upgrade tool) — plus a default export that throws a hard error if someone wires `tailwindcss` directly into PostCSS.
- The core compiler takes zero filesystem dependencies: `CompileOptions` declares `loadModule` and `loadStylesheet` callbacks that default to `throwOnLoadModule`/`throwOnLoadStylesheet`, which is what makes the same code run in Node, Bun, and the browser CDN build.
- `@tailwindcss/node` is the Node runtime boundary: it wires `enhanced-resolve` resolvers (separate `cssResolver` with `mainFields: ['style']`, `esmResolver`, and `cjsResolver` fallback), `jiti` for `.ts` plugin/config files, and `Module.registerHooks({ resolve: resolveSync })` so ESM config reloads work in watch mode.
- `crates/node/src/lib.rs` is the napi-rs bridge exposing the `Scanner` class (`scan()`, `scanFiles()`, `getCandidatesWithPositions()`, and `files`/`scannedFiles`/`globs`/`normalizedSources` getters) plus the `ChangedContent`, `GlobEntry`, and `SourceEntry` object shapes consumed by every JS integration.
- The Cargo workspace has four crates: `tailwindcss-oxide` (the scanner/extractor), `tailwind-oxide` (`crates/node`, the NAPI shim), `classification-macros` (a `ClassifyBytes` proc-macro deriving byte-class lookup tables for the extractor state machines), and a vendored fork of BurntSushi's `ignore` crate pinned to edition 2024.
- Build is `pnpm build` → `turbo build --filter=!./playgrounds/*`, followed by a `postbuild` hook that runs `scripts/pack-packages.mjs` to `pnpm pack` every non-private workspace into `dist/*.tgz` — the integration tests then install those tarballs.
- Test commands are split three ways: `pnpm test` runs `cargo test && vitest run`, `pnpm test:integrations` runs `vitest --root=./integrations`, and `pnpm test:ui` runs Playwright in both `tailwindcss` and `@tailwindcss/browser`.
- `turbo.json` gives `@tailwindcss/oxide#build` explicit `inputs` covering `../oxide/src/**/*` and `../Cargo.toml`, so touching Rust source correctly busts the Turbo cache for the native addon; it also passes `RUSTUP_HOME` through via `globalPassThroughEnv`.
- Deployment shape is npm publishing with provenance: `@tailwindcss/oxide` fans out into 12 platform-specific optionalDependencies (`napi.targets` includes `wasm32-wasip1-threads`), and `.github/workflows/release.yml` builds each target in a matrix then publishes with `id-token: write` for npm trusted publishing.
- `@tailwindcss/standalone` is built by Bun (`bun ./scripts/build.ts`) into seven single-file executables (linux/macos/windows × arm64/x64, glibc and musl), each SHA-256 checksummed; it is marked `private: true` so `pack-packages.mjs` skips it.
- Lightning CSS is the only output post-processor: `optimize()` in `@tailwindcss/node` runs `transform()` twice (so nesting-flattened adjacent rules get merged), pins browser targets to Safari/iOS 16.4, Firefox 128, Chrome 111, and uses `errorRecovery: true` with a warning filter for framework pseudo-classes like `::ng-deep` and `::v-deep`.
- pnpm patches three dependencies — `@napi-rs/cli`, `@parcel/watcher`, and `lightningcss` — specifically so Bun can statically analyze them when compiling the standalone binary.
- `playgrounds/` holds three manual smoke-test apps (vite + React, nextjs, v3) wired via root scripts `pnpm vite` and `pnpm nextjs`; the Vite one is a two-line config registering `@tailwindcss/vite` alongside `@vitejs/plugin-react`.