Karya Semi
HomeBlogSearchTagsCategoriesAboutContact
Karya Semi

Less noise. More notes.

HomeBlogAboutContactPrivacy PolicyDisclaimer

© 2026 Karya Semi. All rights reserved.

XGitHubLinkedIn
  1. Home
  2. /Categories
  3. /Web Development

Getting Started with Next.js: A Developer's Comprehensive Guide

Learn how to use Next.js for building modern, full-stack React applications with server-side rendering, static site generation, and API routes.

Dian Rijal Asyrof/June 20, 2026/6 min read
Illustration for Getting Started with Next.js: A Developer's Comprehensive Guide
Advertisement

Next.js has established itself as the leading React framework for building production-ready, full-stack web applications. Created and maintained by Vercel, it offers an exceptional developer experience with powerful features like server-side rendering (SSR), static site generation (SSG), and integrated API routes. This guide will walk you through the core concepts and practical steps to start building with Next.js.

Why Choose Next.js?

Before diving into implementation, understanding Next.js's value proposition is crucial. It solves several pain points present in client-side only React applications:

  • Improved Performance & SEO: Automatic server-side rendering and static generation ensure content is immediately available to search engines and users, reducing time-to-first-byte (TTFB) and largest contentful paint (LCP).
  • Simplified Routing: File-based routing eliminates the need for complex routing configuration; simply create files in the app or pages directory.
  • Built-in Optimizations: Automatic image optimization, font optimization, script loading strategies, and code splitting are handled out-of-the-box.
  • Full-Stack Capabilities: API routes allow you to build backend endpoints alongside your frontend code, simplifying deployment and architecture.
  • Flexible Rendering: Choose per-page between SSR, SSG, Incremental Static Regeneration (ISR), and client-side rendering based on your data requirements.

Setting Up Your Next.js Project

Getting started is straightforward. Ensure you have Node.js version 18.17 or later installed. Use the official create-next-app CLI to scaffold a new project with recommended defaults.

  1. Run the creation command:

    npx create-next-app@latest my-next-app
  2. Follow the interactive prompts: You'll be asked about using TypeScript, ESLint, Tailwind CSS, and the src/ directory. For this guide, we'll select TypeScript and Tailwind CSS.

  3. Navigate to your project and start the dev server:

    cd my-next-app
    npm run dev

    Visit http://localhost:3000 to see your running application.

The project structure is now set up with key configuration files (next.config.js, tsconfig.json) and the core app directory for the new App Router.

Understanding the App Router (Recommended)

Next.js 13 introduced the App Router (app/ directory), which is now the recommended routing paradigm. It uses a file-system based router where folders define routes and special files define UI for each segment.

Key Files in the App Router:

  • layout.tsx: Defines a shared UI layout that persists across navigation. It wraps the child page.tsx.
  • page.tsx: Defines the unique UI for a route and makes it publicly accessible.
  • loading.tsx: Provides an instant loading UI (suspense boundary) for the route segment.
  • error.tsx: Provides an error boundary for the route segment.
  • template.tsx: Similar to layout.tsx but creates a new instance on every navigation.

Example Directory Structure:

app/
├── layout.tsx        // Root layout (required)
├── page.tsx          // Home page (mapped to "/")
├── about/
│   └── page.tsx      // About page (mapped to "/about")
└── blog/
    ├── layout.tsx    // Blog-specific layout
    └── [slug]/
        └── page.tsx  // Dynamic route for blog posts

Creating Pages and Layouts

Let's create a simple homepage with a shared header. Modify the root app/layout.tsx to include a navigation bar.

// app/layout.tsx
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import './globals.css';
 
const inter = Inter({ subsets: ['latin'] });
 
export const metadata: Metadata = {
  title: 'My Next.js App',
  description: 'A demonstration site built with Next.js',
};
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <nav className="flex items-center justify-between p-4 bg-blue-600 text-white">
          <span className="font-bold text-xl">NextApp</span>
          <div className="flex gap-6">
            <a href="/" className="hover:underline">Home</a>
            <a href="/about" className="hover:underline">About</a>
            <a href="/blog" className="hover:underline">Blog</a>
          </div>
        </nav>
        <main className="p-8">
          {children}
        </main>
      </body>
    </html>
  );
}

Now, create the home page component:

// app/page.tsx
export default function HomePage() {
  return (
    <div>
      <h1 className="text-3xl font-bold mb-4">Welcome to Next.js</h1>
      <p className="text-lg text-gray-700">
        This is a full-stack React application with built-in SSR, SSG, and API routes.
      </p>
    </div>
  );
}

Data Fetching Strategies

Next.js extends the native fetch API to provide powerful data caching and revalidation capabilities. The method you use depends on your data's nature.

1. Server Components (Default in App Router)

In the App Router, all components are React Server Components by default. You can directly async/await fetch data in the component.

// app/blog/[slug]/page.tsx
interface Post {
  id: string;
  title: string;
  content: string;
}
 
export default async function BlogPost({ params }: { params: { slug: string } }) {
  // This fetch happens on the server at request time (SSR) or at build time (SSG)
  // depending on the route configuration.
  const response = await fetch(`https://api.example.com/posts/${params.slug}`);
  const post: Post = await response.json();
 
  return (
    <article>
      <h1 className="text-2xl font-bold">{post.title}</h1>
      <div className="mt-4 whitespace-pre-line">{post.content}</div>
    </article>
  );
}

2. Static Data with generateStaticParams

For static generation of dynamic routes, export a generateStaticParams function to pre-render paths at build time.

// app/blog/[slug]/page.tsx (updated)
export async function generateStaticParams() {
  const response = await fetch('https://api.example.com/posts');
  const posts: Post[] = await response.json();
 
  return posts.map((post) => ({
    slug: post.id,
  }));
}

3. Incremental Static Regeneration (ISR)

Combine static generation with the ability to update pages after deployment using revalidate in fetch or generateStaticParams.

const response = await fetch('https://api.example.com/posts', {
  next: { revalidate: 3600 }, // Revalidate every hour
});

Building API Routes

The App Router uses Route Handlers for API endpoints. Create a route.ts file inside a route segment.

// app/api/posts/route.ts
import { NextResponse } from 'next/server';
 
export async function GET() {
  const posts = [
    { id: '1', title: 'First Post', excerpt: 'Hello world' },
    { id: '2', title: 'Second Post', excerpt: 'Next.js is great' },
  ];
 
  return NextResponse.json(posts);
}
 
export async function POST(request: Request) {
  const body = await request.json();
  // In a real app, you would validate and save to a database
  console.log('Received new post:', body);
 
  return NextResponse.json({ message: 'Post created' }, { status: 201 });
}

You can now fetch this data from a Server Component or a Client Component using standard fetch('/api/posts').

Client-Side Interactivity

Not everything can or should be rendered on the server. For interactive UI, you must use Client Components by adding the 'use client'; directive at the top of the file.

// app/components/Counter.tsx
'use client';
 
import { useState } from 'react';
 
export default function Counter() {
  const [count, setCount] = useState(0);
 
  return (
    <div className="p-4 border rounded">
      <p className="mb-2">Count: {count}</p>
      <button
        onClick={() => setCount(c => c + 1)}
        className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
      >
        Increment
      </button>
    </div>
  );
}

Import this Counter into any Server Component, and it will work seamlessly. Next.js handles the hydration automatically.

Deployment and Optimization

When you're ready to deploy, Next.js offers several options:

  • Vercel: The optimal platform, with zero-configuration deployment, preview environments, and analytics.
  • Docker: Suitable for self-hosted environments. Build a production image with npm run build and start it with npm run start.
  • Static Export: Use next export for fully static sites (no server-side features).

Key Optimization Tips:

  • Use the <Image> component from next/image for automatic image optimization.
  • Use the <Link> component from next/link for client-side navigation and prefetching.
  • Implement dynamic imports (next/dynamic) for heavy components to reduce initial bundle size.
  • Utilize built-in SEO with the metadata export in layout.tsx or page.tsx.

FAQ

The `app` directory (App Router) is the newer, recommended paradigm in Next.js 13+. It supports React Server Components, nested layouts, and enhanced data fetching. The `pages` directory (Pages Router) is the original routing system, which is still fully supported but does not have the latest performance optimizations and features.

For Server Actions (mutations that run on the server), you can use the `action` attribute on a `<form>` element pointing to a server function. For client-side forms, use standard React state management with `useState` and `onSubmit` handlers, often enhanced with libraries like React Hook Form.

Absolutely. Next.js is a frontend framework. Its API routes are optional. You can fetch data from any external REST or GraphQL API hosted on a separate server. Simply call those endpoints from your Server Components using `fetch`.

Next.js supports all common authentication strategies. You can use solutions like NextAuth.js (Auth.js) which integrates seamlessly, or implement your own JWT/session-based logic using cookies and middleware (`middleware.ts`) for protected routes.

Use SSG for pages where data doesn't change frequently (e.g., blog posts, documentation). It provides the fastest performance. Use SSR for pages where data must be fresh on every request (e.g., dashboards, personalized feeds). Next.js allows you to choose per-page, and even mix them with Incremental Static Regeneration (ISR).

Advertisement
DR

Dian Rijal Asyrof

Writes about useful AI tools, programming practice, and the craft of building reliable software.

Previous articleHow I Use AI to Write Blog Posts Faster Without Losing QualityNext articleA Developer's Roadmap: How to Learn Next.js from Zero to Production
nextjsreactssrtypescriptwebdev
Advertisement
Advertisement
On this page↓
  1. Why Choose Next.js?
  2. Setting Up Your Next.js Project
  3. Understanding the App Router (Recommended)
  4. Creating Pages and Layouts
  5. Data Fetching Strategies
  6. Building API Routes
  7. Client-Side Interactivity
  8. Deployment and Optimization
  9. FAQ
  10. What is the difference between the app and pages directory?
  11. How do I handle forms in Next.js?
  12. Can I use Next.js with a separate backend like Express or Django?
  13. How does Next.js handle authentication?
  14. When should I use Static Site Generation (SSG) vs. Server-Side Rendering (SSR)?

On this page

  1. Why Choose Next.js?
  2. Setting Up Your Next.js Project
  3. Understanding the App Router (Recommended)
  4. Creating Pages and Layouts
  5. Data Fetching Strategies
  6. Building API Routes
  7. Client-Side Interactivity
  8. Deployment and Optimization
  9. FAQ
  10. What is the difference between the app and pages directory?
  11. How do I handle forms in Next.js?
  12. Can I use Next.js with a separate backend like Express or Django?
  13. How does Next.js handle authentication?
  14. When should I use Static Site Generation (SSG) vs. Server-Side Rendering (SSR)?

See also

Illustration for A Developer's Roadmap: How to Learn Next.js from Zero to Production
Web Development/Jun 20, 2026

A Developer's Roadmap: How to Learn Next.js from Zero to Production

Master Next.js with this structured guide for intermediate developers. Learn core concepts like the App Router, Server Components, and data fetching through practical examples.

6 min read
nextjsreact
Illustration for How to Learn Next.js: A Practical Guide for Developers
Web Development/Jun 20, 2026

How to Learn Next.js: A Practical Guide for Developers

A step-by-step technical guide for developers on how to effectively learn Next.js, covering core concepts, project structure, and best practices for building production apps.

5 min read
nextjsreact
Illustration for Next.js: A Deep Dive into the React Framework for Production
Web Development/Jun 20, 2026

Next.js: A Deep Dive into the React Framework for Production

Explore the core features, architecture, and best practices for building high-performance, production-ready web applications with Next.js, the leading React framework.

6 min read
nextjsreact