Modern Next.js application with TypeScript, Tailwind CSS, and shadcn/ui components.
# Install dependencies
pnpm install
# Start development server
pnpm devOpen http://localhost:3000 to see the app.
webapp/
├── app/ # Next.js App Router (routes & pages)
│ ├── layout.tsx # Root layout - wraps all pages
│ ├── page.tsx # Home page (/) - Hello World with counter
│ ├── globals.css # Global styles + Tailwind directives
│ └── api/
│ └── health/
│ └── route.ts # GET /api/health endpoint
│
├── components/ # React components
│ └── ui/ # shadcn/ui components
│ ├── button.tsx # Button component with variants
│ └── card.tsx # Card component with subcomponents
│
├── lib/
│ └── utils.ts # Utilities (cn helper for class merging)
│
├── public/ # Static assets (served at /)
│ ├── fonts/ # Font files
│ └── *.svg # SVG images
│
├── package.json # Dependencies & scripts
├── tsconfig.json # TypeScript configuration
├── tailwind.config.ts # Tailwind CSS configuration
├── postcss.config.mjs # PostCSS configuration
├── components.json # shadcn/ui configuration
└── .eslintrc.json # ESLint configuration
The main page is a client component with a simple counter:
- Uses
'use client'directive for client-side interactivity - Imports shadcn/ui components (Card, Button)
- Manages counter state with React's
useState - Button increments counter on click
RESTful API endpoint following Next.js conventions:
- Exports async
GETfunction - Returns JSON:
{ ok: true, timestamp: "<ISO string>" } - Accessible at
/api/health
Root layout that wraps all pages:
- Defines metadata (title, description)
- Imports global CSS
- Provides HTML structure
shadcn/ui Philosophy:
- Components are added to your project (not npm packages)
- Full control over component code
- Built with Radix UI primitives
- Styled with Tailwind CSS
Key Components:
Button- Uses class-variance-authority for variantsCard- Composite component (Header, Title, Description, Content, Footer)
Tailwind Setup:
/* app/globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;CSS Variables:
- Theme colors defined as CSS custom properties
- Supports light/dark mode via
.darkclass - Accessed via
hsl(var(--variable-name))
Utility Function:
// lib/utils.ts
cn(...classes) // Merges Tailwind classes intelligentlypnpm dev # Start dev server (http://localhost:3000)
pnpm build # Build for production
pnpm start # Run production build locally
pnpm lint # Run ESLint| Layer | Technology | Why |
|---|---|---|
| Framework | Next.js 15 | React framework with App Router |
| Language | TypeScript | Type safety |
| Styling | Tailwind CSS | Utility-first CSS |
| Components | shadcn/ui | Accessible, customizable UI |
| Package Mgr | pnpm | Fast, efficient dependency manager |
| Version Mgr | Volta | Node/pnpm version pinning |
Next.js uses file-system routing in the app/ directory:
// app/about/page.tsx
export default function About() {
return <div>About Page</div>;
}
// Accessible at /about// app/api/users/route.ts
import { NextResponse } from 'next/server';
export async function GET() {
return NextResponse.json({ users: [] });
}
// Accessible at /api/users# Add a new component (e.g., input)
npx shadcn@latest add inputThis downloads the component to components/ui/input.tsx.
Volta ensures consistent Node.js and pnpm versions across environments.
Install Volta:
# macOS/Linux
curl https://get.volta.sh | bash
# Windows
# Download installer from volta.shAfter installation, Volta automatically uses versions specified in package.json:
"volta": {
"node": "20.18.2",
"pnpm": "10.28.0"
}Vercel (Recommended):
- Push to GitHub
- Import repository in vercel.com
- Deploy (auto-configured for Next.js)
Build Output:
- Static pages are pre-rendered
- API routes are serverless functions
- Client components are hydrated on the client
- Next.js App Router - Routing & layouts
- TypeScript - Type system
- Tailwind CSS - Utility classes
- shadcn/ui - Component documentation
- Volta - Version management