Skip to main content

Tailwind v4 + shadcn/ui: Default SaaS Stack 2026

·StarterPick Team
tailwindshadcnuicsssaasnextjs2026

Tailwind CSS v4 + shadcn/ui: The Default SaaS UI Stack 2026

The SaaS UI conversation ended in 2024. Tailwind CSS and shadcn/ui became the default — not by mandate, but by adoption. Walk through any popular SaaS boilerplate's package.json in 2026: Tailwind and shadcn/ui are there. ShipFast, Supastarter, MakerKit, Bedrock, next-forge — all of them.

Then Tailwind v4 shipped. The configuration model changed fundamentally. shadcn/ui migrated. Boilerplates updated. This guide explains what changed, why it matters, and what you need to know for new SaaS projects in 2026.

TL;DR

Tailwind CSS v4 moves configuration from tailwind.config.js (JavaScript) to globals.css (CSS). The @theme directive replaces the config file; OKLCH replaces HSL for colors; the build engine is 3.5x faster for full builds and 8x faster for incremental. shadcn/ui has migrated fully — new projects initialize with Tailwind v4 by default. For existing v3 projects, the migration is non-breaking with an automated upgrade tool. For new SaaS projects in 2026, v4 is the starting point.

Key Takeaways

  • CSS-first configuration: tailwind.config.js is gone — all config now lives in globals.css via @theme
  • OKLCH color space: Replaces HSL. More perceptually uniform, better for accessible dark mode palettes
  • Performance: 3.5x faster full builds, 8x faster incremental builds (measured in milliseconds, not seconds)
  • shadcn/ui v4 compatibility: Full support — npx shadcn@latest init initializes with Tailwind v4, React 19, and tw-animate-css
  • Migration: Automated — npx @tailwindcss/upgrade@next handles most of the conversion automatically
  • Boilerplate status: All major Next.js SaaS starters updated to Tailwind v4 as of Q1 2026

What Changed in Tailwind CSS v4

CSS-First Configuration

The biggest paradigm shift: Tailwind v4 removes tailwind.config.js entirely. Configuration moves into your CSS file.

Before (Tailwind v3):

// tailwind.config.js
module.exports = {
  content: ["./src/**/*.{ts,tsx}"],
  theme: {
    extend: {
      colors: {
        brand: {
          50: "#f0f9ff",
          500: "#3b82f6",
          900: "#1e3a5f",
        },
      },
      fontFamily: {
        sans: ["Inter", "sans-serif"],
      },
    },
  },
  plugins: [require("@tailwindcss/typography")],
};

After (Tailwind v4):

/* globals.css */
@import "tailwindcss";
@import "@tailwindcss/typography";

@theme {
  --color-brand-50: oklch(97% 0.02 230);
  --color-brand-500: oklch(60% 0.15 230);
  --color-brand-900: oklch(25% 0.08 230);

  --font-family-sans: "Inter", sans-serif;
}

That's the entire configuration. One CSS file, no JavaScript build config. The @import "tailwindcss" replaces the old @tailwind base; @tailwind components; @tailwind utilities directives.

The @theme Directive

@theme is where you define your design tokens — colors, fonts, spacing, breakpoints. Everything you'd put in theme.extend in the config file:

@theme {
  /* Colors */
  --color-primary: oklch(60% 0.20 250);
  --color-primary-foreground: oklch(98% 0.01 250);
  --color-secondary: oklch(95% 0.02 250);
  --color-destructive: oklch(55% 0.22 25);

  /* Spacing scale extension */
  --spacing-18: 4.5rem;
  --spacing-88: 22rem;

  /* Typography */
  --font-family-display: "Cal Sans", "Inter", sans-serif;

  /* Breakpoints */
  --breakpoint-3xl: 1920px;
}

These variables become Tailwind utilities automatically:

  • --color-primarybg-primary, text-primary, border-primary
  • --spacing-18p-18, m-18, w-18
  • --font-family-displayfont-display

OKLCH Colors

Tailwind v4 adopts OKLCH as the color model. OKLCH is perceptually uniform — equal numeric steps in lightness look equal to the human eye (HSL doesn't guarantee this).

/* HSL (Tailwind v3 shadcn/ui) */
:root {
  --background: 0 0% 100%;           /* hsl(0, 0%, 100%) = white */
  --foreground: 222.2 84% 4.9%;      /* hsl(222, 84%, 5%) = near black */
  --primary: 221.2 83.2% 53.3%;      /* hsl(221, 83%, 53%) = blue */
}

/* OKLCH (Tailwind v4 shadcn/ui) */
:root {
  --background: oklch(1 0 0);         /* white */
  --foreground: oklch(0.14 0.04 250); /* near black, slight blue tint */
  --primary: oklch(0.60 0.20 250);    /* blue */
}

Why this matters for SaaS dark mode:

/* OKLCH dark mode is more predictable */
.dark {
  /* Lightness values invert cleanly */
  --background: oklch(0.10 0 0);     /* dark background */
  --foreground: oklch(0.97 0 0);     /* light text */
  --primary: oklch(0.70 0.18 250);   /* slightly lighter blue (not just inverted HSL) */
}

With HSL, generating accessible dark mode colors requires manual adjustment. With OKLCH, the perceptual uniformity means you can generate light/dark pairs more systematically.


shadcn/ui in 2026: The Migration

shadcn/ui migrated fully to Tailwind v4 in early 2026. New projects initialized with npx shadcn@latest init get:

✓ Tailwind CSS v4
✓ React 19 compatibility
✓ tw-animate-css (replaces tailwindcss-animate)
✓ OKLCH colors (in globals.css, not tailwind.config.js)
✓ data-slot attributes on every component
✓ Updated component registry (all components updated)

Initializing in 2026

# Create a new Next.js project
npx create-next-app@latest my-saas --typescript --tailwind --app

# Initialize shadcn/ui (automatically detects Tailwind v4)
npx shadcn@latest init

The CLI detects Tailwind v4 in your project and generates the appropriate v4 configuration. You don't manually choose v4 vs v3 — it reads your installed version.

What the Init Generates

/* globals.css — generated by shadcn/ui init for Tailwind v4 */
@import "tailwindcss";
@import "tw-animate-css";

@custom-variant dark (&:is(.dark *));

@theme inline {
  --radius-sm: calc(var(--radius) - 4px);
  --radius-md: calc(var(--radius) - 2px);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) + 4px);

  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  /* ... all shadcn tokens */
}

:root {
  --radius: 0.625rem;
  --background: oklch(1 0 0);
  --foreground: oklch(0.145 0 0);
  --primary: oklch(0.205 0 0);
  --primary-foreground: oklch(0.985 0 0);
  /* ... */
}

.dark {
  --background: oklch(0.145 0 0);
  --foreground: oklch(0.985 0 0);
  --primary: oklch(0.922 0 0);
  --primary-foreground: oklch(0.205 0 0);
  /* ... */
}

tw-animate-css: The Animation Change

The old tailwindcss-animate plugin is deprecated. Tailwind v4 replaces it with tw-animate-css — a pure CSS animation library that doesn't require a Tailwind plugin.

/* Old: tailwindcss-animate (v3) */
/* In tailwind.config.js: require("tailwindcss-animate") */
/* Used: animate-in, animate-out, fade-in-0, zoom-in-95 */

/* New: tw-animate-css (v4) */
@import "tw-animate-css";
/* Same classes still work — fully backward compatible */

For most SaaS apps, this change is invisible — animate-in, fade-in-0, slide-in-from-top-2 all still work. The import location moves from the config file to CSS.


Setting Up a SaaS Project with Tailwind v4 + shadcn/ui

Full setup from scratch:

# 1. Create Next.js app
npx create-next-app@latest my-saas \
  --typescript \
  --tailwind \
  --eslint \
  --app \
  --src-dir \
  --import-alias "@/*"

# 2. Initialize shadcn/ui
cd my-saas
npx shadcn@latest init

# Select: Default style, neutral base color, CSS variables: yes

# 3. Add components
npx shadcn@latest add button card input label badge

# 4. Add your brand colors to globals.css

Adding Brand Colors (v4 Pattern)

/* src/app/globals.css */
@import "tailwindcss";
@import "tw-animate-css";

@custom-variant dark (&:is(.dark *));

/* Override shadcn tokens with your brand */
:root {
  --primary: oklch(0.55 0.22 250);        /* your brand blue */
  --primary-foreground: oklch(0.98 0 0);   /* white text on primary */
  --radius: 0.5rem;                         /* your border radius */
}

.dark {
  --primary: oklch(0.70 0.18 250);         /* lighter for dark mode */
  --primary-foreground: oklch(0.10 0 0);   /* dark text on primary */
}

That's all you need to brand the entire shadcn/ui component library. Every button, badge, and link picks up --primary automatically.


Performance: The Build Speed Numbers

Tailwind v4's new Rust-based engine (Oxide) delivers:

ScenarioTailwind v3Tailwind v4Improvement
Full build~1,200ms~340ms3.5x faster
Incremental build~150ms~18ms8x faster
Cold start (CI)~2,100ms~580ms3.6x faster

For development, incremental rebuilds at 18ms are effectively instantaneous. Tailwind no longer feels like it's rebuilding on every save.


Migrating Existing SaaS Projects from v3

If you have an existing boilerplate on Tailwind v3:

# Run the automated upgrade tool
npx @tailwindcss/upgrade@next

# What it does:
# ✓ Installs Tailwind v4
# ✓ Removes tailwind.config.js
# ✓ Creates CSS configuration in globals.css
# ✓ Converts HSL colors to OKLCH
# ✓ Replaces tailwindcss-animate with tw-animate-css
# ✓ Updates shadcn/ui components (if detected)

Migration notes for SaaS codebases:

  1. Custom color tokens — If you've defined custom colors in tailwind.config.js, they're moved to @theme in CSS. The class names (bg-brand-500) remain unchanged.

  2. JIT content paths — The content array in tailwind.config.js is automatically inferred from your project structure in v4. You don't need to configure it.

  3. Plugin compatibility — Most popular Tailwind plugins have v4 versions. @tailwindcss/typography is the one you're most likely using — it's updated and imported via CSS (@import "@tailwindcss/typography") instead of the config file.

  4. shadcn/ui components — Run npx shadcn@latest diff to see which components have updates. Re-adding updated components (npx shadcn@latest add button) pulls the latest v4-compatible versions.


Why This Combination Won

Tailwind v4 + shadcn/ui won the SaaS UI battle for practical reasons:

No runtime overhead: Both are compile-time solutions. Tailwind generates static CSS. shadcn/ui copies components into your repo. Zero runtime cost.

Full ownership: shadcn/ui isn't a component library you import — it's components you own. Customize any component without fighting a library's API. Update when you want, not when the library releases.

Design system without the work: The combination gives you a consistent design system (shared tokens, consistent spacing, matching dark mode) without hiring a designer. The default aesthetic is professional enough to ship.

Ecosystem momentum: In 2026, every Next.js resource — YouTube tutorials, GitHub templates, Stack Overflow answers — assumes Tailwind + shadcn/ui. The shared vocabulary makes onboarding new developers faster.

The question for SaaS builders isn't "should I use Tailwind + shadcn/ui?" It's "which boilerplate that already has it configured should I start with?"


SaaS Boilerplate Tailwind v4 Support Status

As of March 2026, here's where major SaaS boilerplates stand:

BoilerplateTailwind v4shadcn/ui v4Status
next-forgeUpdated Q1 2026
ShipFastUpdated Q1 2026
SupastarterUpdated Q1 2026
MakerKitUpdated Q1 2026
BedrockUpdated Q1 2026
SvelteshipVia shadcn-svelteUpdated (shadcn-svelte v4)
create-t3-appUpdated Q1 2026

All major Next.js SaaS starters shipped Tailwind v4 updates in Q1 2026. When evaluating boilerplates, checking for v4 support is now a baseline — a starter still on v3 is a maintenance warning signal.


The Component Ecosystem in 2026

shadcn/ui's model — copy components into your repo — spawned an ecosystem of pre-built block libraries:

shadcn/ui blocks — Official pre-built page sections (dashboard layouts, login pages, settings pages). Added to the shadcn/ui registry in 2025, now includes 30+ production-ready blocks.

shadcnblocks.com — Community-maintained shadcn/ui sections. Marketing page heroes, feature sections, pricing tables, FAQs. Free tier covers the most-used components.

21st.dev — AI-generated shadcn/ui components. Describe what you want, get a component you can copy into your repo. Quality varies but useful for one-off custom components.

For SaaS builders, the practical workflow: start with next-forge or another boilerplate for the dashboard structure, use shadcn/ui blocks for marketing page sections, and copy custom components from shadcnblocks or 21st.dev as needed. You build your entire UI without writing component primitives from scratch.

Browse all boilerplates with shadcn/ui on StarterPick. Related: comparing shadcn/ui vs Mantine vs SaaS UI and the complete Next.js SaaS tech stack guide.

Comments