Claude
Skills
Sign in
Back

nextjs-patterns

Included with Lifetime
$97 forever

Modern Next.js frontend development patterns with TypeScript, Tailwind CSS v4, shadcn/ui, TanStack Query, and Zustand

Design

What this skill does


# Next.js Frontend Development Patterns

This skill provides comprehensive guidance for building modern Next.js applications following production-ready patterns and best practices.

## Technology Stack

- **Next.js**: 14/15/16+ with App Router (NOT Pages Router)
- **React**: 18/19+ with Server and Client Components
- **TypeScript**: Strict mode with comprehensive typing
- **Styling**: Tailwind CSS v4 with utility-first approach
- **Components**: shadcn/ui (Radix UI primitives)
- **State Management**: Zustand with persist middleware
- **Data Fetching**: TanStack Query (React Query)
- **Validation**: Zod schemas
- **Package Manager**: pnpm preferred

## Core Principles

### 1. Server Components First

**By default, all components are Server Components**. Only add 'use client' when necessary:

✅ **Use Server Components for:**
- Pages that fetch data
- Static content
- Layouts
- Components that don't need interactivity

✅ **Use Client Components for:**
- Interactive elements (onClick, onChange, etc.)
- React hooks (useState, useEffect, etc.)
- Browser APIs (localStorage, window, etc.)
- Event listeners
- Third-party libraries that require client-side

**Example Server Component:**
```typescript
// app/(main)/page.tsx
import { HeroSection } from "@/components/hero-section";
import { FavoritesSection } from "@/components/main/favorites-section";

export default function Home() {
  return (
    <div className="min-h-screen bg-gradient-to-b from-orange-50/30 via-white to-red-50/20">
      <HeroSection />
      <FavoritesSection />
    </div>
  );
}
```

**Example Client Component:**
```typescript
// components/ui/button-with-state.tsx
'use client'

import { useState } from 'react'
import { Button } from '@/components/ui/button'

export function Counter() {
  const [count, setCount] = useState(0)

  return (
    <Button onClick={() => setCount(c => c + 1)}>
      Count: {count}
    </Button>
  )
}
```

### 2. The cn() Utility Pattern

**ALWAYS use the `cn()` utility for className management**:

```typescript
// lib/utils.ts (standard implementation)
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

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

**Usage patterns:**

```typescript
import { cn } from "@/lib/utils"

// Basic usage
<div className={cn("p-4 rounded-md", className)} />

// Conditional classes
<div className={cn(
  "base-class",
  isActive && "active-class",
  isDisabled && "disabled-class"
)} />

// Variant-based classes with props
<div className={cn(
  "base-class",
  variant === "primary" && "bg-primary text-white",
  variant === "secondary" && "bg-secondary text-gray-900"
)} />
```

### 3. Project Structure

```
src/
├── app/
│   ├── layout.tsx              # Root layout
│   ├── page.tsx                # Home page
│   ├── globals.css             # Global styles
│   ├── (main)/                 # Route group for main site
│   │   ├── layout.tsx
│   │   ├── page.tsx
│   │   ├── menu/
│   │   │   ├── page.tsx
│   │   │   └── components/     # Page-specific components
│   │   └── cart/
│   │       └── page.tsx
│   └── api/                    # API routes
│       ├── health/
│       │   ├── route.ts
│       │   └── __tests__/
│       │       └── route.test.ts
│       └── locations/
│           └── route.ts
├── components/
│   ├── ui/                     # shadcn/ui components
│   │   ├── button.tsx
│   │   ├── card.tsx
│   │   ├── dialog.tsx
│   │   └── __tests__/
│   ├── menu/                   # Feature-specific components
│   ├── cart/
│   └── providers/              # Context providers
├── hooks/                      # Custom React hooks
│   ├── use-categories.ts
│   ├── use-menu-items.ts
│   └── __tests__/
├── stores/                     # Zustand stores
│   ├── cart-store.ts
│   ├── location-store.ts
│   └── __tests__/
├── lib/
│   ├── utils.ts               # cn() and other utilities
│   ├── api/                   # API client functions
│   │   ├── types.ts
│   │   └── __tests__/
│   └── __tests__/
├── types/                     # TypeScript type definitions
│   └── tenant.ts
├── config/                    # App configuration
├── actions/                   # Server actions
└── styles/                    # Additional styles
```

**Key conventions:**
- Use route groups `(name)` for logical grouping without affecting URLs
- Co-locate tests with `__tests__/` directories
- Keep page-specific components near the page
- Use absolute imports with `@/` prefix

### 4. Component Patterns

#### A. shadcn/ui Button Component

```typescript
// 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 gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 cursor-pointer [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground shadow-sm hover:bg-primary/90",
        destructive: "bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90",
        outline: "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
        secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
        ghost: "hover:bg-accent hover:text-accent-foreground",
        link: "text-primary underline-offset-4 hover:underline",
      },
      size: {
        default: "h-9 px-4 py-2",
        sm: "h-8 rounded-md px-3 text-xs",
        lg: "h-10 rounded-md px-8",
        icon: "h-9 w-9",
      },
    },
    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 };
```

**Key patterns:**
- Use `class-variance-authority` for variant management
- Always use `React.forwardRef` for ref forwarding
- Export both component and variants
- Use `asChild` prop for polymorphic components
- Always use `cn()` for className merging

#### B. Extending shadcn/ui Components

```typescript
// components/ui/button.tsx (with loading state)
export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean;
  isLoading?: boolean;
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, asChild = false, isLoading, children, disabled, ...props }, ref) => {
    const Comp = asChild ? Slot : "button";
    return (
      <Comp
        className={cn(buttonVariants({ variant, size, className }))}
        ref={ref}
        disabled={disabled || isLoading}
        {...props}
      >
        {isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
        {children}
      </Comp>
    );
  }
);
```

### 5. Data Fetching Patterns

#### A. TanStack Query (Client-Side)

```typescript
// hooks/use-categories.ts
"use client";

import { useQuery } from "@tanstack/react-query";
import type { Category } from "@/lib/api/types";

export function useCategories(brandName?: string, locationSlug?: string, menuSlug?: string) {
  return useQuery<Category[]>({
    queryKey: ["categories", brandName,

Related in Design