Skip to content

Next.js Basics

Before building real routes, you need a mental model of how Next.js turns files into pages and requests into HTML. This lesson covers pages, layouts, components, and the basic request lifecycle in the App Router.

How a Request Becomes a Page

When a browser requests a URL like /blog, Next.js maps that URL to a folder inside app/ (in this case app/blog/), finds the nearest page.tsx file, renders it (along with any parent layout.tsx files) on the server, and sends back HTML. If the page or any component inside it is an async function, Next.js awaits it before rendering, which is how Server Components fetch data directly.

After the initial HTML loads, Next.js hydrates only the parts of the page that are Client Components (marked with "use client"), attaching event listeners so they become interactive. Everything else stays as static, non-interactive HTML, which keeps the amount of JavaScript sent to the browser small.

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

// app/page.tsx
export default function HomePage() {
  return <h1>Hello, Next.js</h1>;
}

Every App Router project needs a root layout.tsx that renders <html> and <body>. The page.tsx files are rendered inside {children}.

The Two Files Every Route Needs

app/
  layout.tsx   // required at the root: wraps <html> and <body>
  page.tsx     // required per route: the actual UI for that URL
  • layout.tsx renders shared UI and must render its children prop somewhere.
  • page.tsx renders the unique content for a specific route.
  • Components inside app/ are Server Components by default — no "use client" needed unless you use state or browser APIs.
  • Any component can be async if it is a Server Component, allowing direct await calls for data fetching.

Next.js Basics Cheat Sheet

Core files and concepts you'll use in nearly every Next.js project.

File / Concept Meaning
app/layout.tsx Root layout; required, renders <html>/<body>
app/page.tsx The homepage route (/)
app/about/page.tsx The /about route
Server Component Default; runs on the server, can be async
Client Component Opt-in via "use client"; runs in the browser too
Hydration Attaching event listeners to server-rendered HTML
next dev Starts the local development server

Server and Client Components at a Glance

In the App Router, every component is a Server Component unless it explicitly opts out with a "use client" directive at the top of the file. Server Components can read files, query databases, and call await fetch() directly in their body, since that code never runs in the browser.

Client Components are needed whenever you use useState, useEffect, event handlers like onClick, or browser-only APIs. Later lessons dedicate full sections to this distinction, but it is important to internalize early because it affects how you structure every component you write.

  • Default (no directive) → Server Component: can be async, cannot use hooks or event handlers.
  • "use client" at the top of the file → Client Component: can use hooks, cannot be async.
  • Server Components can render Client Components, and pass them serializable props.

Running the Development Server

Every Next.js project includes a dev script in package.json that starts a local development server with fast refresh, so changes to your files appear in the browser almost instantly without a full page reload.

npm run dev
# or
npx next dev

# Server starts on http://localhost:3000

Fast Refresh preserves component state across most edits, which makes iterating on UI significantly faster than a full reload.

Common Mistakes

  • Forgetting that a root layout.tsx is required and must render {children}.
  • Adding "use client" to every component out of habit, losing the performance benefits of Server Components.
  • Trying to use useState inside a Server Component and getting a build error.
  • Not restarting the dev server after changing next.config.js.

Key Takeaways

  • Next.js maps URLs to folders inside app/, rendering the nearest page.tsx.
  • layout.tsx files wrap page.tsx files and any deeper nested routes.
  • Components are Server Components by default and can be async to fetch data directly.
  • Client Components opt in via "use client" and are needed for interactivity.
  • npm run dev starts a local server with fast refresh for quick iteration.

Pro Tip

Start every new Next.js feature as a Server Component, and only add "use client" to the smallest possible component once you actually need state, effects, or event handlers — this keeps your client-side JavaScript bundle lean.