Overview
Next.js is the React framework that provides the production infrastructure that React alone does not — server-side rendering, static site generation, file-based routing, API routes, image optimisation, and the build tooling that produces optimised, deployable applications. Where React is a UI library for building component-based interfaces, Next.js is a complete framework that determines how those components are rendered, how pages are routed, how data is fetched, and how the application is built and deployed.
The practical significance of Next.js in production web applications is substantial. Server-side rendering produces pages that load fast and index well in search engines — the HTML that a server-rendered Next.js page delivers to the browser is immediately readable content rather than an empty shell that JavaScript must populate. Static generation produces pages that are pre-built at deploy time and served from a CDN, delivering the fastest possible time-to-first-byte for content that does not change on every request. The App Router introduced in Next.js 13 adds React Server Components — components that render on the server, fetch data directly without API round trips, and send only the rendered HTML and minimal JavaScript to the client.
Next.js is our primary frontend framework for the web applications we build. Whether the application is a customer-facing product, an internal operational tool, a data dashboard, or a marketing site, Next.js provides the rendering flexibility, the routing infrastructure, and the full-stack capabilities that production web applications require.
Next.js Core Concepts We Work With
App Router and React Server Components. The App Router — introduced in Next.js 13 and now the default — organises the application into a app/ directory where folders define routes and files define page components, layout components, loading states, and error boundaries. React Server Components render on the server and can fetch data directly from databases or APIs without exposing the data fetching logic to the client and without the waterfall of client-side data fetching that traditional React applications produce.
Server Components render their output — HTML — on the server and send it to the client. They do not include JavaScript in the client bundle for their own rendering, making the client-side JavaScript bundle smaller. They can directly access server-side resources: databases, file systems, environment variables, and APIs with secrets. A dashboard page that needs data from multiple sources renders those sources directly in server components — no API layer required, no loading state in the browser, data present in the initial HTML.
Client Components — marked with 'use client' — are the components that require browser interactivity: event handlers, React state, browser APIs. The App Router model encourages a composition pattern where server components handle data fetching and static rendering while client components handle the interactive elements that require browser-side execution.
Layouts: the layout.tsx file in each route segment that wraps child pages and persists across navigation within its route tree. The root layout that wraps the entire application — the HTML and body elements, the global providers, the navigation elements that should not be re-rendered on every page navigation.
Loading and error boundaries: loading.tsx and error.tsx files that define the loading state and error UI for each route segment, automatically used by Next.js's Suspense integration during data fetching and when component errors are caught.
Data fetching patterns. Next.js provides multiple data fetching approaches, each appropriate to different content and interactivity requirements.
Server Component data fetching: async Server Components that await data fetch calls directly — the fetch() call or the database query that happens during server-side rendering, with the result available as props to child components without client-side loading states. Next.js extends the native fetch() API with caching and revalidation options that control whether the response is cached, for how long, and when it is revalidated.
Static generation with generateStaticParams: pages for which the possible routes are known at build time are pre-rendered during the build. Blog posts, product pages, documentation — any content-driven page where the set of possible slugs can be enumerated at build time and the content does not change on every request. Static pages are served from CDN edge nodes with minimal latency.
Incremental Static Regeneration: static pages with a revalidation period that causes Next.js to regenerate the page in the background after the specified time interval, delivering the cached version while the regeneration runs. The pattern that provides near-static performance with content that updates on a defined schedule rather than requiring a full rebuild for content updates.
Server Actions: the Next.js mechanism for handling form submissions and mutations from React Server Components — server-side functions that the client calls without an explicit API endpoint, handling the HTTP POST internally. The pattern for progressive enhancement where forms work without JavaScript and are enhanced when JavaScript is available.
Client-side data fetching: React Query or SWR for data that must be fetched on the client — interactive dashboards that update in response to user actions, data that needs to stay fresh through polling or WebSocket subscription, user-specific data fetched after authentication on the client.
Routing. The App Router's file-system-based routing where the folder structure under app/ directly defines the URL structure.
Dynamic routes: [slug] and [...segments] folder naming for routes with dynamic parameters — the blog post page at app/blog/[slug]/page.tsx, the catch-all route at app/docs/[...path]/page.tsx.
Route groups: (groupName) folders that group routes without affecting the URL structure — organising routes that share a layout, separating the public and authenticated route trees, grouping marketing pages separately from application pages.
Parallel routes and intercepting routes: the App Router's advanced routing features for complex UI patterns — the dashboard with independently loaded sidebar and main content panels, the modal that intercepts navigation to show content in an overlay without leaving the current page.
Middleware: Next.js middleware that runs before every request — the authentication check that redirects unauthenticated requests to the login page, the locale detection that redirects to the appropriate language path, the A/B testing logic that assigns users to experiments.
API routes. Next.js route handlers at app/api/*/route.ts that define HTTP endpoints — GET, POST, PUT, DELETE, and other methods handled by exported async functions that receive a Request and return a Response.
Route handler uses: webhook receivers that process incoming events from external services, API endpoints that the frontend fetches for dynamic data, authentication callbacks for OAuth flows, form submission endpoints. Route handlers have access to the full Node.js runtime and can use server-side libraries, access environment variables, and connect to databases.
For applications that use Next.js as a full-stack framework, route handlers are the API layer alongside Server Actions — the endpoints that mobile clients, external integrations, and client-side JavaScript calls.
Image optimisation. The Next.js Image component that automatically optimises images — serving WebP or AVIF formats to browsers that support them, resizing images to the dimensions they are actually displayed at, lazy loading images below the fold, and generating the blur placeholder that prevents layout shift during image loading.
Remote image configuration: the next.config.js image domain allowlist that permits the Next.js image optimisation pipeline to process images from external sources — CDNs, S3 buckets, CMS image domains.
Metadata and SEO. The App Router's metadata API for server-rendered HTML metadata — the metadata export or generateMetadata async function in page and layout components that produce <title>, <meta>, Open Graph, and Twitter card tags from component data.
Dynamic metadata: generateMetadata that fetches content data and uses it to produce page-specific metadata — the blog post title and description from the post content, the product name and image from the product record.
Structured data: JSON-LD scripts in page components for rich search engine result types — article structured data, product structured data, FAQ structured data, breadcrumb structured data.
Authentication. Next.js authentication patterns with NextAuth.js (Auth.js) for the common authentication flows — OAuth providers, email magic link, credentials-based authentication.
Session management with NextAuth: the session provider that makes session data available to client components, the getServerSession() call in Server Components that accesses session data without client-side API calls, the middleware that protects authenticated routes.
Custom authentication: JWT-based authentication without NextAuth for applications with specific authentication requirements — the API route that issues JWTs, the middleware that validates JWTs and attaches user data to requests, the client-side token storage and refresh logic.
Internationalisation. Multi-language Next.js applications with locale-based routing — the /en/, /nl/, language path structure with locale detection and redirect in middleware.
Deployment
Vercel. The platform built by the Next.js team, with native support for all Next.js features — Server Components, Server Actions, ISR, Middleware — with zero configuration. Preview deployments for every pull request, automatic production deployment on merge to main, the edge network that serves static assets and runs Middleware globally.
Self-hosted on VPS with Node.js. Next.js applications run as Node.js servers on VPS infrastructure — next build produces the optimised build, next start serves it. Nginx as the reverse proxy in front of the Node.js server for TLS termination, static asset serving, and request routing. systemd for process management. The self-hosted approach we use for our own applications.
Docker containerisation. Next.js applications packaged in Docker images for deployment to Kubernetes or other container platforms. Multi-stage Dockerfile that produces a minimal production image — the build stage that compiles the Next.js application, the production stage that contains only the compiled output and the Node.js runtime.
Static export. For Next.js applications that do not use server-side features — next export produces a static site from static and statically generated pages, deployable to any static hosting — S3, Cloudflare Pages, Netlify — without a Node.js server.
Technologies Used
- Next.js 14/15 — framework version with App Router and React Server Components
- React 18/19 — UI component library and runtime
- TypeScript — type-safe component and application code
- Tailwind CSS — utility-first CSS framework for component styling
- React Query / TanStack Query — client-side data fetching and cache management
- SWR — lightweight client-side data fetching with revalidation
- NextAuth.js / Auth.js — authentication for Next.js applications
- Prisma / Drizzle — type-safe database ORM for Server Component data fetching
- Zod — runtime validation for API inputs and form data
- Vercel — hosted deployment platform with native Next.js support
- Docker — containerised deployment for self-hosted and Kubernetes environments
- Nginx — reverse proxy for self-hosted VPS deployments
Next.js as the Production Standard
React development without a framework is viable for small applications and development environments. For production web applications — with the SEO requirements, the performance expectations, the routing complexity, and the data fetching patterns that real applications have — Next.js provides the infrastructure that makes production-quality React development tractable. Server-side rendering, static generation, the App Router's data fetching model, image optimisation, and the deployment infrastructure that Vercel and self-hosting provide are not features that can be replicated easily without the framework.
Next.js is our default for web application frontends because it is the framework that takes React's component model and adds the production infrastructure that applications actually need.
The React Framework for Production
Next.js applications built with the App Router, Server Components, TypeScript, and the data fetching patterns appropriate to each page's content — delivering the performance, the SEO, and the developer experience that production web applications require.