Frontend Frameworks

Next.js

Current Version
15.2
License
MIT
Rendering
SSR / SSG / ISR / RSC
Built by
Vercel

Next.js is the standard React framework for production web applications. Its combination of server-side rendering, static generation, React Server Components, and edge deployment capabilities makes it the right choice for a wide range of applications: marketing sites, SaaS products, eCommerce storefronts, and content platforms. The App Router (introduced in Next.js 13 and stable in 14+) represents a significant architectural evolution, bringing React Server Components to production and enabling fine-grained control over rendering strategy at the component level.

Axevate builds on Next.js across multiple service areas - AI-powered applications, eCommerce frontends, headless content sites, and this website itself. Our experience spans the full deployment stack: Vercel for managed deployment, Cloudflare Workers for edge-first architectures (via the wrangler adapter), and self-hosted Docker deployments on AWS. We've worked through the App Router migration challenges, the Server Components mental model shift, and the performance optimization work that separates fast Next.js applications from slow ones.


1App Router vs. Pages Router

The App Router is Next.js's current architecture, using the /app directory. It enables React Server Components (components that run on the server and send HTML to the client, with zero client-side JavaScript), Server Actions (server-side mutations called directly from client components), and nested layouts with independent loading states. The App Router is the recommended choice for all new Next.js projects.

The Pages Router (/pages directory) is the legacy architecture, still fully supported and appropriate for applications that haven't migrated. It uses getServerSideProps, getStaticProps, and getInitialProps for data fetching. If you have an existing Pages Router application, migration to App Router is incremental - both can coexist in the same project.

React Server Components change the mental model significantly. By default, components in the App Router are Server Components - they have no client-side JavaScript, can access server resources directly (databases, file system, environment variables), and don't increase the client bundle. 'use client' explicitly opts a component into the client bundle. Getting the boundary right - minimizing 'use client' while preserving interactivity - is the core skill in App Router development.

2Rendering Strategies

Next.js provides granular control over when and how content is rendered. Static rendering generates HTML at build time - fastest possible delivery, fully cacheable at CDN. Dynamic rendering generates HTML on every request - appropriate for personalized or frequently-updated content. Partial rendering combines both: static shell with dynamic segments. Incremental Static Regeneration (ISR) regenerates static pages in the background after a defined interval, balancing freshness with performance.

The fetch API is extended in Next.js with caching options: fetch(url, {cache: 'force-cache'}) is static (the default); fetch(url, {cache: 'no-store'}) opts into dynamic rendering; fetch(url, {next: {revalidate: 3600}}) implements ISR. Understanding these options - and the situations where they're automatically overridden (cookies(), headers(), or searchParams() in a Server Component forces dynamic rendering) - is essential for predictable rendering behavior.

3Performance and Core Web Vitals

Next.js provides built-in performance optimizations: automatic image optimization via next/image (format conversion, responsive sizes, lazy loading), font optimization via next/font (self-hosted fonts with no external requests, eliminates layout shift), and script optimization via next/script (defer, lazy loading, web worker strategies). Using these built-ins rather than raw HTML elements delivers measurable performance improvements with minimal additional code.

Turbopack (the Rust-based bundler, replacing Webpack) is stable in Next.js 15 for development and in active development for production builds. Local development starts 40-50% faster with Turbopack, which has a meaningful impact on developer productivity in large applications. The production build still uses Webpack in most setups, but the Turbopack production build is approaching parity.


How We Use It in Practice

Real architectural problems across industries — and how we approach them.

eCommerce / DTC Brand

ISR + Shopify Storefront API: 100ms Product Pages at 50,000-SKU Scale

A DTC apparel brand migrated from a custom Ruby monolith to a Next.js headless storefront pulling product data from Shopify's Storefront GraphQL API. At 50,000 SKUs with frequent price and inventory updates, full static generation at build time took 45 minutes — making every code deploy a 45-minute wait and leaving product data potentially stale. Server-side rendering every request would have added 400-600ms per page load for database round-trips.

Our approach

ISR with on-demand revalidation: product pages use revalidate: 3600 (1-hour baseline staleness) as a floor, but Shopify webhooks (product/update, inventory_levels/update) hit a Next.js route handler that calls revalidatePath() for the specific updated product within seconds of a Shopify event. Category listing pages use revalidate: 900 to balance freshness with CDN hit rate. Build time dropped from 45 minutes to 3 minutes (only layout-level pages rebuilt). Product pages are served from Vercel's edge CDN cache 94% of the time; cache misses regenerate in <200ms. Inventory accuracy improved from 'up to 45 minutes stale' to 'under 30 seconds' for any product touched in Shopify.

SaaS Application

Server Components + Postgres: Eliminating the API Layer for a Dashboard

A B2B analytics SaaS had a Next.js frontend making 12 sequential API calls to a separate Node.js backend on every dashboard load — each API call involving a database query, serialization, and round-trip. P95 dashboard load time was 4.2 seconds. The API layer existed because the frontend team and backend team were separate; with the App Router available, it was unnecessary infrastructure.

Our approach

Migration to App Router Server Components with direct Postgres access via Prisma. Dashboard data fetching moved from 12 sequential API calls to 6 parallel async Server Components — each component fetches only the data it needs, and React's concurrent rendering starts streaming the first completed component immediately. PgBouncer handles connection pooling for the serverless Vercel deployment. The intermediate Node.js API was deprecated. P95 dashboard load time: 680ms. The API layer isn't gone — it's still used for client-side mutations and mobile app access — but eliminated for all read paths that can be colocated with Server Components.

Media / Content Platform

Partial Prerendering + Personalization: Static Shell, Dynamic Segment

A news platform wanted to show personalized recommended articles and reader progress on article pages — but article content itself is static and could be served from CDN at millisecond speed. The team was forced to choose between fast static delivery (no personalization) or slower dynamic rendering (personalization, but 600ms to first content). A/B tests showed personalization lifted engagement by 18% but the SSR latency cost hurt mobile users on slow connections.

Our approach

Next.js Partial Prerendering (experimental, available in Next.js 14+): the article content, title, metadata, and static ad slots are rendered at build time and served from CDN edge. The recommendations panel and reader progress bar are wrapped in React Suspense — they render as dynamic Server Component segments that stream in after the static shell. Users see article content in under 100ms (cached HTML from CDN); personalized content streams in within 400ms via a fast edge function. The static shell is 100% cacheable and requires no origin hit; only the personalized segments hit the origin, dramatically reducing origin load. CDN cache hit rate on article pages: 97%.

FAQ

App Router for all new projects. It's the active development focus, enables React Server Components, and represents the architectural direction of the React ecosystem. The Pages Router remains supported but is not receiving new features. If your team is new to the App Router, budget time for the learning curve - the Server Components mental model shift takes a sprint or two to internalize.

Ready to build with Next.js?

Talk to Us