All articles
TECHNOLOGY3 October 2025Rue Johnson

Next.js: Building Modern Web Apps

Next.js is the React framework for production. Server components, static export, file-based routing, and API routes: everything you need to ship, nothing you do not.

TechnologyNext.jsReactFrontend
Next.js: Building Modern Web Apps

Next.js

Building Modern Web Apps

The React Framework for Production:

React is a library. Next.js is a framework. The distinction matters. React gives you components, state management, and a virtual DOM. Next.js gives you routing, server-side rendering, static site generation, API routes, image optimization, and a build pipeline that produces production-ready output. Without Next.js, every React project reinvents these essentials. With Next.js, you start building features immediately because the infrastructure decisions are already made.

This site, majorlinkx.com, is built with Next.js. We use static export (output: 'export' in next.config.js) to generate static HTML, CSS, and JavaScript files that deploy to S3 with CloudFront in front. No server to maintain. No Node.js process to monitor. The build step outputs a directory of files and those files serve globally at edge speeds. For a business portfolio site, this is the correct architecture: fast, cheap, and impossible to crash because there is nothing running.

SSR vs SSG vs ISR: Pick the Right One:

Next.js offers three rendering strategies, and choosing the right one per page is the most important architectural decision you make. Static Site Generation (SSG) renders pages at build time. The HTML is generated once, cached at the edge, and served to every visitor instantly. This is ideal for marketing pages, blog posts, documentation, and any content that does not change per request. Server-Side Rendering (SSR) generates HTML on every request, which is necessary for personalized content, authenticated dashboards, and pages that depend on request-time data like cookies or headers.

Incremental Static Regeneration (ISR) is the middle ground: pages are statically generated but revalidate after a configurable interval. A blog post can revalidate every 60 seconds, meaning the first visitor after 60 seconds triggers a background rebuild while still seeing the cached version. We use SSG for client portfolio sites, SSR for authenticated applications, and ISR for content that updates periodically like pricing pages or event listings. Choosing the wrong strategy means either serving stale data or paying for unnecessary server compute.

App Router and Server Components:

The App Router is Next.js's current routing architecture, and server components are its defining feature. Server components run on the server (or at build time for static export), fetch data, and send rendered HTML to the client. No JavaScript bundle for data fetching. No loading spinners while the client fetches from an API. The HTML arrives fully rendered. Client components handle interactivity: form inputs, click handlers, animations. The mental model is clear: server components for data, client components for interaction.

File-based routing in the App Router uses directory structure to define routes. app/blog/page.tsx serves /blog. app/blog/[slug]/page.tsx serves /blog/terraform-dos-and-donts. Layouts wrap nested routes and persist across navigation. Loading and error states are handled with loading.tsx and error.tsx files at each route level. This convention-based routing eliminates the need for a router configuration file and makes the URL structure visible in your file tree. We enforce this pattern across all our Next.js projects because it makes the codebase navigable without documentation.

How We Build Client Sites:

Our standard Next.js stack for client sites: TypeScript for type safety, Tailwind CSS for styling with a custom design system defined in tailwind.config.js, Framer Motion for animations, and our atomic design component library (atoms, molecules, organisms, templates). State management uses React Context for global state and local useState for component state. We avoid Redux unless the application has genuinely complex client-side state that React Context cannot handle cleanly, which is rare for most business applications.

The build and deploy pipeline is straightforward: push to main triggers a GitHub Actions workflow that runs the build, validates the output, and syncs the static files to S3. CloudFront invalidation ensures the new version propagates to edge locations within minutes. Total deployment time from git push to live site: under three minutes. Total hosting cost: typically under $5 per month for S3 and CloudFront. Total server maintenance: zero. This is the architecture we recommend for any business that needs a fast, reliable web presence without ongoing infrastructure management.