# Extension points — tailwindlabs/tailwindcss

> Canonical page: https://codevetter.com/unpack/tailwindcss/extension-points

# Extension points — tailwindlabs/tailwindcss

Scanned commit 41d9cae8e53378d16087fcf359eb785c2fd42ce4 (2026-09-08). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

The system has three distinct extension tiers. Tier one is CSS-native: `@utility`, `@custom-variant`, and `@theme` register directly into the design system with no JS. Tier two is the JS plugin API, preserved wholesale from v3 in `compat/plugin-api.ts` and loaded via `@plugin`. Tier three is internal: the `Utilities` and `Variants` classes are plain registries with `static`/`functional` methods that core code and plugins call identically, and the upgrade tool has its own ordered `DEFAULT_MIGRATIONS` array. Adding a new template language to the scanner is a matter of one new pre-processor module plus one match arm.
- `Utilities` is the utility registry — `static(name, compileFn)` and `functional(name, compileFn, options)` push into a `DefaultMap<string, Utility[]>`, with a parallel `completions` map driving IntelliSense suggestions. — [packages/tailwindcss/src/utilities.ts#L94-L120](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/utilities.ts#L94-L120) [packages/tailwindcss/src/utilities.ts#L294-L400](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/utilities.ts#L294-L400)
- `Variants` is the variant registry, offering `static`, `functional`, and `fromAst(name, ast, designSystem)` (which powers `@custom-variant` with a body), and tracking `compounds`/`compoundsWith` bit flags that decide which variants may be composed with which. — [packages/tailwindcss/src/variants.ts#L41-L130](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/variants.ts#L41-L130)
- `@utility` is the CSS-native extension point: `createCssUtility(node)` turns the at-rule into a `(designSystem) => void` registration function, with explicit validation that functional utilities end in `-*` and that `@utility` is never nested. — [packages/tailwindcss/src/index.ts#L221-L256](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/index.ts#L221-L256) [packages/tailwindcss/src/utilities.ts](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/utilities.ts)
- `@custom-variant` registrations are topologically sorted before application via `topologicalSort(customVariantDependencies, { onCircularDependency })`, so variants may reference each other and circular references produce a rendered CSS error rather than a stack overflow. — [packages/tailwindcss/src/index.ts#L680-L705](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/index.ts#L680-L705) [packages/tailwindcss/src/utils/topological-sort.ts](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/utils/topological-sort.ts)
- `buildPluginApi` is the JS plugin extension surface, exposing `addBase`, `addVariant`, `matchVariant`, `addUtilities`, `matchUtilities`, `addComponents`, `matchComponents`, and a `theme()` accessor, with name validation that rejects non-single-class selectors and non-lowercase-leading utility names. — [packages/tailwindcss/src/compat/plugin-api.ts#L39-L80](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/compat/plugin-api.ts#L39-L80) [packages/tailwindcss/src/compat/plugin-api.ts#L266-L380](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/compat/plugin-api.ts#L266-L380)
- `@plugin` supports typed options passed as a declaration body — `CssPluginOptions` values are parsed from the declaration text into JSON primitives (`null`, `true`, numbers, comma-separated lists) before being handed to the plugin factory. — [packages/tailwindcss/src/compat/apply-compat-hooks.ts#L57-L90](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/compat/apply-compat-hooks.ts#L57-L90)
- `applyCompatibilityHooks` is the single seam where all v3 behavior is grafted on — it registers `darkModePlugin`, `registerContainerCompat`, `registerLegacyUtilities`, `registerScreensConfig`, and `registerThemeVariantOverrides`, keeping legacy concerns out of core. — [packages/tailwindcss/src/compat/apply-compat-hooks.ts#L1-L25](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/compat/apply-compat-hooks.ts#L1-L25) [packages/tailwindcss/src/compat/legacy-utilities.ts](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/compat/legacy-utilities.ts) [packages/tailwindcss/src/compat/container.ts](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/compat/container.ts)
- `DesignSystem.storage` is an explicit general-purpose extension slot — a `Record<symbol, unknown>` documented as requiring unique symbol keys to avoid collisions; the canonicalization code uses it via `prepareDesignSystemStorage` and `UTILITY_SIGNATURE_KEY`. — [packages/tailwindcss/src/design-system.ts#L60-L68](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/design-system.ts#L60-L68) [packages/tailwindcss/src/design-system.ts#L240-L250](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/tailwindcss/src/design-system.ts#L240-L250) [packages/@tailwindcss-upgrade/src/codemods/template/migrate.ts#L1-L12](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/%40tailwindcss-upgrade/src/codemods/template/migrate.ts#L1-L12)
- Adding a new template language to the scanner requires two edits: a new module in `crates/oxide/src/extractor/pre_processors/` re-exported from `mod.rs`, and a new extension arm in the `pre_process_input` match statement. — [crates/oxide/src/extractor/pre_processors/mod.rs](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/crates/oxide/src/extractor/pre_processors/mod.rs) [crates/oxide/src/scanner/mod.rs#L541-L562](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/crates/oxide/src/scanner/mod.rs#L541-L562)
- The extractor is itself a pluggable set of state machines all implementing the `Machine` trait — `ArbitraryPropertyMachine`, `ArbitraryValueMachine`, `NamedUtilityMachine`, `NamedVariantMachine`, `ModifierMachine`, `StringMachine`, and others — which `main.rs` can benchmark individually via `_run_machine::<T>`. — [crates/oxide/src/extractor/mod.rs#L8-L22](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/crates/oxide/src/extractor/mod.rs#L8-L22) [crates/oxide/src/extractor/machine.rs](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/crates/oxide/src/extractor/machine.rs) [crates/oxide/src/main.rs#L18-L48](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/crates/oxide/src/main.rs#L18-L48)
- The upgrade tool's template codemods are an ordered array `DEFAULT_MIGRATIONS: Migration[]` where each entry is `(designSystem, userConfig, rawCandidate) => string`; order is load-bearing, flagged by the inline comment that `migrateVariantOrder` must run before variant-modifying migrations. — [packages/@tailwindcss-upgrade/src/codemods/template/migrate.ts#L27-L46](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/%40tailwindcss-upgrade/src/codemods/template/migrate.ts#L27-L46)
- CSS-level codemods are a parallel, separately-composed pipeline in `codemods/css/` (`migrate-at-apply`, `migrate-at-layer-utilities`, `migrate-import`, `migrate-media-screen`, `migrate-preflight`, `migrate-tailwind-directives`, `migrate-theme-to-var`, `migrate-variants-directive`), each with a co-located test file. — [packages/@tailwindcss-upgrade/src/codemods/css/migrate.ts](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/%40tailwindcss-upgrade/src/codemods/css/migrate.ts) [packages/@tailwindcss-upgrade/src/codemods/css/migrate-at-layer-utilities.ts](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/%40tailwindcss-upgrade/src/codemods/css/migrate-at-layer-utilities.ts)
- The CLI command table is a literal dispatch in `run()` — `command === 'build'` and `command === 'canonicalize'` — with options merged from `build.options()` and `sharedOptions`, so a new subcommand means a module exporting `options()`/`handle()` plus one branch. — [packages/@tailwindcss-cli/src/index.ts#L30-L79](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/%40tailwindcss-cli/src/index.ts#L30-L79) [packages/@tailwindcss-cli/src/commands/help/index.ts](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/%40tailwindcss-cli/src/commands/help/index.ts)
- `internal-example-plugin` is a workspace package existing purely as a plugin-resolution fixture, consumed as a devDependency by `@tailwindcss/postcss` tests. — [packages/internal-example-plugin/package.json](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/internal-example-plugin/package.json) [packages/@tailwindcss-postcss/package.json](https://github.com/tailwindlabs/tailwindcss/blob/41d9cae8e53378d16087fcf359eb785c2fd42ce4/packages/%40tailwindcss-postcss/package.json)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
