DEV Community

Cover image for Understanding Next.js 15: A Complete Guide for React Developers (PART 1)
Fonyuy Gita
Fonyuy Gita

Posted on • Edited on

Understanding Next.js 15: A Complete Guide for React Developers (PART 1)

Table of Contents

  1. What is Next.js?
  2. The Origin Story: Why Next.js Was Created
  3. Next.js and React: Understanding the Relationship
  4. Why Next.js is Cool: The Game-Changing Features
  5. Setting Up Next.js 15
  6. Understanding the Project Structure
  7. Files and Folders Explained
  8. Routing in Next.js: The Complete Guide

What is Next.js?

Think of Next.js as React's professional upgrade. While React is fantastic for building user interfaces, it's like having a powerful engine without a complete car. Next.js is the full vehicle that takes React and wraps it with everything you need to build production-ready web applications.

At its core, Next.js is a React framework that provides structure, optimization, and additional features that React alone doesn't offer. It's like the difference between buying individual ingredients and getting a complete meal kit with recipes, cooking instructions, and all the tools you need.

When you build with React alone, you're responsible for setting up build tools, configuring routing, handling server-side rendering, optimizing performance, and managing countless other details. Next.js handles these concerns for you, letting you focus on building your application's unique features.

The Origin Story: Why Next.js Was Created

original story
To understand why Next.js exists, let's imagine you're a React developer in 2016. You've built a beautiful React application, but you're facing several challenges that every React developer encountered:

The SEO Problem: Your React app renders on the client side, meaning search engines see a blank page with a loading spinner. Google's crawlers can't index your content effectively, making your site invisible to search engines.

The Performance Problem: Users have to download your entire JavaScript bundle before they see anything meaningful. On slower connections, this creates frustrating loading experiences.

The Configuration Problem: Setting up webpack, Babel, routing, and other build tools requires deep knowledge of complex tooling. You spend more time configuring than building.

The Deployment Problem: Getting your React app production-ready involves numerous optimization steps that are easy to miss or misconfigure.

Guillermo Rauch and the team at Vercel (formerly Zeit) recognized these pain points and created Next.js to solve them systematically. They wanted React development to be as simple as creating a file and writing components, while automatically handling all the production concerns.

Next.js was born from the philosophy that frameworks should provide "zero-configuration" developer experience while maintaining the flexibility to customize when needed. It's the bridge between React's component-based architecture and the real-world requirements of modern web applications.

Next.js and React: Understanding the Relationship

Here's a crucial point that often confuses beginners: Next.js IS React. It's not a replacement for React; it's React with superpowers.

React Nextjs

Think of this relationship like a smartphone and its operating system. React is like the core processor that handles the fundamental operations, while Next.js is like iOS or Android that provides the interface, apps, and features that make the device useful in daily life.

When you write Next.js code, you're still writing React components with JSX, using hooks, managing state, and following all the React patterns you already know. The difference is that Next.js provides the framework around your React components to handle routing, rendering, optimization, and deployment.

Here's what this means practically:

// This is a React component
function MyComponent() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode
// This is the same component in Next.js - no difference!
function MyComponent() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

The magic happens in how Next.js organizes, renders, and optimizes your React components behind the scenes.

Why Next.js is Cool: The Game-Changing Features

Next.js transforms React development by providing solutions to common problems that would otherwise require complex setup and configuration. Let's explore the features that make developers fall in love with Next.js:

Server-Side Rendering (SSR) Made Simple: Instead of sending an empty HTML shell to the browser, Next.js can render your React components on the server and send fully-formed HTML. This means faster initial page loads and better SEO, all without changing how you write React components.

Static Site Generation (SSG): Next.js can pre-build your pages at build time, creating static HTML files that load instantly. This is perfect for blogs, marketing sites, and any content that doesn't change frequently.

Automatic Code Splitting: Next.js automatically splits your code into smaller chunks, loading only what's needed for each page. This means users don't download your entire application upfront.

Built-in CSS Support: Whether you prefer CSS modules, styled-components, or Tailwind CSS, Next.js handles the configuration and optimization automatically.

API Routes: You can create backend API endpoints directly in your Next.js project, eliminating the need for a separate backend service for simple applications.

Image Optimization: The Next.js Image component automatically optimizes images for different screen sizes and formats, improving performance without manual intervention.

File-based Routing: No more router configuration files. Create a file in the pages or app directory, and Next.js automatically creates the route.

Zero Configuration: Most features work out of the box without configuration, but everything can be customized when needed.

Setting Up Next.js 15

Let's get your hands dirty with actual code. Setting up Next.js 15 is remarkably straightforward, but understanding what happens during setup helps you become a better developer.

First, ensure you have Node.js installed (version 18.17 or later). Then run:

npx create-next-app@latest my-next-app
Enter fullscreen mode Exit fullscreen mode

During setup, you'll be prompted with several questions. Here's what each means:

Would you like to use TypeScript? (Yes/No)
# TypeScript adds type safety to your JavaScript
# Recommended for larger projects

Would you like to use ESLint? (Yes/No)
# ESLint catches common coding errors and enforces style
# Definitely recommended

Would you like to use Tailwind CSS? (Yes/No)
# Tailwind is a utility-first CSS framework
# Great for rapid styling

Would you like to use `src/` directory? (Yes/No)
# Organizes your app code in a src folder
# Personal preference, both approaches work

Would you like to use App Router? (Yes/No)
# App Router is the new routing system in Next.js 13+
# Recommended for new projects

Would you like to customize the default import alias? (Yes/No)
# Allows you to use @ instead of relative imports
# Helpful for cleaner imports
Enter fullscreen mode Exit fullscreen mode

For beginners, I recommend these settings:

✓ Would you like to use TypeScript? ... No (start simple)
✓ Would you like to use ESLint? ... Yes
✓ Would you like to use Tailwind CSS? ... Yes
✓ Would you like to use `src/` directory? ... No
✓ Would you like to use App Router? ... Yes
✓ Would you like to customize the default import alias? ... Yes
Enter fullscreen mode Exit fullscreen mode

After setup completes, navigate to your project and start the development server:

cd my-next-app
npm run dev
Enter fullscreen mode Exit fullscreen mode

Open your browser to http://localhost:3000, and you'll see your Next.js application running!

Understanding the Project Structure

When you examine your new Next.js project, you'll see a structure that's both familiar and new. Let's walk through it systematically:

my-next-app/
├── app/                    # App Router directory (Next.js 13+)
│   ├── favicon.ico        # Website icon
│   ├── globals.css        # Global styles
│   ├── layout.tsx         # Root layout component
│   └── page.tsx           # Home page component
├── public/                # Static assets
│   ├── next.svg           # Next.js logo
│   └── vercel.svg         # Vercel logo
├── .eslintrc.json         # ESLint configuration
├── .gitignore             # Git ignore rules
├── next.config.js         # Next.js configuration
├── package.json           # Project dependencies
├── postcss.config.js      # PostCSS configuration
├── README.md              # Project documentation
└── tailwind.config.js     # Tailwind CSS configuration
Enter fullscreen mode Exit fullscreen mode

This structure reflects Next.js's philosophy of convention over configuration. Each directory has a specific purpose, and understanding these purposes helps you build applications more effectively.

Files and Folders Explained

Let's examine each important file and folder to understand their roles in your Next.js application:

The app/ Directory: This is where your application lives. In Next.js 13+, the App Router uses this directory to define your application's structure. Every folder inside app/ potentially represents a route in your application.

app/layout.tsx: Think of this as the template that wraps every page in your application. It's like the HTML shell that contains your navigation, footer, and other elements that appear on every page:

// app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        {/* This is where your page content appears */}
        {children}
      </body>
    </html>
  )
}
Enter fullscreen mode Exit fullscreen mode

app/page.tsx: This is your home page component. Any file named page.tsx in the app directory becomes a route:

// app/page.tsx
export default function Home() {
  return (
    <div>
      <h1>Welcome to Next.js!</h1>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

app/globals.css: Global styles that apply to your entire application. This is where you'd put CSS reset rules, typography definitions, and styles that need to be available everywhere.

public/ Directory: Static assets that should be served directly by the web server. Images, fonts, and other files placed here can be accessed via URLs like /image.jpg.

next.config.js: Configuration file for customizing Next.js behavior. Most projects start with a minimal configuration, but this file becomes crucial as your application grows:

/** @type {import('next').NextConfig} */
const nextConfig = {
  // Example configurations
  images: {
    domains: ['example.com'], // Allow images from external domains
  },
  experimental: {
    // Enable experimental features
  }
}

module.exports = nextConfig
Enter fullscreen mode Exit fullscreen mode

package.json: Contains your project's dependencies and scripts. Pay attention to the scripts section:

{
  "scripts": {
    "dev": "next dev",        // Start development server
    "build": "next build",    // Build for production
    "start": "next start",    // Start production server
    "lint": "next lint"       // Run ESLint
  }
}
Enter fullscreen mode Exit fullscreen mode

Routing in Next.js: The Complete Guide

Routing is where Next.js truly shines. Instead of configuring complex routing libraries, Next.js uses the file system to determine your application's routes. This approach is intuitive once you understand the patterns.

File-based Routing Fundamentals

The core concept is simple: files and folders in your app/ directory become routes in your application. Here's how it works:

app/
├── page.tsx              # Route: /
├── about/
│   └── page.tsx         # Route: /about
├── blog/
│   ├── page.tsx         # Route: /blog
│   └── [slug]/
│       └── page.tsx     # Route: /blog/[slug]
└── dashboard/
    ├── page.tsx         # Route: /dashboard
    └── settings/
        └── page.tsx     # Route: /dashboard/settings
Enter fullscreen mode Exit fullscreen mode

Each page.tsx file exports a React component that becomes the content for that route. The folder structure directly maps to URL paths.

App Router vs Pages Router

Next.js 15 supports two routing systems, and understanding both helps you work with existing projects and choose the right approach for new ones.

Pages Router (Legacy): Uses the pages/ directory where each file automatically becomes a route. This is the traditional Next.js approach:

pages/
├── index.js           # Route: /
├── about.js           # Route: /about
└── blog/
    └── [slug].js      # Route: /blog/[slug]
Enter fullscreen mode Exit fullscreen mode

App Router (Recommended): Uses the app/ directory with more flexible routing patterns and better support for layouts and data fetching:

app/
├── page.tsx           # Route: /
├── about/
│   └── page.tsx      # Route: /about
└── blog/
    └── [slug]/
        └── page.tsx  # Route: /blog/[slug]
Enter fullscreen mode Exit fullscreen mode

The App Router provides better developer experience with features like nested layouts, loading states, and error boundaries that are built into the routing system.

Dynamic Routes

Dynamic routes handle variable URL segments. Instead of creating separate pages for each blog post, you create one dynamic route that handles all posts:

// app/blog/[slug]/page.tsx
export default function BlogPost({ params }: { params: { slug: string } }) {
  return (
    <div>
      <h1>Blog Post: {params.slug}</h1>
      <p>This page handles /blog/my-first-post, /blog/another-post, etc.</p>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

For multiple dynamic segments, you can nest them:

app/blog/[category]/[slug]/page.tsx
Enter fullscreen mode Exit fullscreen mode

This handles routes like /blog/tech/nextjs-guide or /blog/design/color-theory.

Route Groups

Route groups let you organize your routes without affecting the URL structure. Wrap folder names in parentheses to create groups:

app/
├── (marketing)/
│   ├── about/
│   │   └── page.tsx     # Route: /about
│   └── contact/
│       └── page.tsx     # Route: /contact
└── (app)/
    ├── dashboard/
    │   └── page.tsx     # Route: /dashboard
    └── profile/
        └── page.tsx     # Route: /profile
Enter fullscreen mode Exit fullscreen mode

This is helpful for organizing related routes and applying different layouts to different sections of your app.

Parallel Routes

Parallel routes allow you to render multiple pages simultaneously in the same layout. This is useful for dashboards where you might want to show different sections independently:

app/dashboard/
├── page.tsx
├── @analytics/
│   └── page.tsx
├── @team/
│   └── page.tsx
└── layout.tsx
Enter fullscreen mode Exit fullscreen mode

The layout can render both parallel routes:

// app/dashboard/layout.tsx
export default function DashboardLayout({
  children,
  analytics,
  team,
}: {
  children: React.ReactNode
  analytics: React.ReactNode
  team: React.ReactNode
}) {
  return (
    <div>
      {children}
      <div className="grid grid-cols-2 gap-4">
        {analytics}
        {team}
      </div>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Intercepting Routes

Intercepting routes let you load a route within the context of the current page. This is perfect for modals that show content while keeping the current page in the background:

app/
├── feed/
│   └── page.tsx
├── photo/
│   └── [id]/
│       └── page.tsx
└── @modal/
    └── (..)photo/
        └── [id]/
            └── page.tsx
Enter fullscreen mode Exit fullscreen mode

When a user navigates to /photo/123 from the feed, the intercepting route shows the photo in a modal while keeping the feed visible.

API Routes

API routes let you create backend endpoints directly in your Next.js application. Place files in the app/api/ directory:

// app/api/hello/route.ts
export async function GET() {
  return Response.json({ message: 'Hello from Next.js API!' })
}

export async function POST(request: Request) {
  const body = await request.json()
  // Process the request
  return Response.json({ success: true })
}
Enter fullscreen mode Exit fullscreen mode

This creates an API endpoint at /api/hello that handles both GET and POST requests.

When to Use Which Routing Pattern

Understanding when to use each routing pattern helps you build more maintainable applications:

Static Routes (/about/page.tsx): Use for pages with fixed content that doesn't change based on URL parameters. Perfect for about pages, contact forms, and landing pages.

Dynamic Routes (/blog/[slug]/page.tsx): Use when you have many similar pages that differ only by an identifier. Ideal for blog posts, product pages, and user profiles.

Route Groups (/(marketing)/about/page.tsx): Use for organizing related routes without affecting URLs. Helpful for applying different layouts to different sections of your app.

Parallel Routes (@analytics/page.tsx): Use when you need to render multiple independent sections simultaneously. Great for dashboards and complex layouts.

Intercepting Routes ((..)photo/[id]/page.tsx): Use for modal-style interactions where you want to show content without fully navigating away. Perfect for image galleries and quick previews.

API Routes (/api/users/route.ts): Use for creating backend functionality within your Next.js app. Ideal for form submissions, authentication, and data processing.

The key to mastering Next.js routing is understanding that each pattern solves specific problems. Start with static and dynamic routes, then gradually incorporate more advanced patterns as your application's complexity grows.


This guide provides the foundation for understanding Next.js 15. In the next article, we'll dive deeper into data fetching, server components, and the powerful features that make Next.js a game-changer for React developers. The journey from React to Next.js is about embracing a more structured, optimized approach to building web applications while keeping the React patterns you already love.

Top comments (8)

Collapse
 
johnbrindi profile image
johnbrindi

This is really simplified. Thank you Gita🙏

Collapse
 
fonyuygita profile image
Fonyuy Gita

Welcome🙇🏿‍♂️

Collapse
 
kiwanacollins profile image
kiwana collins

You have made me love next js

Collapse
 
sebastien_ngam_1fb9995092 profile image
Sebastien Ngam

And now i am anxiously waiting for part II of this

Collapse
 
iws_technical_a9b612b1a53 profile image
iws technical

thank you very much

Collapse
 
fonyuygita profile image
Fonyuy Gita

Thank you

Collapse
 
abdul_fadiga_1f402d165920 profile image
Abdul Fadiga

Thank you for this very helpful

Collapse
 
fonyuygita profile image
Fonyuy Gita

Weicome