Fixing Tailwind Culling in Monorepos

A practical pattern for preventing Tailwind from culling classes in shared monorepo components.

Dec 13, 2025

When using Tailwind CSS v4 in a monorepo with shared React component packages, you may hit a subtle issue where classes in shared components are not added to your computed CSS file.

This happens because Tailwind only generates CSS for utility classes it can statically detect in the files it scans. If a consuming application only scans its own source code, any classes defined inside a shared package are invisible to Tailwind and get culled from the final build.

Importing the component is not enough — Tailwind does not follow imports at runtime.

The Solution

Treat shared UI packages as first-class Tailwind citizens.

  1. Shared component packages build their own CSS containing the utilities they use

  2. Consuming applications scan both their own code and shared packages

This guarantees Tailwind sees every class, regardless of where it’s defined.

Implementation Specifics

Step 1: Configure the Shared Component Package

Your shared package should explicitly generate its own Tailwind output.

packages/ui-components/postcss.config.js

export default {
  plugins: {
    '@tailwindcss/postcss': {
      content: ['./src/**/*.{js,jsx,ts,tsx}'],
    },
  },
}

packages/ui-components/src/styles.css

@import "tailwindcss";

packages/ui-components/package.json

{
  "scripts": {
    "build": "tsc && postcss src/styles.css -o dist/styles.css"
  },
  "exports": {
    "./styles.css": "./dist/styles.css"
  }
}

This produces a dist/styles.css file containing all utilities required by the shared components.

At this point, your UI package fully owns its styling.

Step 2: Configure Consuming Applications

The consuming app must scan both its own code and the shared package, whether it’s linked locally or installed from node_modules.

packages/app/postcss.config.js

export default {
  plugins: {
    '@tailwindcss/postcss': {
      content: [
        './src/**/*.{js,jsx,ts,tsx}',

        // Local workspace development
        '../ui-components/src/**/*.{js,jsx,ts,tsx}',
        '../ui-components/dist/**/*.{js,jsx,d.ts}',

        // Installed package (CI / production)
        './node_modules/@company/ui-components/**/*.{js,jsx,ts,tsx}',
      ],
    },
  },
}

This ensures Tailwind detects classes regardless of how the package is resolved.

Step 3: Build in the Correct Order

Because the app depends on generated CSS from the shared package, build order matters.

yarn workspace @company/ui-components build
yarn workspace @company/app build

Monorepo tooling can enforce this automatically (more on that below).

A note on the paths

Each path covers a different stage of the development lifecycle:

  • ui-components/src – Local workspace development

  • ui-components/dist – TypeScript output and generated artifacts

  • node_modules/@company/ui-components – Published package in CI or production

This redundancy is intentional. It eliminates environment-specific styling bugs.