So integrieren Sie ShadCN mit Next.js

Die Einrichtung einer modernen UI-Komponentenbibliothek sollte sich nicht anfühlen wie das Zusammenbauen von Möbeln ohne Anleitung. Wenn Sie mit Next.js 15 entwickeln und schöne, anpassbare Komponenten ohne die Black-Box-Frustration traditioneller Bibliotheken wollen, zeigt Ihnen dieser Leitfaden genau, wie Sie Shadcn UI in Ihr Projekt integrieren.
Dieser Artikel behandelt den kompletten Shadcn UI Next.js Setup-Prozess, von der initialen Projekterstellung über die Komponenteninstallation, Tailwind CSS-Konfiguration bis hin zur ordnungsgemäßen Dark Mode-Implementierung. Sie lernen, wie Sie häufige React 19-Kompatibilitätsprobleme vermeiden und ein produktionsreifes Komponentensystem einrichten, das Ihnen tatsächlich gehört.
Wichtige Erkenntnisse
- Shadcn UI kopiert Komponentenquellcode direkt in Ihr Projekt und gibt Ihnen vollständige Kontrolle über Eigentum und Anpassung
- Die CLI übernimmt Installation und Dependency-Management und macht die Einrichtung auch bei React 19-Kompatibilitätsüberlegungen unkompliziert
- Die Tailwind CSS-Integration ist nahtlos, mit eingebauter Theming-Unterstützung und Dark Mode-Implementierung
- Komponenten sind framework-agnostisch und funktionieren sowohl mit App Router als auch Pages Router in Next.js
Warum Shadcn UI für Ihr Next.js-Projekt wählen
Shadcn UI verfolgt einen grundlegend anderen Ansatz bei Komponentenbibliotheken. Anstatt eine Abhängigkeit zu installieren, die Sie nicht modifizieren können, kopiert Shadcn Komponentenquellcode direkt in Ihr Projekt. Das bedeutet, Sie erhalten:
- Vollständiges Eigentum an Ihren Komponenten - modifizieren Sie alles, jederzeit
- Tailwind-first Design, das sich nahtlos in Ihre bestehenden Styles integriert
- Null Runtime-Overhead - Komponenten sind nur Code in Ihrem Projekt
- Type Safety von Grund auf eingebaut
- Barrierefreiheit standardmäßig korrekt durch Radix UI-Primitive behandelt
Dieser Ansatz glänzt besonders mit Next.js 15’s App Router, wo Server-Komponenten und Client-Boundaries sorgfältiges Komponentendesign erfordern.
Voraussetzungen und initiale Einrichtung
Bevor Sie mit Ihrem Shadcn UI Next.js-Setup beginnen, stellen Sie sicher, dass Sie haben:
- Node.js 18.17 oder höher
- Einen Paketmanager (npm, pnpm, yarn oder bun)
- Grundlegende Vertrautheit mit React und Tailwind CSS
Erstellen Ihres Next.js 15-Projekts
Beginnen Sie mit der Erstellung eines neuen Next.js-Projekts mit TypeScript und Tailwind CSS:
npx create-next-app@latest my-app --typescript --tailwind --app
Wenn Sie dazu aufgefordert werden, wählen Sie diese Optionen:
- ✓ Would you like to use ESLint? Yes
- ✓ Would you like to use
src/
directory? Yes (empfohlen) - ✓ Would you like to customize the default import alias? No
Navigieren Sie zu Ihrem Projekt:
cd my-app
Installation und Konfiguration von Shadcn UI
Die Shadcn CLI übernimmt den größten Teil der schweren Arbeit für die Komponenteninstallation. Führen Sie den Initialisierungsbefehl aus:
npx shadcn@latest init
Sie sehen mehrere Konfigurationsaufforderungen:
- Style: Wählen Sie Ihren bevorzugten Stil (Default/New York)
- Base color: Wählen Sie aus verfügbaren Farbschemata
- CSS variables: Verwenden Sie Yes für bessere Theming-Unterstützung
Umgang mit React 19 Peer Dependencies
Wenn Sie npm mit React 19 verwenden, werden Sie auf Peer Dependency-Warnungen stoßen:
npm error code ERESOLVE
npm error ERESOLVE unable to resolve dependency tree
Die CLI wird Sie auffordern, eine Lösungsstrategie zu wählen:
? How would you like to proceed?
❯ Use --force
Use --legacy-peer-deps
Wählen Sie --legacy-peer-deps
für den sichersten Ansatz. Benutzer von pnpm, yarn oder bun sehen diese Warnungen nicht und können normal fortfahren.
Hinzufügen Ihrer ersten Komponenten
Mit initialisiertem Shadcn fügen Sie Komponenten über die CLI hinzu:
npx shadcn@latest add button card
Dieser Befehl:
- Lädt den Komponentenquellcode herunter
- Platziert ihn in
src/components/ui/
- Installiert alle erforderlichen Dependencies (wie Radix UI-Primitive)
- Aktualisiert Ihre Komponentenimporte
So sieht eine typische Shadcn Button-Komponente nach der Installation aus:
// src/components/ui/button.tsx
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline: "border border-input bg-background hover:bg-accent",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = "Button"
export { Button, buttonVariants }
Beachten Sie, wie die Komponente vollständig anpassbar ist - Sie können Varianten modifizieren, neue hinzufügen oder das Styling komplett ändern.
Konfiguration von Tailwind CSS für Shadcn
Shadcn UI funktioniert sowohl mit Tailwind CSS v3 als auch v4. Die CLI konfiguriert automatisch Ihre tailwind.config.js
während der Initialisierung. Das wird hinzugefügt:
// tailwind.config.js
module.exports = {
darkMode: ["class"],
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
],
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
},
},
plugins: [require("tailwindcss-animate")],
}
Aktualisieren Sie Ihre globals.css
Die CLI aktualisiert auch Ihre globals.css
mit CSS-Variablen für das Theming:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--primary: 221.2 83.2% 53.3%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96%;
--secondary-foreground: 222.2 84% 4.9%;
--muted: 210 40% 96%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96%;
--accent-foreground: 222.2 84% 4.9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 221.2 83.2% 53.3%;
--radius: 0.5rem;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
--primary: 217.2 91.2% 59.8%;
--primary-foreground: 222.2 84% 4.9%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 224.3 76.3% 94.1%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
Implementierung des Dark Mode mit next-themes
Für eine produktionsreife Dark Mode-Implementierung verwenden Sie next-themes, um Hydratationsprobleme zu vermeiden.
Installation von next-themes
npm install next-themes
Erstellen eines Theme Providers
Erstellen Sie src/components/theme-provider.tsx
:
"use client"
import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
import { type ThemeProviderProps } from "next-themes/dist/types"
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}
Aktualisieren Sie Ihr Root Layout
Modifizieren Sie src/app/layout.tsx
:
import { ThemeProvider } from "@/components/theme-provider"
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
</ThemeProvider>
</body>
</html>
)
}
Erstellen einer Theme Toggle-Komponente
"use client"
import { Moon, Sun } from "lucide-react"
import { useTheme } from "next-themes"
import { Button } from "@/components/ui/button"
export function ThemeToggle() {
const { setTheme, theme } = useTheme()
return (
<Button
variant="ghost"
size="icon"
onClick={() => setTheme(theme === "light" ? "dark" : "light")}
>
<Sun className="h-5 w-5 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-5 w-5 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span>
</Button>
)
}
Arbeiten mit React 19-Änderungen
React 19 führt mehrere Änderungen ein, die beeinflussen, wie Sie mit Shadcn-Komponenten arbeiten:
Vereinfachte ref-Behandlung
React 19 erlaubt das Übergeben von ref
als reguläre Prop und eliminiert die Notwendigkeit für forwardRef
in vielen Fällen:
// Alter Ansatz (React 18)
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, ...props }, ref) => {
return <input ref={ref} className={className} {...props} />
}
)
// Neuer Ansatz (React 19)
function Input({ className, ref, ...props }: InputProps & { ref?: React.Ref<HTMLInputElement> }) {
return <input ref={ref} className={className} {...props} />
}
Neue Form Hooks
React 19’s useActionState
und useFormStatus
Hooks funktionieren nahtlos mit Shadcn Form-Komponenten:
import { useActionState } from "react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
function ContactForm() {
const [state, formAction] = useActionState(async (prevState, formData) => {
// Server Action-Logik hier
const email = formData.get("email")
// Formular verarbeiten...
return { success: true }
}, { success: false })
return (
<form action={formAction}>
<Input name="email" type="email" required />
<Button type="submit">Submit</Button>
{state.success && <p>Danke für Ihr Abonnement!</p>}
</form>
)
}
Häufige Probleme und Lösungen
Build-Fehler mit Tailwind CSS
Wenn Sie nach der Einrichtung auf Build-Fehler stoßen, stellen Sie sicher, dass Ihre PostCSS-Konfiguration korrekt ist:
// postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
Komponentenstyling wird nicht angewendet
Überprüfen Sie, dass Ihre globals.css
in Ihr Root Layout importiert ist:
import "./globals.css"
TypeScript-Fehler mit Komponenten-Props
Stellen Sie sicher, dass Ihre tsconfig.json
die korrekten Pfade enthält:
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}
Best Practices für die Produktion
-
Anpassen des cn-Utilities: Die
cn
-Funktion inlib/utils.ts
führt Klassen intelligent zusammen. Erweitern Sie sie für Ihre spezifischen Bedürfnisse. -
Erstellen von Komponentenvarianten: Verwenden Sie CVA (class-variance-authority), um konsistente Komponentenvarianten in Ihrer Anwendung zu erstellen.
-
Bundle-Größe optimieren: Installieren Sie nur Komponenten, die Sie tatsächlich verwenden. Jede Komponente ist unabhängig.
-
Barrierefreiheit testen: Shadcn-Komponenten verwenden Radix UI-Primitive, die Barrierefreiheit behandeln, aber testen Sie immer mit Screenreadern.
-
Versionskontrolle: Da Komponenten in Ihr Projekt kopiert werden, committen Sie sie in die Versionskontrolle und verfolgen Sie Änderungen.
Fazit
Die Einrichtung von Shadcn UI mit Next.js gibt Ihnen ein modernes Komponentensystem, das Flexibilität mit Entwicklungsgeschwindigkeit ausbalanciert. Im Gegensatz zu traditionellen Komponentenbibliotheken besitzen Sie jede Zeile Code, können alles anpassen und sind nicht an die Design-Entscheidungen anderer gebunden.
Die Kombination aus Next.js 15’s App Router, React 19’s Verbesserungen und Tailwind CSS schafft eine mächtige Grundlage für den Bau moderner Webanwendungen. Mit Shadcns Ansatz, Komponenten zu kopieren anstatt sie als Dependencies zu installieren, erhalten Sie das Beste aus beiden Welten: schnelle Entwicklung und vollständige Kontrolle.
FAQs
Bei der Verwendung von npm mit React 19 müssen Sie das --legacy-peer-deps Flag während der Komponenteninstallation verwenden, aufgrund von Peer Dependency-Konflikten. Paketmanager wie pnpm, yarn und bun handhaben diese Dependencies eleganter und benötigen keine speziellen Flags. Das Endergebnis ist dasselbe, unabhängig davon, welchen Paketmanager Sie wählen.
Ja, Shadcn UI funktioniert sowohl mit App Router als auch Pages Router. Der Komponentencode selbst ist framework-agnostisch. Der Hauptunterschied liegt darin, wie Sie Provider wie den Theme Provider implementieren - im Pages Router würden Sie Ihre App in _app.tsx anstatt im Root Layout wrappen.
Da Shadcn Komponenten direkt in Ihr Projekt kopiert, können Sie sie wie jeden anderen Code modifizieren. Öffnen Sie die Komponentendatei in src/components/ui/, passen Sie die Tailwind-Klassen oder CVA-Varianten an und speichern Sie. Sie können auch die globalen Theme-Variablen in Ihrem CSS modifizieren, um Farben und Abstände über alle Komponenten hinweg zu ändern.
Nein, Sie sollten nur Komponenten installieren, wenn Sie sie benötigen. Jede Komponente ist unabhängig und enthält ihre eigenen Dependencies. Das hält Ihre Bundle-Größe minimal und Ihr Projekt organisiert. Verwenden Sie npx shadcn@latest add [component-name], um einzelne Komponenten bei Bedarf hinzuzufügen.
Da Komponenten in Ihr Projekt kopiert werden, werden sie nicht automatisch aktualisiert, wenn Shadcn neue Versionen veröffentlicht. Sie können manuell die Shadcn UI-Dokumentation auf Updates überprüfen und entweder den add-Befehl für spezifische Komponenten erneut ausführen oder Änderungen manuell anwenden. Das gibt Ihnen Kontrolle darüber, wann und wie Komponenten in Ihrem Projekt aktualisiert werden.