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

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. This guide uses a src/ directory, so answer Yes when it asks about using src/.

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: Processed as a PostCSS plugin during the Next.js build
  • Path Alias: Use @/* as shorthand for src/* paths
  • Theme System: CSS variable-based, light/dark mode support via @theme inline
  • shadcn/ui: Configured for RSC (rsc: true), ready to add components
  • App Router: Based on the Next.js App Router