Featured

Next.js Complete Guide: From Beginner to Expert with Code Structure

T
Team
·25 min read
#nextjs#react#web development#framework#tutorial#beginner guide

Next.js Complete Guide: From Beginner to Expert with Code Structure


Next.js has become the go-to framework for building production-ready React applications. This comprehensive guide will take you from absolute beginner to expert level, covering everything you need to know about Next.js with practical code examples and best practices.


Table of Contents


1. [Getting Started (Beginner)](#getting-started)

2. [Core Concepts](#core-concepts)

3. [Routing & Navigation](#routing--navigation)

4. [Data Fetching](#data-fetching)

5. [Styling & UI](#styling--ui)

6. [Optimization (Intermediate)](#optimization)

7. [Advanced Patterns (Expert)](#advanced-patterns)

8. [Production Code Structure](#production-code-structure)

9. [Deployment & Performance](#deployment--performance)


---


Getting Started (Beginner)


What is Next.js?


Next.js is a React framework that provides:

  • Server-Side Rendering (SSR) - Render pages on the server
  • Static Site Generation (SSG) - Pre-render pages at build time
  • API Routes - Build backend APIs alongside your frontend
  • File-based Routing - Automatic routing based on file structure
  • Built-in Optimizations - Image optimization, code splitting, and more

  • Installation


    bash
    1# Create a new Next.js app
    2npx create-next-app@latest my-app
    3 
    4# Or with TypeScript
    5npx create-next-app@latest my-app --typescript
    6 
    7# Or with specific options
    8npx create-next-app@latest my-app --typescript --tailwind --app

    Project Structure (Basic)


    text
    1my-app/
    2├── app/ # App Router (Next.js 13+)
    3│ ├── layout.js # Root layout
    4│ ├── page.js # Home page
    5│ └── globals.css # Global styles
    6├── public/ # Static files
    7├── next.config.js # Next.js configuration
    8└── package.json # Dependencies

    Your First Page


    javascript
    1// app/page.js
    2export default function Home() {
    3 return (
    4 <div>
    5 <h1>Welcome to Next.js!</h1>
    6 <p>This is your first page.</p>
    7 </div>
    8 );
    9}

    ---


    Core Concepts


    Pages vs App Router


    Next.js offers two routing systems:


    Pages Router (Traditional)

    text
    1pages/
    2├── index.js # Home page (/)
    3├── about.js # About page (/about)
    4└── blog/
    5 └── [slug].js # Dynamic route (/blog/:slug)

    App Router (Next.js 13+)

    text
    1app/
    2├── page.js # Home page (/)
    3├── about/
    4│ └── page.js # About page (/about)
    5└── blog/
    6 └── [slug]/
    7 └── page.js # Dynamic route (/blog/:slug)

    Server Components vs Client Components


    Server Component (Default)

    javascript
    1// app/components/ServerComponent.js
    2// Runs on the server - no 'use client' directive
    3export default function ServerComponent() {
    4 // Can directly access databases, APIs, etc.
    5 const data = fetch('https://api.example.com/data');
    6
    7 return <div>{/* Rendered on server */}</div>;
    8}

    Client Component

    javascript
    1// app/components/ClientComponent.js
    2'use client'; // Required for client-side interactivity
    3 
    4import { useState } from 'react';
    5 
    6export default function ClientComponent() {
    7 const [count, setCount] = useState(0);
    8
    9 return (
    10 <button onClick={() => setCount(count + 1)}>
    11 Count: {count}
    12 </button>
    13 );
    14}

    ---


    Routing & Navigation


    Basic Routing


    javascript
    1// app/about/page.js
    2export default function About() {
    3 return <h1>About Page</h1>;
    4}

    Dynamic Routes


    javascript
    1// app/blog/[slug]/page.js
    2export default function BlogPost({ params }) {
    3 return <h1>Blog Post: {params.slug}</h1>;
    4}

    Nested Dynamic Routes


    javascript
    1// app/shop/[...slug]/page.js
    2// Matches /shop, /shop/a, /shop/a/b, etc.
    3export default function Shop({ params }) {
    4 return <div>Shop: {params.slug.join('/')}</div>;
    5}

    Navigation


    javascript(21 lines, showing 15)
    1'use client';
    2 
    3import Link from 'next/link';
    4import { useRouter } from 'next/navigation';
    5 
    6export default function Navigation() {
    7 const router = useRouter();
    8
    9 return (
    10 <nav>
    11 {/* Client-side navigation */}
    12 <Link href="/about">About</Link>
    13 <Link href="/blog/post-1">Blog Post</Link>
    14
    15 {/* Programmatic navigation */}

    Route Groups


    javascript
    1// app/(marketing)/about/page.js
    2// app/(marketing)/contact/page.js
    3// app/(shop)/products/page.js
    4// Groups don't affect URL structure

    ---


    Data Fetching


    Server Components - Direct Fetching


    javascript(16 lines, showing 15)
    1// app/posts/page.js
    2export default async function Posts() {
    3 // Fetch data directly in Server Component
    4 const res = await fetch('https://api.example.com/posts', {
    5 cache: 'no-store' // Always fetch fresh data
    6 });
    7 const posts = await res.json();
    8
    9 return (
    10 <ul>
    11 {posts.map(post => (
    12 <li key={post.id}>{post.title}</li>
    13 ))}
    14 </ul>
    15 );

    Caching Strategies


    javascript
    1// Time-based revalidation
    2fetch(url, { next: { revalidate: 3600 } }); // Revalidate every hour
    3 
    4// Force dynamic
    5fetch(url, { cache: 'no-store' });
    6 
    7// Force static
    8fetch(url, { cache: 'force-cache' });

    Client-Side Data Fetching


    javascript(27 lines, showing 15)
    1'use client';
    2 
    3import { useEffect, useState } from 'react';
    4 
    5export default function ClientPosts() {
    6 const [posts, setPosts] = useState([]);
    7 const [loading, setLoading] = useState(true);
    8
    9 useEffect(() => {
    10 fetch('/api/posts')
    11 .then(res => res.json())
    12 .then(data => {
    13 setPosts(data);
    14 setLoading(false);
    15 });

    Using SWR (Recommended for Client Fetching)


    bash
    1npm install swr

    javascript(20 lines, showing 15)
    1'use client';
    2 
    3import useSWR from 'swr';
    4 
    5const fetcher = (url) => fetch(url).then(res => res.json());
    6 
    7export default function Posts() {
    8 const { data, error, isLoading } = useSWR('/api/posts', fetcher);
    9
    10 if (error) return <div>Failed to load</div>;
    11 if (isLoading) return <div>Loading...</div>;
    12
    13 return (
    14 <ul>
    15 {data.map(post => (

    ---


    Styling & UI


    CSS Modules


    javascript
    1// app/components/Button.module.css
    2.button {
    3 background: blue;
    4 color: white;
    5 padding: 10px 20px;
    6}

    javascript
    1// app/components/Button.js
    2import styles from './Button.module.css';
    3 
    4export default function Button() {
    5 return <button className={styles.button}>Click me</button>;
    6}

    Tailwind CSS


    javascript
    1// app/components/Card.js
    2export default function Card({ title, children }) {
    3 return (
    4 <div className="bg-white rounded-lg shadow-md p-6">
    5 <h2 className="text-2xl font-bold mb-4">{title}</h2>
    6 {children}
    7 </div>
    8 );
    9}

    Styled Components


    bash
    1npm install styled-components

    javascript
    1'use client';
    2 
    3import styled from 'styled-components';
    4 
    5const StyledButton = styled.button`
    6 background: ${props => props.primary ? 'blue' : 'gray'};
    7 color: white;
    8 padding: 10px 20px;
    9 border: none;
    10 border-radius: 4px;
    11`;
    12 
    13export default function Button({ primary, children }) {
    14 return <StyledButton primary={primary}>{children}</StyledButton>;
    15}

    ---


    Optimization (Intermediate)


    Image Optimization


    javascript
    1import Image from 'next/image';
    2 
    3export default function OptimizedImage() {
    4 return (
    5 <Image
    6 src="/hero.jpg"
    7 alt="Hero image"
    8 width={800}
    9 height={600}
    10 priority // Load immediately
    11 placeholder="blur" // Blur placeholder
    12 />
    13 );
    14}

    Font Optimization


    javascript
    1// app/layout.js
    2import { Inter } from 'next/font/google';
    3 
    4const inter = Inter({ subsets: ['latin'] });
    5 
    6export default function RootLayout({ children }) {
    7 return (
    8 <html lang="en" className={inter.className}>
    9 <body>{children}</body>
    10 </html>
    11 );
    12}

    Code Splitting


    javascript
    1'use client';
    2 
    3import dynamic from 'next/dynamic';
    4 
    5// Lazy load component
    6const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
    7 loading: () => <p>Loading...</p>,
    8 ssr: false // Disable SSR if needed
    9});
    10 
    11export default function Page() {
    12 return <HeavyComponent />;
    13}

    Metadata & SEO


    javascript
    1// app/about/page.js
    2export const metadata = {
    3 title: 'About Us',
    4 description: 'Learn more about our company',
    5 openGraph: {
    6 title: 'About Us',
    7 description: 'Learn more about our company',
    8 images: ['/og-image.jpg'],
    9 },
    10};
    11 
    12export default function About() {
    13 return <h1>About</h1>;
    14}

    ---


    Advanced Patterns (Expert)


    Server Actions


    javascript
    1// app/actions.js
    2'use server';
    3 
    4export async function createPost(formData) {
    5 const title = formData.get('title');
    6 const content = formData.get('content');
    7
    8 // Save to database
    9 await db.posts.create({ title, content });
    10
    11 revalidatePath('/posts');
    12 redirect('/posts');
    13}

    javascript
    1// app/posts/new/page.js
    2import { createPost } from '../actions';
    3 
    4export default function NewPost() {
    5 return (
    6 <form action={createPost}>
    7 <input name="title" required />
    8 <textarea name="content" required />
    9 <button type="submit">Create Post</button>
    10 </form>
    11 );
    12}

    Middleware


    javascript(17 lines, showing 15)
    1// middleware.js
    2import { NextResponse } from 'next/server';
    3 
    4export function middleware(request) {
    5 // Authentication check
    6 const token = request.cookies.get('token');
    7
    8 if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    9 return NextResponse.redirect(new URL('/login', request.url));
    10 }
    11
    12 return NextResponse.next();
    13}
    14 
    15export const config = {

    API Routes


    javascript
    1// app/api/posts/route.js
    2export async function GET(request) {
    3 const posts = await db.posts.findMany();
    4 return Response.json(posts);
    5}
    6 
    7export async function POST(request) {
    8 const body = await request.json();
    9 const post = await db.posts.create({ data: body });
    10 return Response.json(post, { status: 201 });
    11}

    Streaming & Suspense


    javascript(25 lines, showing 15)
    1// app/dashboard/page.js
    2import { Suspense } from 'react';
    3 
    4async function UserProfile() {
    5 const user = await fetchUser();
    6 return <div>{user.name}</div>;
    7}
    8 
    9async function UserPosts() {
    10 const posts = await fetchPosts();
    11 return <ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>;
    12}
    13 
    14export default function Dashboard() {
    15 return (

    Error Boundaries


    javascript
    1// app/error.js
    2'use client';
    3 
    4export default function Error({ error, reset }) {
    5 return (
    6 <div>
    7 <h2>Something went wrong!</h2>
    8 <button onClick={() => reset()}>Try again</button>
    9 </div>
    10 );
    11}

    Loading States


    javascript
    1// app/loading.js
    2export default function Loading() {
    3 return <div>Loading...</div>;
    4}

    ---


    Production Code Structure


    Recommended Folder Structure


    text(31 lines, showing 15)
    1my-app/
    2├── app/
    3│ ├── (auth)/
    4│ │ ├── login/
    5│ │ └── register/
    6│ ├── (dashboard)/
    7│ │ ├── dashboard/
    8│ │ └── settings/
    9│ ├── api/
    10│ │ ├── auth/
    11│ │ └── posts/
    12│ ├── components/
    13│ │ ├── ui/
    14│ │ ├── forms/
    15│ │ └── layout/

    Component Organization


    javascript(23 lines, showing 15)
    1// app/components/ui/Button.js
    2'use client';
    3 
    4export default function Button({
    5 children,
    6 variant = 'primary',
    7 onClick
    8}) {
    9 const baseStyles = 'px-4 py-2 rounded font-medium';
    10 const variants = {
    11 primary: 'bg-blue-600 text-white hover:bg-blue-700',
    12 secondary: 'bg-gray-200 text-gray-800 hover:bg-gray-300',
    13 };
    14
    15 return (

    Utility Functions


    javascript
    1// app/lib/utils.js
    2export function formatDate(date) {
    3 return new Intl.DateTimeFormat('en-US', {
    4 year: 'numeric',
    5 month: 'long',
    6 day: 'numeric',
    7 }).format(new Date(date));
    8}
    9 
    10export function cn(...classes) {
    11 return classes.filter(Boolean).join(' ');
    12}

    Database Layer


    javascript
    1// app/lib/db.js
    2import { PrismaClient } from '@prisma/client';
    3 
    4const globalForPrisma = globalThis;
    5 
    6export const db = globalForPrisma.prisma || new PrismaClient();
    7 
    8if (process.env.NODE_ENV !== 'production') {
    9 globalForPrisma.prisma = db;
    10}

    Environment Variables


    javascript
    1// .env.local
    2DATABASE_URL="postgresql://..."
    3NEXT_PUBLIC_API_URL="https://api.example.com"
    4SECRET_KEY="your-secret-key"

    javascript
    1// app/lib/config.js
    2export const config = {
    3 apiUrl: process.env.NEXT_PUBLIC_API_URL,
    4 secretKey: process.env.SECRET_KEY,
    5};

    ---


    Deployment & Performance


    Build Optimization


    javascript(24 lines, showing 15)
    1// next.config.js
    2/** @type {import('next').NextConfig} */
    3const nextConfig = {
    4 // Enable SWC minification
    5 swcMinify: true,
    6
    7 // Optimize images
    8 images: {
    9 domains: ['example.com'],
    10 },
    11
    12 // Compression
    13 compress: true,
    14
    15 // Production source maps

    Performance Monitoring


    javascript
    1// app/instrumentation.js
    2export async function register() {
    3 if (process.env.NEXT_RUNTIME === 'nodejs') {
    4 await import('./lib/monitoring');
    5 }
    6}

    Deployment Checklist


  • [ ] Set environment variables
  • [ ] Optimize images
  • [ ] Enable compression
  • [ ] Set up error tracking (Sentry)
  • [ ] Configure analytics
  • [ ] Set up CDN
  • [ ] Enable caching headers
  • [ ] Test production build locally
  • [ ] Set up monitoring

  • Vercel Deployment


    bash
    1# Install Vercel CLI
    2npm i -g vercel
    3 
    4# Deploy
    5vercel
    6 
    7# Production deployment
    8vercel --prod

    ---


    Best Practices Summary


    Do's ✅


  • Use Server Components by default
  • Leverage Next.js Image component
  • Implement proper error boundaries
  • Use TypeScript for type safety
  • Optimize bundle size
  • Implement proper caching strategies
  • Use middleware for authentication
  • Follow the file-based routing conventions

  • Don'ts ❌


  • Don't use 'use client' unnecessarily
  • Don't fetch data in Client Components when Server Components can do it
  • Don't ignore SEO metadata
  • Don't skip error handling
  • Don't forget to optimize images
  • Don't use inline styles for everything
  • Don't ignore accessibility

  • ---


    Resources


  • [Next.js Documentation](https://nextjs.org/docs)
  • [Next.js GitHub](https://github.com/vercel/next.js)
  • [React Documentation](https://react.dev)
  • [Vercel Platform](https://vercel.com)

  • ---


    Conclusion


    Next.js is a powerful framework that simplifies React development while providing excellent performance out of the box. By following this guide, you've learned:


    1. Basics: Setup, routing, and core concepts

    2. Intermediate: Data fetching, styling, and optimization

    3. Advanced: Server actions, middleware, and streaming

    4. Expert: Production structure and deployment


    Start building your Next.js application today and experience the power of modern web development!


    Happy coding! 🚀


    Enjoyed this article?

    Support our work and help us create more free content for developers.

    Stay Updated

    Get the latest articles and updates delivered to your inbox.