A modern monorepo setup using pnpm workspaces with Svelte, Storybook, and Tailwind CSS v4.
svelte-storybook-tailwind-monorepo/
├── apps/
│ ├── main-app/ # SvelteKit application
│ └── storybook/ # Storybook application
└── packages/
├── ui/ # Svelte component library
└── tailwind-theme/ # Custom Tailwind v4 theme package
The @some-org/tailwind-theme package provides:
Theme Package (packages/tailwind-theme/):
@theme directive with custom CSS variables@source scanning for all UI packagesComponent Library (packages/ui/):
bg-brand-600)Applications (apps/main-app/, apps/storybook/):
# Install dependencies
pnpm install
# Start main app
pnpm run dev:main-app
# Start Storybook
pnpm run dev:storybook
# Build all packages
pnpm run build:packages
packages/tailwind-theme/src/theme.css)@theme {
/* Custom colors */
--color-brand-500: #3b82f6;
--color-brand-600: #2563eb;
/* ... more variables */
}
/* Centralized source scanning */
@source '../../*/src/**/*.{svelte,js,ts}';
/* Exclude test and config files for better performance */
@source not '../../*/src/**/*.test.{js,ts}';
@source not '../../*/src/**/*.spec.{js,ts}';
@source not '../../*/src/**/*.config.{js,ts}';
@source not '../../*/src/**/*.d.ts';
apps/main-app/src/app.css)@import "tailwindcss";
@import "@some-org/tailwind-theme/theme.css";
@plugin '@tailwindcss/forms';
@plugin '@tailwindcss/typography';
The Problem: Utility classes work fine when used directly (<div class="bg-brand-500">), but components from UI packages don't get theme styles applied.
The Root Cause: Without @source, Tailwind only scans the current app's files. It never discovers classes used in your UI package components, so those utility classes are never generated.
The Solution: The @source directive tells Tailwind to scan additional file paths for class names.
const variantClasses = {
primary: "bg-brand-600 text-white hover:bg-brand-700",
};
/* Include all component files */
@source '../../*/src/**/*.{svelte,js,ts}';
/* Exclude non-component files for better performance */
@source not '../../*/src/**/*.test.{js,ts}';
@source not '../../*/src/**/*.spec.{js,ts}';
@source not '../../*/src/**/*.config.{js,ts}';
@source not '../../*/src/**/*.d.ts';
Benefits:
@theme directive doesn't work from imported packagesSolution: Import the theme CSS directly, not as a JavaScript plugin
Solution: Use @source directive with correct relative paths to scan UI packages
Solution: Centralize all @source directives in the theme package using glob patterns
Solution: Use @source not to exclude test files, config files, and type definitions
The current setup automatically scans all packages matching packages/*/src/**/*.{svelte,js,ts}.
To add a new UI package:
packages/your-ui-package/@import '@some-org/tailwind-theme/theme.css';bg-brand-500, text-brand-900, etc.No additional configuration needed!
Issue: Utility classes like bg-brand-500 work directly but UI package components have no styles.
Diagnosis:
# Check if @source directive is present
grep -r "@source" packages/tailwind-theme/src/
# Verify CSS generation
pnpm run build:packages
# Look for your component classes in the generated CSS
Solution: Ensure @source directive includes your UI package paths.
Issue: Tailwind builds are slow in large monorepos.
Solution: Add exclusions for non-component files:
@source not '../../*/src/**/*.test.{js,ts}';
@source not '../../*/src/**/*.config.{js,ts}';
@source not '../../*/src/**/*.d.ts';
Issue: Some utility classes disappear after production builds.
Common Causes:
bg-${color}-500 won't workSolution: Use complete class names and verify @source coverage.
Key Changes:
tailwind.config.js with CSS @theme directive@source instead of content arraypnpm run dev:main-app - Start main applicationpnpm run dev:storybook - Start Storybookpnpm run build:main-app - Build main applicationpnpm run build:storybook - Build Storybookpnpm run build:packages - Build all packagespnpm run lint - Lint all packagespnpm run format - Format all packages