Back to Blog

Setting Up Tailwind CSS v4 + shadcn/ui in Next.js from Scratch

(edited: March 29, 2026)

Uses pnpm or npm with TypeScript.

1. Create Project

Bash
npx create-next-app@latest my-project --typescript --eslint --app
cd my-project

When create-next-app asks about Tailwind CSS, select No. We will set up v4 manually.

2. Install Packages

Tailwind CSS v4 (PostCSS Method)

Next.js uses the PostCSS plugin instead of the Vite plugin.

pnpm:

Bash
pnpm add tailwindcss @tailwindcss/postcss postcss

npm:

Bash
npm install tailwindcss @tailwindcss/postcss postcss

shadcn/ui Required Dependencies

pnpm:

Bash
pnpm add class-variance-authority clsx tailwind-merge lucide-react

npm:

Bash
npm install class-variance-authority clsx tailwind-merge lucide-react

Node.js Type Definitions

pnpm:

Bash
pnpm add -D @types/node

npm:

Bash
npm install -D @types/node

3. Create Files

postcss.config.mjs

Tauri uses the Vite plugin (@tailwindcss/vite), but Next.js uses the PostCSS plugin.

JAVASCRIPT
const config = {
  plugins: {
    "@tailwindcss/postcss": {},
  },
};

export default config;

src/app/globals.css

Based on the Next.js App Router, write this in src/app/globals.css.

CSS
@import "tailwindcss";

:root {
  --background: oklch(1 0 0);
  --foreground: oklch(0.1450 0 0);
  /* ... other CSS variables */
}

.dark {
  --background: oklch(0.1450 0 0);
  --foreground: oklch(0.9850 0 0);
  /* ... dark mode variables */
}

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  /* ... theme variable mappings */
}

src/lib/utils.ts

TYPESCRIPT
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

components.json

Differences from the Tauri setup: rsc is true, and the CSS path is src/app/globals.css.

JSON
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "config": "",
    "css": "src/app/globals.css",
    "baseColor": "slate",
    "cssVariables": true,
    "prefix": ""
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils",
    "ui": "@/components/ui",
    "lib": "@/lib",
    "hooks": "@/hooks"
  },
  "iconLibrary": "lucide"
}

4. Modify Files

tsconfig.json

JSON
{
  "compilerOptions": {
    // ... existing settings
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

If created with create-next-app, the @/* alias may already be configured.

src/app/layout.tsx

TYPESCRIPT
import type { Metadata } from "next";
import "./globals.css";

export const metadata: Metadata = {
  title: "My App",
  description: "Next.js + Tailwind CSS v4 + shadcn/ui",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

src/app/page.tsx

TYPESCRIPT
export default function Home() {
  return (
    <div className="flex items-center justify-center min-h-screen">
      <h1 className="text-4xl font-bold">Hello, Next.js + Tailwind v4</h1>
    </div>
  );
}

5. Adding shadcn/ui Components

Bash
npx shadcn@latest add button
npx shadcn@latest add card
# Add any components you need...

Or initialize everything at once with shadcn init:

Bash
npx shadcn@latest init

Components are automatically generated in the src/components/ui/ folder.

6. Differences from Tauri Setup

ItemTauri (Vite)Next.js
Tailwind Integration@tailwindcss/vite (Vite plugin)@tailwindcss/postcss (PostCSS plugin)
Config FileAdd plugin in vite.config.tsCreate separate postcss.config.mjs
CSS File Locationsrc/index.csssrc/app/globals.css
Entry PointImport CSS in src/main.tsxImport CSS in src/app/layout.tsx
RSC Supportfalse (client-only)true (React Server Components)
tailwind.config.jsNot required (v4)Not required (v4)

7. Key Features

  • Tailwind CSS v4: CSS-first configuration, no tailwind.config.js needed
  • PostCSS Integration: Seamlessly integrates with Next.js build pipeline
  • Path Alias: Use @/* as shorthand for src/* paths
  • Theme System: CSS variable-based, light/dark mode support via @theme inline
  • shadcn/ui: RSC compatible, component library ready to use
  • App Router: Based on Next.js 15 App Router architecture

Comments