Published on

Tailwind Config for Packages in a Monorepo

Authors
  • Name
    Ripal & Zalak
    Twitter

Tailwind Config for Packages in a Monorepo

Configuring TailwindCSS in a monorepo setup can be challenging, especially when working with shared components and multiple apps. This guide provides practical solutions for managing Tailwind configurations effectively in a monorepo.


The Problem

In a monorepo using tools like Vite, React, TailwindCSS, and pnpm, Tailwind classes might not work for shared packages unless you add all file paths explicitly in the content array of each configuration file. This approach can be cumbersome and error-prone.


Best Practices for Tailwind Config in a Monorepo

1. Use a Shared Tailwind Preset

TailwindCSS presets allow you to define shared configurations, such as themes and plugins, in a centralized location.

Steps:

  1. Create a shared package for Tailwind configuration (e.g., packages/tailwind-config).

  2. Add tailwindcss and postcss as dependencies in the shared package:

    pnpm add tailwindcss postcss -w
    
  3. Create a tailwind.config.js file in the shared package:

    module.exports = {
      theme: {
        extend: {
          colors: {
            primary: '#1da1f2',
          },
        },
      },
      plugins: [],
    }
    
  4. Export the preset from package.json:

    {
      "name": "@your-org/tailwind-config",
      "main": "tailwind.config.js"
    }
    
  5. Use the preset in your apps/packages:

    // tailwind.config.js in an app or package
    const sharedConfig = require('@your-org/tailwind-config')
    
    module.exports = {
      presets: [sharedConfig],
      content: ['./src/**/*.{tsx,ts,jsx,js}'],
    }
    

2. Centralize Paths in a Global Config

You can define all relevant file paths for Tailwind's content property in a centralized location.

Steps:

  1. In the shared Tailwind package, include all relevant file paths:
    module.exports = {
      content: [
        '../../apps/**/src/**/*.{js,ts,jsx,tsx}',
        '../../packages/**/src/**/*.{js,ts,jsx,tsx}',
      ],
      theme: {},
      plugins: [],
    }
    
  2. Reference this global content in each app/package's tailwind.config.js file.

3. Import and Export Tailwind Configurations

If you prefer not to use presets, you can create a base configuration file and import it into other projects.

Steps:

  1. Create a shared Tailwind configuration file:
    // packages/tailwind-config/tailwind.config.js
    module.exports = {
      theme: {
        extend: {},
      },
      plugins: [],
    }
    
  2. Import this file in your app/package configurations:
    // apps/app1/tailwind.config.js
    module.exports = require('../../packages/tailwind-config/tailwind.config.js')
    

4. Handling Vite and Next.js Specifics

For Vite and Next.js, ensure that:

  1. Paths are Resolved Correctly:

    • In Vite, use the vite.config.js file to handle path resolutions.
  2. Next.js Transpile Packages:

    • Add the shared Tailwind package to the transpile list in next.config.js:
      module.exports = {
        experimental: {
          transpilePackages: ['@your-org/tailwind-config'],
        },
      }
      

Frequently Asked Questions

1. Why use a shared Tailwind preset?

A preset simplifies maintaining consistent theming and plugins across multiple projects without duplicating configurations.

2. Can I use Tailwind without a shared preset?

Yes, but you'll need to manage configurations individually for each project, which can become repetitive and error-prone.

3. Do I need to restart the development server after changes?

Yes, for changes in Tailwind configuration or presets to take effect, restart your development server.


By following these best practices, you can set up TailwindCSS in a monorepo efficiently, ensuring consistency and maintainability across all packages and apps.