Version 3 of the kit: - Radix UI replaced with Base UI (using the Shadcn UI patterns) - next-intl replaces react-i18next - enhanceAction deprecated; usage moved to next-safe-action - main layout now wrapped with [locale] path segment - Teams only mode - Layout updates - Zod v4 - Next.js 16.2 - Typescript 6 - All other dependencies updated - Removed deprecated Edge CSRF - Dynamic Github Action runner
236 lines
7.9 KiB
Plaintext
236 lines
7.9 KiB
Plaintext
---
|
|
status: "published"
|
|
label: "Tailwind CSS"
|
|
title: "Tailwind CSS Configuration | Next.js Supabase SaaS Kit"
|
|
order: -1
|
|
description: "Configure Tailwind CSS 4, extend the design system, and customize styles across your Makerkit monorepo application."
|
|
---
|
|
|
|
Makerkit uses Tailwind CSS 4 with Shadcn UI for styling. All style configuration lives in `apps/web/styles/`, with the main entry point at `globals.css`. This guide covers how to customize Tailwind, add new packages to the content paths, and extend the design system.
|
|
|
|
## Style File Structure
|
|
|
|
The styling system uses these files in `apps/web/styles/`:
|
|
|
|
```
|
|
apps/web/styles/
|
|
├── globals.css # Main entry point, imports everything
|
|
├── theme.css # Theme color variables (light/dark mode, :root/.dark)
|
|
├── shadcn-ui.css # Maps CSS variables to Tailwind's @theme inline
|
|
├── makerkit.css # Makerkit-specific component styles
|
|
└── markdoc.css # Content/documentation styles
|
|
```
|
|
|
|
## Tailwind CSS 4 Configuration
|
|
|
|
Tailwind CSS 4 uses CSS-based configuration instead of JavaScript. The `@theme inline` directive in `shadcn-ui.css` maps your CSS variables to Tailwind design tokens:
|
|
|
|
```css title="apps/web/styles/shadcn-ui.css"
|
|
@theme inline {
|
|
--color-background: var(--background);
|
|
--color-foreground: var(--foreground);
|
|
--color-primary: var(--primary);
|
|
--color-primary-foreground: var(--primary-foreground);
|
|
|
|
/* Border radius */
|
|
--radius-sm: calc(var(--radius) - 4px);
|
|
--radius-md: calc(var(--radius) - 2px);
|
|
--radius-lg: var(--radius);
|
|
|
|
/* Font families */
|
|
--font-sans: -apple-system, BlinkMacSystemFont, var(--font-sans-fallback);
|
|
--font-heading: var(--font-sans);
|
|
}
|
|
```
|
|
|
|
The actual color values are defined in `theme.css` using oklch format (see [Theme Colors](/docs/next-supabase-turbo/customization/theme)).
|
|
|
|
These tokens become available as Tailwind utilities: `bg-primary`, `text-foreground`, `rounded-lg`, etc.
|
|
|
|
## Adding Content Paths for New Packages
|
|
|
|
When you create a new package in the monorepo, Tailwind needs to know where to scan for class names. Add a `@source` directive in `apps/web/styles/globals.css`:
|
|
|
|
```css title="apps/web/styles/globals.css"
|
|
@import 'tailwindcss';
|
|
@import 'tw-animate-css';
|
|
|
|
/* local styles */
|
|
@import './theme.css';
|
|
@import './shadcn-ui.css';
|
|
@import './markdoc.css';
|
|
@import './makerkit.css';
|
|
|
|
/* content sources - update the below if you add a new path */
|
|
@source '../../../packages/*/src/**/*.{ts,tsx}';
|
|
@source '../../../packages/features/*/src/**/*.{ts,tsx}';
|
|
@source '../../../packages/billing/*/src/**/*.{ts,tsx}';
|
|
@source '../../../packages/plugins/*/src/**/*.{ts,tsx}';
|
|
@source '../../../packages/cms/*/src/**/*.{ts,tsx}';
|
|
@source '../{app,components,config,lib}/**/*.{ts,tsx}';
|
|
|
|
/* Add your new package here */
|
|
@source '../../../packages/your-package/src/**/*.{ts,tsx}';
|
|
```
|
|
|
|
The `@source` directive is the Tailwind CSS 4 replacement for the `content` array in the old `tailwind.config.ts`.
|
|
|
|
## Custom Utility Classes
|
|
|
|
Add custom utilities using the `@utility` directive in `makerkit.css` or a new CSS file:
|
|
|
|
```css title="apps/web/styles/makerkit.css"
|
|
@utility container {
|
|
@apply mx-auto px-4 lg:px-8 xl:max-w-[80rem];
|
|
}
|
|
```
|
|
|
|
Or add utilities in a `@layer`:
|
|
|
|
```css
|
|
@layer utilities {
|
|
.text-balance {
|
|
text-wrap: balance;
|
|
}
|
|
|
|
.scrollbar-hidden {
|
|
-ms-overflow-style: none;
|
|
scrollbar-width: none;
|
|
}
|
|
|
|
.scrollbar-hidden::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Extending the Theme
|
|
|
|
Add custom design tokens in `shadcn-ui.css` inside the `@theme inline` block:
|
|
|
|
```css title="apps/web/styles/shadcn-ui.css"
|
|
@theme inline {
|
|
/* ... existing tokens ... */
|
|
|
|
/* Custom colors */
|
|
--color-brand: var(--brand);
|
|
--color-brand-light: var(--brand-light);
|
|
}
|
|
```
|
|
|
|
Then define the values in `theme.css`:
|
|
|
|
```css title="apps/web/styles/theme.css"
|
|
:root {
|
|
--brand: oklch(65% 0.2 250);
|
|
--brand-light: oklch(85% 0.1 250);
|
|
}
|
|
```
|
|
|
|
Use these in your components:
|
|
|
|
```tsx
|
|
<div className="bg-brand text-brand-light">
|
|
Content
|
|
</div>
|
|
```
|
|
|
|
## Component-Level Styles
|
|
|
|
For complex component styles, use `@layer components` in `makerkit.css`:
|
|
|
|
```css title="apps/web/styles/makerkit.css"
|
|
@layer components {
|
|
.card-hover {
|
|
@apply transition-all duration-200;
|
|
@apply hover:shadow-lg hover:-translate-y-0.5;
|
|
}
|
|
|
|
.btn-gradient {
|
|
@apply bg-gradient-to-r from-primary to-accent;
|
|
@apply text-primary-foreground;
|
|
@apply hover:opacity-90 transition-opacity;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Shadcn UI Component Customization
|
|
|
|
Override Shadcn component styles by targeting their classes:
|
|
|
|
```css title="apps/web/styles/shadcn-ui.css"
|
|
@layer components {
|
|
/* Custom button variants */
|
|
.btn-primary-gradient {
|
|
@apply bg-gradient-to-r from-blue-600 to-indigo-600;
|
|
@apply hover:from-blue-700 hover:to-indigo-700;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Dark Mode Utilities
|
|
|
|
Create dark-mode-aware utilities using the `dark:` variant:
|
|
|
|
```css
|
|
@layer utilities {
|
|
.glass {
|
|
@apply bg-white/80 backdrop-blur-sm;
|
|
@apply dark:bg-neutral-900/80;
|
|
}
|
|
|
|
.surface-elevated {
|
|
@apply bg-white shadow-sm;
|
|
@apply dark:bg-neutral-800 dark:shadow-none;
|
|
}
|
|
}
|
|
```
|
|
|
|
The dark variant is configured in `theme.css` as:
|
|
|
|
```css
|
|
@custom-variant dark (&:is(.dark *));
|
|
```
|
|
|
|
## Common Mistakes
|
|
|
|
**Missing content paths**: New packages won't have their Tailwind classes compiled if you forget to add a `@source` directive. Styles will appear missing in production even if they work in development.
|
|
|
|
**Using `@apply` excessively**: Reserve `@apply` for reusable component patterns. For one-off styles, use utility classes directly in JSX. Excessive `@apply` increases CSS bundle size.
|
|
|
|
**Forgetting `@layer` directives**: Custom styles without `@layer` can have specificity issues. Always wrap custom styles in `@layer base`, `@layer components`, or `@layer utilities`.
|
|
|
|
**Hardcoding colors**: Use theme variables (`bg-primary`, `text-foreground`) instead of hardcoded colors (`bg-blue-500`). This ensures consistency and makes theme changes easier.
|
|
|
|
## Verification
|
|
|
|
After modifying Tailwind configuration:
|
|
|
|
1. Restart the dev server (Tailwind config changes require a restart)
|
|
2. Run `pnpm build` to verify all classes compile correctly
|
|
3. Check production build for missing styles: `pnpm build && pnpm start`
|
|
4. Verify dark mode works for any new utilities
|
|
|
|
```bash
|
|
# Quick verification commands
|
|
pnpm dev # Development server
|
|
pnpm build # Production build (catches missing content paths)
|
|
pnpm typecheck # Type checking
|
|
```
|
|
|
|
{% faq
|
|
title="Frequently Asked Questions"
|
|
items=[
|
|
{"question": "Why are my Tailwind classes not working in production?", "answer": "The most common cause is missing @source directives in globals.css. Add your package path as a @source directive and rebuild. Classes must exist in scanned files to be included in the production CSS bundle."},
|
|
{"question": "How do I add a completely custom color?", "answer": "Define the CSS variable in theme.css (:root block), e.g. --brand: oklch(65% 0.2 250). Then map it in shadcn-ui.css inside @theme inline: --color-brand: var(--brand). Use it as bg-brand or text-brand in your components."},
|
|
{"question": "Should I use @apply or inline utilities?", "answer": "Prefer inline utilities for most cases. Use @apply only for frequently repeated patterns that need to stay in sync. Inline utilities are more explicit and easier to maintain."},
|
|
{"question": "How do I override Shadcn component styles?", "answer": "Add overrides in shadcn-ui.css within @layer components. Target the specific component classes or create variant classes. You can also pass className props to override individual instances."}
|
|
]
|
|
/%}
|
|
|
|
## Next Steps
|
|
|
|
- Back to [Customization Overview](/docs/next-supabase-turbo/customization)
|
|
- Configure your [theme colors](/docs/next-supabase-turbo/customization/theme) for brand consistency
|
|
- Set up [custom fonts](/docs/next-supabase-turbo/customization/fonts) for typography
|
|
- Choose your [layout style](/docs/next-supabase-turbo/customization/layout-style) for navigation |