
Nextjs Shadcn
Scaffold and extend Next.js App Router apps with shadcn/ui while keeping Server Components default and client boundaries minimal.
Overview
nextjs-shadcn is an agent skill for the Build phase that defines Next.js App Router and shadcn/ui architecture, server-client boundaries, and folder conventions.
Install
npx skills add https://github.com/laguagu/claude-code-nextjs-skills --skill nextjs-shadcnWhat is this skill?
- Server vs client decision tree: default Server Components; use client only at the smallest leaf boundary
- Discourages useEffect when Server Components, Server Actions, or event handlers suffice
- Serializable props rule: plain data or Server Actions—no functions or classes across the boundary
- Opinionated app/ tree: (protected), (public), actions/, api/, shared components/ui and ai/ for agents
- Tailwind v4 globals.css theme variables preferred over hardcoded design tokens
- Route groups: (protected) and (public)
- Dedicated ai/ directory for tools, agents, and prompts
Adoption & trust: 572 installs on skills.sh; 42 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your Next.js repo is turning into a forest of use client files, non-serializable props, and misplaced shadcn components.
Who is it for?
Indie SaaS and content apps on Next.js App Router using shadcn/ui who want agents to mirror a single architectural north star.
Skip if: Pages Router-only legacy apps, mobile-native stacks, or teams that do not use shadcn/Tailwind.
When should I use this skill?
Building or refactoring Next.js App Router UIs with shadcn/ui and strict server-client boundaries.
What do I get? / Deliverables
The app follows a consistent App Router layout with minimal client islands, shared ui/ primitives, and Server Actions wired for agent-friendly feature work.
- Consistent app/ and components/ directory layout
- Server-first page and leaf client component patterns
- Theme-aligned globals.css using Tailwind v4 variables
Recommended Skills
Journey fit
Frontend architecture decisions—folders, Server Actions, and shadcn placement—belong in Build when the product UI is taking shape. Focuses on React/Next UI structure and Tailwind theme usage, not API design, SEO campaigns, or production monitoring.
How it compares
Architecture and boundary rules for Next + shadcn—not a component catalog generator or deployment skill.
Common Questions / FAQ
Who is nextjs-shadcn for?
Solo developers building Next.js frontends with shadcn/ui who want Claude, Cursor, or Codex to respect Server Components and folder conventions.
When should I use nextjs-shadcn?
During Build (frontend) when creating app routes, shared UI, auth-gated areas, or AI features; especially before large agent-driven refactors that tend to add unnecessary use client.
Is nextjs-shadcn safe to install?
It provides structural coding guidance only; check the Security Audits panel on this page for the skill package before install.
SKILL.md
READMESKILL.md - Nextjs Shadcn
# Architecture ## Best Practices - Avoid `useEffect` - prefer Server Components, Server Actions, or event handlers - `"use client"` only at leaf components (smallest boundary) - Props must be serializable (data or Server Actions, no functions/classes) - Prefer Tailwind v4 `globals.css` theme variables over hardcoded values ## Component Patterns ### Server vs Client Decision Tree ``` Need state/effects/browser APIs? ├── Yes → "use client" at smallest boundary └── No → Server Component (default) Passing data to client? ├── Functions/classes → ❌ Not serializable ├── Plain objects/arrays → ✅ Props └── Server logic → ✅ Server Actions ``` ### Component Placement ``` app/ ├── (protected)/ # Auth required routes │ ├── dashboard/ │ ├── settings/ │ ├── components/ # Route-specific components │ └── lib/ # Route-specific types/utils ├── (public)/ # Public routes │ ├── login/ │ └── register/ ├── actions/ # Server Actions (global) ├── api/ # API routes components/ # Shared across routes ├── ui/ # shadcn primitives └── shared/ # Business components hooks/ # Custom React hooks lib/ # Shared utilities data/ # Database queries ai/ # AI logic (tools, agents, prompts) ``` ### AI Directory Structure When building AI applications, organize the `ai/` directory: ``` ai/ ├── model-names.ts # Model definitions & DEFAULT_MODEL_NAME ├── actions/ # AI-related server actions │ ├── model.ts # saveModelId, getModelId (cookie-based) │ └── chat.ts # Chat-related actions ├── utils.ts # findSources, getLastUserMessageText, etc. ├── agents/ # Agent definitions (if using agents) │ └── assistant.ts └── tools/ # Tool definitions (if using tools) ``` **model-names.ts example:** ```ts export interface Model { id: string label: string description: string } export const models: Model[] = [ { id: "gpt-5.4-mini", label: "GPT 5.4 mini", description: "Fast, lightweight tasks" }, { id: "gpt-5.4", label: "GPT 5.4", description: "Complex, multi-step tasks" }, ] export const DEFAULT_MODEL_NAME = "gpt-5.4-mini" ``` **Cookie-based model storage:** ```ts // ai/actions/model.ts - Server Action for MUTATION only "use server" import { cookies } from "next/headers" export async function saveModelId(model: string) { const cookieStore = await cookies() cookieStore.set("model-id", model) } // ❌ WRONG: Don't use Server Action for reading data // export async function getModelId() { ... } // ✅ CORRECT: Read cookies directly in Server Component // page.tsx import { cookies } from "next/headers" export default async function Page() { const cookieStore = await cookies() const modelId = cookieStore.get("model-id")?.value ?? DEFAULT_MODEL_NAME return <Chat modelId={modelId} /> } ``` ### className Pattern Always accept and merge `className`: ```tsx import { cn } from "@/lib/utils" interface CardProps extends React.HTMLAttributes<HTMLDivElement> { variant?: "default" | "outline" } export function Card({ className, variant = "default", ...props }: CardProps) { return ( <div className={cn( "rounded-lg p-4", variant === "outline" && "border", className )} {...props} /> ) } ``` ## Data Fetching Patterns ### Server Component (default) Fetch data directly in Server Components: ```tsx export default async function Page() { const data = await fetchData() return <Component data={data} /> } ``` ### Cached Data Function Use `'use cache'` for reusable cached queries: ```tsx // data/products.ts export async function getProducts() {