Setting up a project with create-next-app

Every CLI flag that shapes the project, the folder layout it produces, and which config files you will actually edit.

create-next-app and its flags

npx create-next-app@latest my-app \
  --ts --app --eslint --tailwind --src-dir --turbopack \
  --import-alias "@/*"

cd my-app
npm run dev            # http://localhost:3000
npm run build          # production build into .next/
npm start              # serve the build (never in development)
FlagEffect
--ts / --jsTypeScript or JavaScript source files
--appApp Router (app/) instead of the Pages Router
--src-dirPut the router inside src/ rather than the project root
--eslintAdd the Next.js ESLint config and a lint script
--tailwindWire up Tailwind and a global stylesheet
--import-aliasMap @/* to the root or to src/
--turbopackUse Turbopack as the dev and build bundler
  • The CLI writes a project and prints the next steps. It does not update itself afterwards; the versions it pinned live in package.json, so commit the lockfile.
  • Answer in the interactive prompt or pass the flags — both work, and the flags make the setup reproducible in a script.
  • Pin the Node version with an engines field or an .nvmrc. A build server on an older Node is one of the most common CI failures.
  • A tutorial written for the Pages Router will not match what this generates. Check the import path in any example before copying it.

The folder layout

my-app/                     (with --src-dir)
  src/app/
    layout.tsx              required root layout: renders html and body
    page.tsx                the / route
    globals.css             imported once by the root layout
    favicon.ico
  public/                   served from /, copied unprocessed
  next.config.ts            framework configuration
  tsconfig.json             paths: { "@/*": ["./src/*"] }
  eslint.config.mjs
  package.json

Routes are created by file names, not by registration. Only page, layout, route, loading, error, not-found and a few siblings become routes; a helper file next to a page is just a module.

  • With --src-dir the router lives in src/app; without it, app/ sits at the project root. The import alias must point at whichever one you chose.
  • public/logo.png is served as /logo.png, with no hashing and no optimisation. An image imported from code goes through the build instead.
  • Files imported by a server component stay on the server, so a database client in src/lib/db.ts never reaches the browser bundle.
  • Only add 'use client' where you need state, events or browser APIs. Everything else stays a server component by default.

The config files you will edit

// next.config.ts
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  reactStrictMode: true,
  images: {
    remotePatterns: [{ protocol: 'https', hostname: 'images.example.com' }]
  },
  async redirects() {
    return [{ source: '/old-guide', destination: '/guides/intro', permanent: true }]
  }
}

export default nextConfig
  • The config file is executed by Node at build time, so it cannot read anything about an incoming request. Per-request behaviour belongs in middleware.
  • next dev runs Turbopack for a fast inner loop; next build can use it too. If one of your loaders is not supported yet, that is a signal to check, not a reason to avoid the bundler.
  • next build prints a route table that marks each route static or dynamic. Read it after a change — it is the fastest way to see an accidental per-request render.
  • The TypeScript paths entry and the Next.js alias must agree. A mismatch shows up as a module-not-found error even though the file exists.
  • redirects and rewrites in the config run before your routes, which makes them the cheapest place to handle a URL migration.
💡
The root layout is required and is the only place that may render html and body. Every route under app/ depends on it, so a build failure across the whole site usually starts there.

FAQ

App Router or Pages Router?
The App Router for anything new: server components, nested layouts, streaming and server actions all live there. The Pages Router still works and existing apps can stay on it, but new examples and features assume app/.
Is Turbopack ready to use?
It is the default for development and is used by the build as well. If a specific webpack loader or plugin is not supported, the failure is explicit and you can fall back for that build — but check first that the plugin is still needed.

Routing, links and navigation Dynamic routes, params and metadata

Last refreshed 2026-09-18.