Setup

Create a Project

npx create-next-app@latest my-app

The CLI asks a few questions. Recommended answers:

QuestionAnswer
TypeScript?Yes
ESLint?No (next lint is deprecated in v16, use Biome or oxlint)
Tailwind CSS?Yes
src/ directory?No (simpler for smaller projects)
App Router?Yes
Turbopack for dev?Yes (default in v16)
Import alias?@/* (default)
cd my-app
npm run dev

Open http://localhost:3000. The dev server uses Turbopack for fast refresh.

Project Structure

my-app/
  app/
    layout.tsx       # Root layout (html, body, global providers)
    page.tsx         # Home page (/)
    globals.css      # Global styles, Tailwind imports
    favicon.ico      # Favicon
  public/            # Static assets (images, fonts)
  next.config.ts     # Next.js configuration
  tailwind.config.ts # Tailwind configuration
  tsconfig.json      # TypeScript configuration
  package.json

Root Layout

// app/layout.tsx
import type { Metadata } from "next";
import "./globals.css";

export const metadata: Metadata = {
  title: "My App",
  description: "Built with Next.js",
};

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

Home Page

// app/page.tsx
export default function Home() {
  return (
    <main className="flex min-h-screen items-center justify-center">
      <h1 className="text-4xl font-bold">Hello Next.js</h1>
    </main>
  );
}

Turbopack Dev Server

Turbopack is the default bundler since Next.js 16. It’s Rust-based and significantly faster than Webpack.

# Turbopack is used by default for `next dev`
npm run dev

# Explicitly enable (if on v15)
npx next dev --turbopack
MetricWebpackTurbopack
Cold start~3-5s~1-2s
Fast Refresh~200-500ms~50-100ms
Route compile~500ms-2s~100-300ms

Tip: Turbopack is for dev only. Production builds (next build) still use Webpack in v15 and transitioning to Turbopack in v16+.

Tailwind CSS v4

New projects created with create-next-app use Tailwind CSS v4, which uses a CSS-first configuration approach.

/* app/globals.css */
@import "tailwindcss";

That’s it. No tailwind.config.ts needed for basic usage. Tailwind v4 auto-detects your source files.

Gotcha: If you’re following older tutorials, they’ll reference tailwind.config.js with content arrays and theme.extend. Tailwind v4 doesn’t need any of that for standard setups. Only create a config if you need custom plugins or advanced theme overrides.

next.config.ts

// next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  // Common options:
};

export default nextConfig;

Common configuration options:

const nextConfig: NextConfig = {
  // Enable image optimization for external sources
  images: {
    remotePatterns: [
      { protocol: "https", hostname: "images.example.com" },
    ],
  },

  // Environment variables available to the client
  env: {
    NEXT_PUBLIC_API_URL: process.env.API_URL,
  },

  // Redirects
  async redirects() {
    return [
      { source: "/old-page", destination: "/new-page", permanent: true },
    ];
  },
};

Adding Your First Route

Create a new page by adding a page.tsx file in a new folder:

// app/about/page.tsx
export default function About() {
  return (
    <main className="p-8">
      <h1 className="text-3xl font-bold">About</h1>
      <p className="mt-4 text-gray-600">This is the about page.</p>
    </main>
  );
}

Visit http://localhost:3000/about. No imports, no router configuration. The filesystem is the router.

Scripts Reference

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  }
}
ScriptPurpose
devStart dev server with Turbopack and hot reload
buildCreate production build
startRun production server (after build)
lintRun linter (deprecated in v16, consider alternatives)

Next: First App | App Router