Tailwind Config for Monorepo Projects
Share Tailwind CSS configuration across monorepo packages with a preset-based approach, shared content paths, and consistent theme tokens.
Framework
Detailed Explanation
Tailwind in Monorepos
Monorepos (Turborepo, Nx, PNPM workspaces) need a strategy for sharing Tailwind config across packages.
The Preset Approach
Create a shared config package:
packages/
tailwind-config/
tailwind.config.js <- shared preset
package.json
ui/
tailwind.config.js <- extends preset
web/
tailwind.config.js <- extends preset
Shared Preset
// packages/tailwind-config/tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
brand: "#1a73e8",
accent: "#ff6b35",
},
fontFamily: {
sans: ["Inter", "ui-sans-serif", "system-ui"],
},
},
},
plugins: [
require("@tailwindcss/typography"),
],
};
Consuming the Preset
// apps/web/tailwind.config.js
const sharedConfig = require("@acme/tailwind-config");
module.exports = {
presets: [sharedConfig],
content: [
"./app/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
// Include shared UI package
"../../packages/ui/src/**/*.{js,ts,jsx,tsx}",
],
};
Content Path Scanning
The biggest gotcha in monorepos is content paths. Each app must scan:
- Its own source files
- Any shared packages that use Tailwind classes
Turborepo with Tailwind
In turbo.json, ensure tailwind.config.js is part of your build inputs:
{
"pipeline": {
"build": {
"inputs": ["src/**", "tailwind.config.*", "postcss.config.*"]
}
}
}
Tips
- Keep the preset minimal -- only shared design tokens
- Let each app extend for app-specific customization
- Use CSS variables for values that change between apps
Use Case
Use this approach when you have multiple applications or packages in a monorepo that need to share a consistent Tailwind design system.