Courses Curriculum Cities Blog Enroll Now
Next.js Full-Stack · Day 1 of 5 ~40 minutes

Day 1: Next.js App Router: Pages, Layouts, and Routing

Set up a Next.js 14 app with the App Router, create nested layouts, dynamic routes, and understand how server and client components differ.

1
Day 1
2
Day 2
3
Day 3
4
Day 4
5
Day 5
What You'll Build

A Next.js 14 app with a public landing page, a dashboard section with a shared layout, dynamic blog post pages, and working navigation — all using the App Router.

1
Section 1 · 8 min

Create Your Next.js App

Next.js is the leading React framework for production apps. The App Router (introduced in Next.js 13) uses the app/ directory and React Server Components by default. This is the modern way to build Next.js apps.

bashterminal
# Create a new Next.js app
npx create-next-app@latest my-app --typescript --tailwind --app --src-dir

# Prompts:
# Would you like to use ESLint? Yes
# Would you like to use import alias? Yes (@/*)

cd my-app && npm run dev
# Open http://localhost:3000
Project Structure
src/app/
All routes live here. Each folder = a URL segment
layout.tsx
Persistent shell (nav, footer) that wraps all pages
page.tsx
The UI for a route. Required for a route to be accessible
loading.tsx
Shown while page is loading. Uses React Suspense automatically
error.tsx
Error boundary for the route segment
2
Section 2 · 10 min

Server vs Client Components

This is the most important concept in Next.js 14. By default, all components are Server Components — they render on the server and send HTML. Client Components run in the browser and can use hooks and events.

typescriptsrc/app/page.tsx (Server Component)
// No 'use client' = Server Component by default
// Can: fetch data, access DB directly, use async/await
// Cannot: use useState, useEffect, onClick, browser APIs

async function getPosts() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=5')
  return res.json()
}

export default async function Home() {
  const posts = await getPosts()  // direct async in server component

  return (
    <main>
      <h1>Latest Posts</h1>
      {posts.map((post) => (
        <div key={post.id}>{post.title}</div>
      ))}
    </main>
  )
}
typescriptsrc/components/Counter.tsx (Client Component)
'use client'  // This makes it a Client Component

import { useState } from 'react'

export default function Counter() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
}
3
Section 3 · 12 min

Dynamic Routes and Nested Layouts

Dynamic routes use brackets: [slug]. Nested layouts let you wrap sections of your app (like a dashboard) in their own persistent UI without affecting other pages.

textroute structure
src/app/
├── page.tsx              → /
├── layout.tsx            → root layout (nav + footer)
├── blog/
│   ├── page.tsx          → /blog
│   └── [slug]/
│       └── page.tsx      → /blog/my-post
└── dashboard/
    ├── layout.tsx        → dashboard sidebar layout
    ├── page.tsx          → /dashboard
    └── settings/
        └── page.tsx      → /dashboard/settings
typescriptsrc/app/blog/[slug]/page.tsx
interface Props {
  params: { slug: string }
}

export default async function BlogPost({ params }: Props) {
  // params.slug = whatever is in the URL
  const { slug } = params

  return (
    <article>
      <h1>Post: {slug}</h1>
    </article>
  )
}

// Generate static pages at build time
export async function generateStaticParams() {
  return [{ slug: 'hello-world' }, { slug: 'getting-started' }]
}
4
Section 4 · 10 min

Link, Navigation, and Metadata

Use Next.js's Link component for client-side navigation. Use the Metadata API for SEO — it statically generates <head> tags without needing a separate library.

typescriptsrc/app/blog/[slug]/page.tsx
import { Metadata } from 'next'
import Link from 'next/link'

// Dynamic SEO metadata
export async function generateMetadata({ params }: Props): Promise<Metadata> {
  return {
    title: `${params.slug} | My Blog`,
    description: `Read about ${params.slug}`,
    openGraph: { title: params.slug, type: 'article' }
  }
}

export default function Nav() {
  return (
    <nav>
      <Link href="/">Home</Link>
      <Link href="/blog" prefetch={true}>Blog</Link>
      <Link href="/dashboard">Dashboard</Link>
    </nav>
  )
}

What You Learned Today

  • Created a Next.js 14 app with the App Router and understood the file-based routing system
  • Differentiated Server Components (async, direct DB access) from Client Components (hooks, events)
  • Built dynamic routes with [slug] and nested layouts for sections like dashboard
  • Used the Metadata API for automatic SEO without a third-party library
Your Challenge

Go Further on Your Own

  • Add a loading.tsx file to the blog route and test the Suspense loading state
  • Create a (marketing) route group that shares a layout without adding a URL segment
  • Add usePathname() in a client component to highlight the active nav link
Day 1 Complete

Nice work. Keep going.

Day 2 is ready when you are.

Continue to Day 2
Course Progress
20%

Want live instruction and hands-on projects? Join the AI bootcamp — 3 days, 5 cities.

Finished this lesson?