When I was tasked to build a multi-tenant SaaS application using Next.js + Tailwind on a monorepo, the internet disappointed me. There was nothing solid out there on how to load a specific Tailwind preset for a specific tenant. This was the solution I came up with, hope this helps ;)
Full repository available here.
Final result for default, Reddit and Discord themed tenants using the exact same codebase with different environment variables!
Let's dive into it!
We will be starting with the official Next.js with Tailwind example repo. To clone the example, run the following command:
yarn create next-app --example with-tailwindcss with-tailwindcss-app`
Setup environment
Create a .env file and define a NEXT_PUBLIC_TENANT environment variable.
NEXT_PUBLIC_TENANT=reddit
Setup Tailwind Presets
Add a tailwind folder to the root of your project with the following structure.
.
└── tailwind
├── default
│ └── preset.js
├── reddit
│ └── preset.js
└── discord
└── preset.js
Presets take the exact same shape as the configuration in a tailwind.config.js file. Since presets are merged on top of the default, we only need to include the theme object.
// default preset.js
module.exports = {
theme: {
extend: {
colors: {
primary: "#2563EB",
},
},
},
};
Add a getPreset() helper function in the tailwind.config.js file
// tailwind.config.js
const getPreset = () => {
if (!process.env.NEXT_PUBLIC_TENANT)
return [require(`./tailwind/default/preset.js`)];
try {
return [
require(`./tailwind/${process.env.NEXT_PUBLIC_TENANT}/preset.js`),
];
} catch (err) {
return [require(`./tailwind/default/preset.js`)];
}
};
module.exports = {
presets: getPreset(),
content: [
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
};
You're almost there
Find and replace all text-blue-600 from index.tsx with text-primary
Yay
That's it! Restart the server when you change the value of NEXT_PUBLIC_TENANT to see the changes.
Note: The values of NEXT_PUBLIC_TENANT correspond to the folder names in ./tailwind

Oldest comments (0)