Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

The fastest reliable way to start a Next.js project is to install Node.js 20.9 or newer, run create-next-app, start the development server, and build features inside the generated app directory. The current starter uses the App Router, TypeScript, Tailwind CSS, ESLint, Turbopack and the @/* import alias by default. This guide takes you from an empty machine to a production build, explains the App Router versus Pages Router, and shows how to structure, test and deploy the result.

What Next.js provides

Next.js is a React framework for building full-stack web applications. It handles lower-level bundling and compilation so you can concentrate on routes, components, data and shipping. The current App Router is file-system based and uses React Server Components, Suspense and Server Functions. Both the App Router and the older Pages Router are supported; a new project should normally start with the App Router unless an existing codebase or library requires Pages Router conventions.

Prerequisites

Install a supported Node.js runtime

The current installation guidance requires Node.js 20.9 or newer. Use the official Node.js installer or a version manager, then verify both tools:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
node --version
npm --version

macOS, Windows (including WSL) and Linux are supported. If your version is older than 20.9, upgrade before creating the project; otherwise dependency installation or the development server may fail.

Choose a package manager

The examples use pnpm because the official guide presents it as a quick path. npm, Yarn and Bun work with equivalent commands. Install pnpm first if it is not available:

corepack enable
corepack prepare pnpm@latest --activate

Create the project

  1. Run the generator from the directory where you keep source code:
    pnpm create next-app@latest my-app --yes
  2. Enter the new directory:
    cd my-app
  3. Start the development server:
    pnpm dev
  4. Open http://localhost:3000 in a browser. Edit a file and save it; Next.js will refresh the page during development.

The --yes flag accepts the recommended defaults. If you omit it, the interactive wizard asks about TypeScript, linting, Tailwind CSS, the App Router, Turbopack and the import alias. Selecting those options produces the same modern baseline.

Equivalent commands

npx create-next-app@latest my-app
# or
yarn create next-app my-app
# or
bun create next-app my-app

Understand the generated files

A fresh project contains more files than the minimum, but these are the important pieces:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Path Purpose
app/layout.tsx Required root layout. Put shared HTML structure, metadata and site-wide UI here.
app/page.tsx Renders the / route.
app/globals.css Global styles imported by the root layout.
public/ Optional static assets, referenced with root-relative URLs such as /logo.svg.
next.config.* Optional Next.js configuration.
package.json Dependencies and scripts for development, builds and production serving.
tsconfig.json TypeScript compiler settings when TypeScript is enabled.

Replace the starter markup in app/page.tsx with your own page. Keep reusable site chrome in app/layout.tsx, and create additional route segments by adding folders and a page.tsx file.

Add routes with the App Router

Static routes

To create /about, add app/about/page.tsx:

export default function AboutPage() {
  return (
    <main>
      <h1>About</h1>
      <p>Information about the project.</p>
    </main>
  );
}

The folder name becomes the URL segment. A nested folder such as app/blog/page.tsx creates /blog.

Dynamic routes

Use square brackets for a variable segment. app/posts/[slug]/page.tsx can read the slug from route parameters:

type Props = { params: Promise<{ slug: string }> };

export default async function PostPage({ params }: Props) {
  const { slug } = await params;
  return <article>Showing post: {slug}</article>;
}

Keep route data loading in server components when possible. This avoids sending unnecessary JavaScript to the browser.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Layouts and loading states

A layout.tsx file wraps its segment and descendants, so navigation can preserve shared UI. Add loading.tsx beside a route to provide an immediate loading state while that segment renders. Add error.tsx for a route-level error boundary when you need a tailored recovery message.

Server and client components

App Router components are server components by default. They can fetch data and render HTML without shipping their implementation to the browser. Add the 'use client' directive at the top of a component only when it needs browser APIs, event handlers or client-side state:

'use client';

import { useState } from 'react';

export function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

Keep the client boundary as small as practical. A server page can render a client component, pass it serializable props and retain server-side data work.

App Router or Pages Router?

Question App Router Pages Router
Best starting point Modern default for new applications. Useful when following an existing Pages-based project.
Routing model Folders and files under app; layouts are built in. Folders and files under pages; uses the established Pages APIs.
React features Server Components, Suspense and Server Functions. Traditional client/server data-fetching APIs.
Migration concern May require learning server-component boundaries. Often the least disruptive choice for an existing application.

The official documentation supports both routers. Choose based on your team’s existing APIs, compatibility requirements and preferred conventions rather than mixing patterns casually. You can migrate sections over time, but each router has its own file and data-fetching rules.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Static assets, styling and configuration

Serve files from public

Create public/images/hero.jpg and reference it as /images/hero.jpg. Do not include public in the URL. Keep cacheable, public resources there; private files should not be exposed from this directory.

Use the generated Tailwind setup or your own CSS

The recommended starter enables Tailwind CSS and imports global styles from the root layout. You can also write ordinary CSS modules or global CSS. Keep global rules in the global stylesheet and component-specific rules in a CSS module to reduce accidental cross-page effects.

Environment variables

Store local values in .env.local and never commit secrets. Variables intended for browser code must use the NEXT_PUBLIC_ prefix; unprefixed values remain server-side. Configure the same names in your deployment platform before building.

Build and run the production version

  1. Stop the development server if necessary.
  2. Run the production compiler:
    pnpm build
  3. Serve the generated build locally:
    pnpm start
  4. Open http://localhost:3000 again and test the production behavior, including navigation, forms, images, environment variables and error states.

The generated package.json normally contains these scripts:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Script Use
next dev Development server with fast refresh; Turbopack is the current default bundler.
next build Creates an optimized production build and reports compile or route errors.
next start Serves that production build; run it only after a successful build.

Deployment checklist

  • Commit the project without .env.local, build output or secret keys.
  • Set production environment variables in the hosting service.
  • Run pnpm build in the deployment environment using Node.js 20.9 or newer.
  • Use the host’s start command, normally pnpm start, unless it provides a managed Next.js runtime.
  • Verify every route, dynamic parameter, form action, image and external API from the deployed URL.
  • Confirm that server-only code is not imported into client components and that browser-only APIs are behind a client boundary.

Troubleshooting common failures

“Node version is not supported”

Check node --version. Upgrade to 20.9 or newer, reopen your terminal, remove and reinstall dependencies, then retry the command.

Port 3000 is already in use

Stop the other process or select another port:

pnpm dev -- --port 3001

Changes are not appearing

Confirm you edited a file inside the project directory, check the terminal for compile errors and hard-refresh the browser. If the dependency tree is corrupted, stop the server, remove node_modules and the package-manager lockfile only if necessary, reinstall, and start again.

“useState” or window errors

The component is probably being treated as a server component. Add 'use client' at its top, or move the browser-only code into a small client component.

Production build fails but development works

Run pnpm build locally and read the first reported error. Common causes are missing deployment environment variables, invalid TypeScript, a server-only import in client code, or a route that relies on a development-only file.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability and cost considerations

Build with server components by default, limit client JavaScript, and use route-level loading and error files for predictable navigation. Test the exact production build rather than relying only on next dev. Hosting cost, caching behavior and regional latency depend on the provider and your application’s data services; Next.js itself does not prescribe one deployment platform.

Or skip the browser setup

If your Next.js workflow needs screenshots for previews, tests or documentation, ScreenshotNeo provides a single HTTP request instead of maintaining a browser automation stack. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and each response identifies the result with X-Page-Verdict and X-Billed headers.

API documentation is at https://screenshotneo.com/docs/. A basic call is:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
const buffer = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', buffer));

ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. Options include full-page lazy-image capture, CSS-selector element capture, dark mode, device presets, custom viewports, retina scale, PDF page settings, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, selectable cache TTLs, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage data and an OpenAPI specification. Existing parameter names used by other screenshot APIs are accepted to ease migration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan, and yearly billing provides two months free. Create a free ScreenshotNeo account to get started.

Frequently Asked Questions

Can I use JavaScript instead of TypeScript in Next.js?

Yes. The generator can create a JavaScript project; choose JavaScript in the interactive prompts instead of accepting the TypeScript default.

Do I have to use Tailwind CSS?

No. Tailwind is a recommended default, but CSS modules, global CSS or another styling system can be used.

Can a Pages Router project and an App Router project coexist?

A migration can contain both directories, but their routing and data APIs differ. Keep each route’s conventions clear and migrate deliberately.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why does my deployed app show an environment-variable error?

Local .env.local values are not automatically copied to a host. Add the required variables to the deployment provider and rebuild.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.