Migrate to RunxBuild today!! Deploy More while Spending Less

Calculate your savings
unxBuild

Next.js Setup: From create-next-app to a Route You Can Actually Deploy

Sean

Platform Writer

Sep 20, 2026
8 min read

Setting up Next.js starts with one command, npx create-next-app@latest, which scaffolds TypeScript, the App Router, ESLint and a default next.config.js in under a minute. The part tutorials skip is everything after: which config options actually matter, where environment variables live, how to add a real route and an API handler that does something, and what npm run build produces versus npm run dev. This post walks through the whole path, from the scaffold command to a route running on a live URL, so the project you start today is the one you deploy this week, not a folder that only runs on your laptop.

Next.js Setup: From create-next-app to a Route You Can Actually Deploy

Every Next.js tutorial nails the first five minutes: run the command, answer the prompts, see the welcome page. Then it stops, because the interesting decisions, App Router versus Pages Router, where secrets live, what next.config.js is actually for, come after the scaffold, not during it. And almost none of them mention deploying the thing, which is the only step that turns a local dev server into a website. This post covers the setup decisions and finishes where the tutorials should: a live route.

Table of contents

What create-next-app actually decides for you

The create-next-app command asks four or five questions and every answer changes the shape of the project. Saying yes to TypeScript adds a tsconfig.json and renames files to .tsx. Saying yes to the App Router puts routing under app/ with file-based page.tsx and layout.tsx files instead of pages/. Turbopack is now the default bundler for both dev and build, which is worth knowing before you go looking for a webpack config that no longer exists by default.

npx create-next-app@latest my-app --typescript --app --eslint
cd my-app
npm run dev

The generated package.json gives you four scripts: dev, build, start, lint. dev runs the development server with fast refresh; build produces an optimized production build; start serves that build; lint runs ESLint. Treat build then start as the two commands that tell you the truth about what ships, because dev hides some of the errors that only show up in a production build.

The App Router layout you just got

Under App Router, app/layout.tsx wraps every page and is where you set the <html> tag, global fonts and any shared providers. app/page.tsx is the home route. A folder becomes a URL segment automatically: app/about/page.tsx serves /about, and app/blog/[slug]/page.tsx serves a dynamic route with slug available as a parameter.

  • layout.tsx wraps its segment and everything below it, so shared navigation belongs at the root, not repeated on every page.
  • loading.tsx shows automatically while a route’s data is fetching, no manual spinner state required.
  • error.tsx catches errors thrown in that segment and renders a fallback instead of a blank screen.
  • Route groups, folders in parentheses like (marketing), organize routes without adding a URL segment.

This structure means routing decisions are file placement decisions. Get the folder right and the URL, the shared layout and the error boundary follow from it.

TypeScript, environment variables, and next.config.js

TypeScript setup is mostly automatic: rename a file to .ts or .tsx, run next dev, and Next.js installs the dependencies and writes tsconfig.json itself. The one setting worth checking is strict: true, which the default config already sets and which is worth keeping rather than loosening the first time a type error is inconvenient.

Environment variables live in .env.local for values you never commit, and any variable prefixed NEXT_PUBLIC_ gets inlined into the browser bundle at build time; everything else stays server-only. That prefix is a security boundary, not a convention, so a database URL or API secret should never carry it.

# .env.local
DATABASE_URL=postgres://user:pass@host:5432/appdb
NEXT_PUBLIC_SITE_NAME=My App

next.config.js is where you set images.remotePatterns for external image domains, redirects() and rewrites() for URL rules, and output: standalone if you want a minimal, self-contained build for a container. Most projects need none of these on day one, which is why the default file is nearly empty; add options as a real requirement shows up.

A first route and an API handler that does something

A route handler under app/api/ responds like any backend endpoint. This one reads a query parameter and returns JSON, which is the shape most first integrations need.

// app/api/hello/route.ts
import { NextRequest, NextResponse } from "next/server";

export async function GET(request: NextRequest) {
  const name = request.nextUrl.searchParams.get("name") ?? "world";
  return NextResponse.json({ message: `Hello, ${name}` });
}

A page that calls it on the server, rather than fetching from the browser after load, keeps the response in the initial HTML and avoids a loading flash.

// app/greeting/page.tsx
export default async function GreetingPage() {
  const res = await fetch("http://localhost:3000/api/hello?name=RunxBuild", { cache: "no-store" });
  const data = await res.json();
  return <p>{data.message}</p>;
}

That pair, a route handler and a server component that calls it, is the smallest complete backend loop in Next.js. Everything from a contact form to a dashboard extends this pattern.

The build you’ll actually ship

npm run build is the step that catches what dev mode forgives: type errors, unused variables under strict linting, and pages that fail to prerender because they call browser-only APIs during the server render. Run it before every deploy, not just in CI, so the first time you see a build error is not on a Friday afternoon push.

The build output tells you the shape of each route: static, server-rendered, or an API route. A marketing page with no data fetching gets prerendered to static HTML at build time; a page with fetch calls or cookies() gets rendered per request. Reading that table once explains why one page loads instantly and another has a visible network round trip.

  • Static routes ship as HTML, fastest and cheapest to serve.
  • Server-rendered routes run on every request, needed for personalized or frequently changing data.
  • API routes are the backend endpoints your app or other services call.

Deploying what you just built

A Next.js app needs a host that runs the build as a live process, not a folder of static files, because the App Router’s server components and API routes execute on request. Push the repository, let the build run in the same place it deploys, and check the environment variables made it into the new environment before you check anything else, since a missing DATABASE_URL is the single most common first-deploy failure.

On RunxBuild, a Next.js project deploys from the GitHub repository with the build log visible, environment variables set per service, and a live route on push. See how the App Router’s server-run pieces map onto a web service rather than a static site, and read how to run a Next.js app locally first if the dev server itself is still the part giving you trouble.

How this fits the rest of the stack

The setup above gets you to a route that runs somewhere, but sizing the thing that runs it is a separate question: how much memory the process needs at idle, whether a database sits beside it, and what the bandwidth looks like once real traffic shows up. Model that combination in the RunxBuild hosting calculator before picking a plan, rather than guessing and re-sizing later. Next.js on RunxBuild covers the build-from-repository path this post ends on, with build logs, environment variables and rollback included. When the API route and the page are both working locally, the dashboard is where the repository gets connected and the first deploy runs.

Useful related references:

FAQ

Do I need TypeScript to set up Next.js?

No, but it is the default in create-next-app and worth keeping. TypeScript catches prop mismatches and missing return values before they reach the browser, and the setup cost is close to zero since Next.js installs the dependencies and writes tsconfig.json for you the first time you rename a file to .tsx.

What is the difference between App Router and Pages Router?

App Router, under app/, supports server components, layouts, loading and error states, and route handlers as first-class features. Pages Router, under pages/, is the older model with getServerSideProps for data fetching. New projects should use App Router; existing Pages Router apps do not need to migrate to get value from Next.js.

Where should environment variables live in Next.js?

In .env.local for values you never commit. Any variable prefixed NEXT_PUBLIC_ is inlined into the browser bundle at build time and is not a secret; everything without that prefix stays server-only. Never put a database URL or API key behind the NEXT_PUBLIC_ prefix.

Do I need next.config.js for a basic setup?

No. The default, nearly empty config works for a standard site. Add images.remotePatterns, redirects(), rewrites(), or output: standalone only when a specific requirement, an external image host or a container build, actually needs them.

How do I know if my Next.js app is ready to deploy?

Run npm run build locally and confirm it completes without errors, since dev mode forgives things production does not. Check that every environment variable the app reads locally is also set in the deploy target, and that the build’s route table matches what you expect for static versus server-rendered pages.

#nextjs setup#create-next-app#next.config.js#app router tutorial#deploy nextjs app