This is a Next.js project bootstrapped with create-next-app.
First, run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun devOpen http://localhost:3000 with your browser to see the result.
You can start editing the page by modifying src/app/page.tsx. The page auto-updates as you edit the file.
npm test
# Watch mode
npm test -- --watchFile-based routing is a convention where the file and folder structure in your src/app directory automatically creates routes in your application. You don't need to manually configure routes—the structure itself defines them.
- Folders = Route Segments: Each folder in
src/apprepresents a URL segment - Special Files:
page.tsx- Creates a publicly accessible page at that routelayout.tsx- Wraps child routes with a shared layoutroute.ts- API endpointsnot-found.tsx- Custom 404 page
src/app/
├── page.tsx → "/" (Home page)
├── layout.tsx → Root layout wrapping all pages
├── not-found.tsx → Custom 404 page
├── globals.css → Global styles
Routes:
http://localhost:3000/- Home page
src/app/users/
├── page.tsx → GET /users (List users)
├── page.module.css → Scoped styles
└── api/
└── route.ts → API endpoints for users
└── [id]/
└── route.ts → GET /api/users/[id] (User by ID)
Routes:
http://localhost:3000/users- Users listing pageGET /api/users- Fetch all usersGET /api/users/:id- Fetch specific user by ID
src/app/products/
├── page.tsx → GET /products (List products)
├── page.module.css → Scoped styles
└── api/
└── route.ts → API endpoints for products
Routes:
http://localhost:3000/products- Products listing pageGET /api/products- Fetch all products
src/app/api/auth/
└── [...nextauth]/
├── auth-options.ts → NextAuth configuration
└── route.ts → NextAuth API route
Routes:
GET/POST /api/auth/signin- Sign inGET/POST /api/auth/callback/[provider]- OAuth callbacksGET /api/auth/session- Get session infoPOST /api/auth/signout- Sign out
src/app/login/
├── page.tsx → GET /login (Login page)
└── page.module.css → Scoped styles
Routes:
http://localhost:3000/login- Login page
Dynamic Route Segments use square brackets [paramName]:
[id]- Single dynamic segment[...slug]- Catch-all segment (matches multiple path segments)
Example:
/api/users/[id]/route.tsmatches/api/users/1,/api/users/2, etc./api/auth/[...nextauth]/route.tsmatches/api/auth/signin,/api/auth/callback/google, etc.
src/components/
├── core/ → Layout components
│ ├── auth-button.tsx → Authentication button
│ ├── navbar.tsx → Navigation bar
│ └── footer.tsx → Footer
├── users/ → User-specific components
│ ├── user-card.tsx → Display user info
│ └── email-mask.tsx → Email masking utility
└── products/ → Product-specific components
├── product-card.tsx → Display product
└── product-form.tsx → Product form
src/services/
├── users/
│ └── users-service.ts → User API calls
└── products/
└── products-service.ts → Product API calls
src/store/
├── store.ts → Redux/store configuration
├── store-provider.tsx → Store provider wrapper
├── users/
│ └── users-slice.ts → User state management
└── products/
└── products-slice.ts → Product state management
Tests mirror the source structure:
__tests__/
├── components/
│ ├── auth-button.test.tsx
│ ├── navbar.test.tsx
│ ├── footer.test.tsx
│ ├── user-card.test.tsx
│ ├── email-mask.test.tsx
│ └── __snapshots__/
├── pages/
│ ├── home.test.tsx
│ ├── login.test.tsx
│ ├── users.test.tsx
│ ├── not-found.test.tsx
│ └── __snapshots__/
├── services/
│ └── users-service.test.ts
├── store/
│ └── users-slice.test.ts
└── config/
└── mocks/
└── users-data.mock.ts
- Pages created just by adding
page.tsxfiles - Automatic URL generation based on folder structure
route.tsfiles create API endpoints- Support for HTTP methods (GET, POST, PUT, DELETE, etc.)
- Square bracket syntax
[paramName]for dynamic segments - Catch-all routes with
[...slug]for flexible matching
layout.tsxcreates shared UI across routes- Supports nested layouts for feature-based organization
not-found.tsxfor custom 404 pages- Error boundaries for handling runtime errors
This project demonstrates different rendering approaches in Next.js 13+:
Default in Next.js 13+ - Components are rendered on the server unless marked with "use client".
SSR Pages:
- Home Page (
src/app/page.tsx) ✅ SSR- No
"use client"directive - Static content rendered on server
- When: Initial page load, SEO optimization needed
- How: Rendered on server, HTML sent to browser
- No
Server Components Benefits:
- Access to databases, APIs, secrets directly
- Better SEO (complete HTML on first load)
- Reduced JavaScript sent to browser
- Secure operations without exposing credentials
Marked with "use client" directive - Components run in the browser.
CSR Pages:
-
Users Page (
src/app/users/page.tsx) ❌ CSR- Uses
"use client"directive - Uses Redux with
useAppDispatch&useAppSelector - Fetches user data with
useEffect - When: Interactive features, client-side state
- Pattern: Renders empty shell, loads data client-side
- Uses
-
Products Page (
src/app/products/page.tsx) ❌ CSR- Uses
"use client"directive - Uses Redux store, session, and state management
- Interactive form toggle with
useState - Fetches products with
useEffect - When: Complex interactions, user authentication
- Uses
-
Login Page (
src/app/login/page.tsx) ❌ CSR- Uses
"use client"directive - Uses
useSearchParams()for URL params - Interactive OAuth sign-in with
next-auth/react - When: Authentication flows, dynamic redirects
- Uses
CSR Components:
- AuthButton (
src/components/core/auth-button.tsx) ❌ CSR- Uses
"use client"directive - Uses
useSession()hook - Interactive sign-out functionality
- Uses
CSR Benefits:
- Rich interactivity and real-time updates
- Client-side state management (Redux)
- Dynamic user experiences
- No page reload for UI updates
API routes in src/app/api/ are always server-side:
GET /api/users- Fetch all users (server-side)GET /api/users/[id]- Fetch user by ID (server-side)GET /api/products- Fetch products (server-side)POST /api/products- Add products (server-side)POST /api/auth/[...nextauth]- Authentication (server-side)
src/app/layout.tsx ✅ SSR
- Server component (no
"use client") - Wraps all pages with providers
- Uses
StoreProvider(client wrapper) - Uses
AuthProvider(client wrapper) - Sets metadata for SEO
src/middleware.ts ✅ Server-Side
- Runs on every request
- Protects routes:
/usersand/api/users - Requires authentication via NextAuth
| Scenario | Choose |
|---|---|
| Static content, SEO critical | ✅ Server Component (SSR) |
| Interactive features, real-time updates | ❌ Client Component (CSR) |
| Using React hooks (useState, useEffect) | ❌ Client Component |
| Using session, auth features | ❌ Client Component |
| Accessing databases, secrets | ✅ Server Component |
| Handling form submissions | Both (Server action or API route) |
| Third-party OAuth | ❌ Client Component (for UI) |
Browser → useEffect() → Dispatch Redux Action
→ Fetch from API Route → Server fetches data
→ JSON response → Redux store update → Re-render
Server renders layout with Providers
→ Client-side components hydrate with state
→ Pages can be CSR or SSR
User clicks "Continue with Google"
→ Client-side: nextAuth signIn()
→ Server-side: NextAuth route handler
→ OAuth provider → Session created
→ Redirects to protected page
→ Middleware verifies session
✅ Intuitive Structure - Folder structure matches URL paths
✅ No Config Needed - Routes are automatic
✅ Co-location - Related files stay together
✅ Type-Safe - Full TypeScript support
✅ Scalable - Easy to add new routes
✅ SEO-Friendly - Clean URL structure
✅ Flexible Rendering - Mix SSR and CSR as needed
✅ Built-in Middleware - Route protection and auth
To learn more about Next.js file-based routing:
- Next.js App Router Documentation - Comprehensive guide to App Router
- File Conventions - Special file names and their purposes
- Routing Fundamentals - Core routing concepts
- Dynamic Routes - Using dynamic segments
- API Routes - Creating API endpoints
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.