Open-Source Wikis

/

Tailwind CSS

/

How to contribute

/

Development workflow

tailwindlabs/tailwindcss

Development workflow

A typical session.

1. Get the repo building

git clone https://github.com/tailwindlabs/tailwindcss
cd tailwindcss
pnpm install
rustup default stable
rustup target add wasm32-wasip1-threads
pnpm build

The pnpm build step is required at least once: it compiles the Rust crate into a Node addon (@tailwindcss/oxide), bundles every TypeScript package with tsup, and runs scripts/pack-packages.mjs to emit installable tarballs into dist/ for the integration tests.

2. Pick a package and run it in watch mode

The fastest dev loop depends on which package you're touching:

You're working on… Use this
The compiler (packages/tailwindcss) pnpm tdd (Vitest watch)
The CLI pnpm --filter @tailwindcss/cli dev
The Vite plugin pnpm vite (drives playgrounds/vite)
The Next.js example pnpm nextjs
The browser build pnpm --filter @tailwindcss/browser dev
The Rust scanner cargo watch -p tailwindcss-oxide -x test (if cargo-watch is installed)

pnpm dev at the root spins up turbo dev across all packages but skips the playgrounds.

3. Write a failing test

Pick the closest existing test file:

  • Compiler bug touching at-rule semantics → add to packages/tailwindcss/src/index.test.ts.
  • Specific utility behavior → add to packages/tailwindcss/src/utilities.test.ts.
  • Variant logic → packages/tailwindcss/src/variants.test.ts.
  • Scanner extraction shape → crates/oxide/src/extractor/*_machine.rs tests at the bottom of each file.
  • Scanner walking/source detection → crates/oxide/tests/scanner.rs.
  • Upgrade tool codemod → next to the codemod, e.g. packages/@tailwindcss-upgrade/src/codemods/css/migrate-at-apply.test.ts.
  • Integration / real-bundler regression → integrations/<bundler>/.

The test files use Vitest with expect.toMatchInlineSnapshot() heavily. Run with --update to refresh snapshots:

pnpm test -- --update

4. Implement the fix

Code conventions are enforced by Prettier (semi: false, singleQuote: true, printWidth: 100) and prettier-plugin-organize-imports. Don't fight the import sorter — saves time later.

For TypeScript, types are checked via tsc --noEmit per package. There is no JS emit; bundling happens through tsup.

For Rust, formatting is rustfmt (configuration in crates/node/rustfmt.toml).

5. Run the local test suite

pnpm test                    # cargo test + vitest run
pnpm lint                    # prettier --check + per-package tsc

If your change crosses the JS/Rust boundary, also run integration tests:

pnpm build                   # rebuild dist/ tarballs
pnpm test:integrations

If your change can affect browser CSS resolution (custom properties, color-mix, @property), run the UI tests too:

pnpm test:ui

The UI test suites run via Playwright (packages/tailwindcss/playwright.config.ts, packages/@tailwindcss-browser/playwright.config.ts).

6. Document the change

Edit CHANGELOG.md under ## [Unreleased], in either ### Added, ### Fixed, or ### Changed. Match the existing style: a single-line bullet ending with a (#PR) link.

7. Open the PR

The pull request template (.github/PULL_REQUEST_TEMPLATE.md) asks for:

  • A description of the change.
  • A test plan.
  • Confirmation that tests pass.

Maintainers are auto-assigned via .github/CODEOWNERS.

Tips

  • Don't add new dependencies casually. Most packages have very few runtime dependencies (the compiler package has none). New deps need a justification.
  • Use the playgrounds for sanity checks, but don't commit changes to them as part of your PR unless they're testing your fix.
  • The compiler has zero runtime deps. That's intentional — it has to work in browser bundles via @tailwindcss/browser.
  • patches/ is sacred. The @parcel/watcher and lightningcss patches exist so the Bun-built standalone CLI can statically analyze them. If you bump those packages, re-verify the patches.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Development workflow – Tailwind CSS wiki | Factory