Skip to content
All posts
Tutorial3 min read

Getting Started with Next.js 16 — A Complete Guide

DebuggerMe TeamDebuggerMe TeamApril 20, 2026
Next.js 16 logo with code snippets in the background
Photo by Unsplash
On this page

Next.js 16 brings a mature, production-ready App Router that changes how we think about React applications. In this guide, we'll build a complete project from scratch — no shortcuts.

Prerequisites

Before diving in, make sure you have:

  • Node.js 20+ installed
  • Basic familiarity with React and TypeScript
  • A code editor (VS Code recommended)

Project Setup

Scaffold a new project with the official create-next-app CLI:

bash
npx create-next-app@latest my-app --typescript --tailwind --app
cd my-app
npm run dev

Your project will be running at http://localhost:3000.

Understanding the App Router

The App Router is the heart of Next.js 16. Unlike the old pages/ directory, everything in app/ is a React Server Component by default.

File Conventions

code
src/app/
├── layout.tsx        # Root layout (wraps every page)
├── page.tsx          # Homepage → /
├── about/
│   └── page.tsx      # About page → /about
└── blog/
    ├── page.tsx      # Blog listing → /blog
    └── [slug]/
        └── page.tsx  # Dynamic route → /blog/:slug

Server vs Client Components

This is the key mental model shift:

[!NOTE] Server Components run on the server at build time or request time. They can fetch data directly, read files, and access databases — but they cannot use useState, useEffect, or event handlers.

[!TIP] Client Components are marked with "use client" at the top of the file. They run in the browser and support interactivity. Keep them small and push them to the leaves of your component tree.

tsx
// Server Component (default) — no directive needed
export default async function BlogList() {
  const posts = await db.posts.findMany(); // Direct DB access ✅
  return <ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>;
}

// Client Component — needs the directive
"use client";
import { useState } from "react";

export function Counter() {
  const [count, setCount] = useState(0); // useState ✅
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

Data Fetching

Server Components make data fetching dramatically simpler:

tsx
// No useEffect, no loading state, no API routes needed
export default async function ProductPage({ params }: { params: { id: string } }) {
  const product = await fetch(`https://api.example.com/products/${params.id}`, {
    next: { revalidate: 3600 }, // ISR: revalidate every hour
  }).then(r => r.json());

  return (
    <div>
      <h1>{product.name}</h1>
      <p>${product.price}</p>
    </div>
  );
}

Layouts

Layouts persist between navigations — they don't unmount. This is perfect for headers, footers, and sidebars:

tsx
// app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <Header />
        <main>{children}</main>
        <Footer />
      </body>
    </html>
  );
}

Static Generation with generateStaticParams

For dynamic routes, export generateStaticParams to pre-render pages at build time:

tsx
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
  const posts = await getAllPosts();
  return posts.map((post) => ({ slug: post.slug }));
}

Metadata API

Replace <Head> with the built-in Metadata API:

tsx
import type { Metadata } from "next";

export const metadata: Metadata = {
  title: "My Page",
  description: "Page description for SEO",
  openGraph: { title: "My Page", type: "article" },
};

Deployment

Push to GitHub and connect to Vercel for zero-config deployment:

bash
git push origin main
# Vercel auto-detects Next.js and configures everything

Summary

Next.js 16 with the App Router gives you:

  • Server Components for zero-bundle-size data fetching
  • Nested layouts that persist between routes
  • Static generation with generateStaticParams
  • Built-in metadata for SEO
  • TypeScript-first developer experience

Start with Server Components everywhere, add "use client" only when you need interactivity. That's the golden rule.

Tools in this post

Related Tool

JSON Parser & Formatter

Validate, format, and minify JSON data with error highlighting.

Try it free

Related Tool

XML Formatter & Beautifier

Beautify and minify XML code with syntax highlighting.

Try it free
DebuggerMe Team

Written by

DebuggerMe Team

The DebuggerMe team builds developer tools, writes technical content, and helps teams ship better software.

Share this post

Back to all posts

Related Articles

All articles →