Module 1: Getting Started with Next.js 16 — Installation, Project Structure & Your First Page

Module 1: Getting Started with Next.js 16 — Installation, Project Structure & Your First Page

AI Reading

Quick summary of this article

Learn how to install Next.js 16, understand the App Router project structure, run the development server and build your first page with TypeScript and Turbopack.

  • Next.js 16 requires Node.js 20.9+ and TypeScript 5.1+, and Turbopack is now the default bundler for both next dev and next build.
  • create-next-app scaffolds a project with the App Router, where every folder inside app/ maps to a URL segment.
  • app/layout.tsx is the root layout that wraps every page and must contain the <html> and <body> tags.
  • Every route needs a page.tsx file — a folder without one is simply not routable.

Complete Next.js 16 Series — Module 1 of 12 (Beginner → Advanced)

Next.js is the most widely used React framework for building production web applications. Version 16 is the biggest release in years: Turbopack is now the default bundler, React 19.2 powers the App Router, and the older Pages Router patterns are officially legacy. This series takes you from an empty folder to a deployed, authenticated, database-backed application using Next.js 16.4, TypeScript and Tailwind CSS 4.

Prerequisites: Node.js 20.9 or newer, npm 10+, and a working knowledge of JavaScript. React experience helps but is not mandatory — we cover the React 19 features you need as we go.

What Actually Changed in Next.js 16

Before you type a single command, here is what matters for a new project:

  • Turbopack is the default for next dev and next build. You no longer need the --turbopack flag.
  • Node.js 18 is no longer supported. The minimum is 20.9.0.
  • TypeScript 5.1+ is the minimum supported compiler.
  • Async request APIs are mandatory. params, searchParams, cookies() and headers() must all be awaited — the temporary synchronous compatibility from v15 is gone.
  • middleware.ts is deprecated in favour of proxy.ts, which runs on the Node.js runtime.
  • Partial Prerendering is configured through cacheComponents: true instead of the old experimental flag.

Creating Your First Project

Open a terminal and run:

npx create-next-app@latest nextjs16-course

The installer asks a series of questions. For this series, answer them like this:

Would you like to use TypeScript?          Yes
Would you like to use ESLint?              Yes
Would you like to use Tailwind CSS?        Yes
Would you like your code inside src/?      Yes
Would you like to use App Router?          Yes
Would you like to use Turbopack?           Yes
Would you like to customise the import alias?  No

Then start the development server:

cd nextjs16-course
npm run dev

Open http://localhost:3000 and you should see the default Next.js welcome screen. Edit src/app/page.tsx, save the file, and the browser updates in well under a second.

Understanding the Project Structure

This is the folder layout create-next-app produces:

nextjs16-course/
├── src/
│   └── app/
│       ├── favicon.ico
│       ├── globals.css
│       ├── layout.tsx
│       └── page.tsx
├── public/
├── next.config.ts
├── package.json
├── postcss.config.mjs
└── tsconfig.json

Each piece has one clear job:

  • src/app/ — the App Router. Every folder inside it becomes a URL segment.
  • src/app/layout.tsx — the root layout. It wraps every page in your application.
  • src/app/page.tsx — the home page, served at /.
  • src/app/globals.css — global styles, including the Tailwind import.
  • public/ — static assets served from /. public/logo.png is available at /logo.png.
  • next.config.ts — framework configuration.
  • tsconfig.json — TypeScript config, with @/ already mapped to src/.

Anatomy of the Root Layout

Open src/app/layout.tsx:

import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";

const geistSans = Geist({ variable: "--font-geist-sans", subsets: ["latin"] });
const geistMono = Geist_Mono({ variable: "--font-geist-mono", subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{ children: React.ReactNode }>) {
  return (
    <html lang="en">
      <body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
        {children}
      </body>
    </html>
  );
}

Three things to notice:

  1. A layout receives children — the matched page or nested layout.
  2. It renders the <html> and <body> tags. Only the root layout does this.
  3. It exports a metadata object. Next.js reads it and generates the <title> and <meta> tags for you, on the server, with no extra library.

Writing Your First Page

Replace the contents of src/app/page.tsx with a real page:

export default function HomePage() {
  const course = {
    name: "Complete Next.js 16",
    modules: 12,
    level: "Beginner to Advanced",
  };

  return (
    <main className="mx-auto max-w-2xl px-6 py-16">
      <h1 className="text-4xl font-bold tracking-tight">{course.name}</h1>
      <p className="mt-4 text-lg text-neutral-600">
        {course.modules} modules · {course.level}
      </p>
      <ul className="mt-8 space-y-2">
        <li>✅ Server Components by default</li>
        <li>✅ Turbopack builds</li>
        <li>✅ TypeScript end to end</li>
      </ul>
    </main>
  );
}

Save the file and refresh the browser. Note what you did not write: no import React, no ReactDOM.render, no client-side router setup. page.tsx default-exports a React component and Next.js handles routing, rendering and hydration.

That component is a Server Component. It runs on the server, never ships to the browser as JavaScript, and can be async — a topic we unpack properly in Module 5.

The Development Workflow

The generated package.json contains the scripts you will use every day:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "eslint"
  }
}
  • npm run dev — development server with Fast Refresh on port 3000.
  • npm run build — production build. Turbopack compiles, type-checks and prerenders.
  • npm start — serves the production build on port 3000.
  • npm run lint — ESLint with the Next.js flat config.

Run a production build now, even though the app is trivial. It catches type errors that the dev server tolerates:

npm run build

You will see Next.js report the route table, including a marker showing whether a route is static or dynamic:

Route (app)                   Size     First Load JS
┌ ○ /                         1.2 kB          106 kB
└ ○ /_not-found               0.8 kB          103 kB
○  (Static)  prerendered as static content

The ○ means / was prerendered to static HTML at build time. Visitors get a file straight from the edge with no server render. That happens automatically because this page uses no request-time data — and it is the single biggest reason Next.js apps are fast.

A Quick Note on Configuration

Configuration lives in next.config.ts, fully typed:

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  reactStrictMode: true,
};

export default nextConfig;

Leave it empty for now. We add image domains, output: "standalone" and cacheComponents in later modules.

Module 1 Recap

  • Next.js 16 needs Node.js 20.9+ and TypeScript 5.1+.
  • Turbopack is the default — no flags required.
  • Folders in src/app/ are URL segments; page.tsx makes a segment routable.
  • layout.tsx wraps pages and renders <html> and <body>.
  • Metadata is exported as a typed Metadata object.
  • Pages are Server Components by default and are statically prerendered when possible.

Next up — Module 2: layouts, nested routing, the Link component and the file conventions that power the App Router.

Leave a Reply

Your email address will not be published. Required fields are marked *