Skip to main content
Next.js development

You are reading the case study.

We are a senior Next.js development agency, and the strongest receipt we can show you is the page you are on: a Next.js 16 App Router build with 440+ indexable routes, ISR fed by a live ATS, and OG images rendered at the edge. The rest of the receipts are one click away.

16
Next.js major version serving this page
440+
Indexable routes on this site
5 min
ISR window on our live careers pages
73K+
Lines in one Next.js platform we shipped
The receipts

The proof is already rendering.

Most agencies claiming Next.js expertise show you a portfolio site about their work. Ours is the work: this site is a production Next.js build, the case studies behind these cards are published here, and we deploy production builds to Vercel daily.

This website

You are reading it

bearplex.com is a Next.js 16 App Router build, and every route you can click is part of the pitch.

  • 440+ indexable routes, most generated programmatically from typed data files
  • Careers pages rebuilt by ISR every five minutes from a live ATS
  • Edge-runtime Open Graph image service, sitewide JSON-LD, llms.txt for AI crawlers

Vertex360

Client platform

A complete NDIS management platform for Australian disability providers, built as a long-term development partner.

  • Next.js and TypeScript at the core of a 73K+ line codebase
  • 32 integrated modules, from rostering to NDIA claim submission
  • Vercel in the production stack, $1.2M+ in monthly claims processed across providers

Yaay365

Client ecosystem

A Kenyan membership and rewards ecosystem of six applications, two of them built on Next.js.

  • Member website on Next.js 13: deals, subscriptions, e-wallet, referrals
  • Marketing site on Next.js 14 with Framer Motion
  • Part of a 150K+ line, six-app platform sharing one backend

Optinizers

AI product interface

An AI onboarding platform whose retrieval interface we built on Next.js.

  • Natural-language questions answered with citations, exact quotes, and timestamps
  • Next.js with the Vercel AI SDK on the interface layer
  • Backed by a LangGraph pipeline with Pinecone and PostgreSQL underneath

Hanan's Bridal

Delivered build

A luxury designer-collections e-commerce platform for a bridal boutique in Georgia carrying premium designer houses.

  • Next.js e-commerce build presenting designer collections as first-class catalogues
  • Collections supplied directly by premium bridal houses
  • No public case study yet, so it gets a name here and nothing we cannot show

Letti AI

Vercel deployment

A career intelligence platform from the wider React and Vercel practice around our Next.js work.

  • React 18 frontend with Radix UI over a six-stage AI pipeline
  • Docker, GitHub Actions, and Vercel in the production stack
  • Semantic job matching on 3072-dimensional embeddings

Every claim above is pulled from the linked case study or from this site's own codebase. Hanan's Bridal has no public case study yet, which is why it gets a name and no link. If a number is not in the source, we do not print it here.

The practice

What we do with Next.js.

Seven areas, one standard: rendering decided per route on purpose, bundles held to budgets, and code your own team can maintain after handover. Select an area.

01

App Router product builds

Full products built on the App Router from day one: server components as the default, explicit client boundaries, layouts and streaming used deliberately, and a caching policy written down per route. The same architecture that serves the page you are reading.

Server componentsStreamingRoute-level caching

Everything ships with source, a documented caching policy per route, and a runbook. You own the project; we make sure your team can run it without us.

The sharp edges

What the tutorials leave out.

Next.js is excellent, and it has edges that only show up in production: boundaries that reshape bundles, caching semantics that moved between major versions, regeneration that serves stale pages by design. None of this is a reason to avoid the framework. It is the difference between a build that survives its second year and one that does not.

The fact

The server/client boundary is architecture, not a directive

One 'use client' placed high in the component tree silently drags an entire subtree into the browser bundle, and data access or secrets that drift into client components become public. Teams discover the boundary exists when the bundle doubles or a key leaks into page source.

How we run it

We treat the boundary as a designed seam: server components by default, client islands kept small and leaf-level, and the serialization boundary reviewed like an API contract. Bundle composition per route is checked in review, not discovered in production.

The fact

Caching semantics have changed across major versions

Next.js 13 and 14 cached fetch calls aggressively by default; Next.js 15 flipped fetch and GET route handlers to uncached by default and reworked the client router cache. Code written against one major's implicit behavior can silently change freshness on the next.

How we run it

Every route gets an explicit, written caching policy: what is static, what revalidates and on what interval, what is always dynamic. Upgrades are treated as behavioral changes, verified route by route against that policy before they ship.

The fact

ISR bites when it is treated as magic

Incremental Static Regeneration serves stale content by design until the revalidation window passes, on-demand revalidation only works if something actually calls it, and ISR with per-user content is simply the wrong tool. The failure mode is a page that looks fine and is quietly hours old.

How we run it

We make staleness a product decision with a number attached. This site's careers pages run a five-minute ISR window against a live ATS because five minutes is an acceptable delay for a job posting. Personalized routes render dynamically; nothing per-user ever goes through ISR.

The fact

Self-hosting Next.js is real work, not a checkbox

Off Vercel, you own what the platform otherwise absorbs: standalone output and a Node or container runtime, image optimization dependencies, a shared cache handler if ISR runs across multiple instances, CDN configuration, and middleware behavior differences.

How we run it

We deploy production builds to Vercel daily and it is our default recommendation, but when data residency or platform strategy requires self-hosting, we plan the cache handler, image pipeline, and CDN explicitly and load-test the result. The tradeoff is written down before the decision, not after.

The fact

Bundle discipline decays without enforcement

Every dependency imported into a client component ships to every visitor who hits that route. Chart libraries, editors, date libraries, and analytics SDKs accumulate one pull request at a time, and no single change looks like the problem.

How we run it

Per-route bundle budgets enforced in CI, analyzer output reviewed when budgets move, heavy interactivity isolated behind dynamic imports, and server components carrying everything that does not genuinely need to be interactive.

A senior Next.js build is not a framework choice. It is a caching policy someone wrote down, a bundle budget someone enforces, and an upgrade path someone has already read the release notes for.

Honest counsel

When Next.js is the wrong choice.

We make money building on Next.js, which is exactly why you should hear us say where it does not fit. If your project lands in one of these, we will tell you in the first call and point you at the right architecture instead.

And one thing that is not on the list: fear of Vercel lock-in. Next.js self-hosts on any Node runtime or container; the pieces the platform absorbs (ISR cache, image pipeline, CDN) are engineering work we have planned before, not a trap.

A brochure site your marketing team edits every day

If the site is mostly static pages and the people changing it are not engineers, a CMS-first setup is often the honest answer. Next.js with a headless CMS is excellent, but only if someone will actually maintain the pipeline; otherwise the CMS alone may serve you better.

An internal tool behind a login

No crawler will ever see it, so server rendering buys you nothing. A Vite single-page app is simpler to build, simpler to reason about, and simpler to operate. We have shipped exactly that when it fit: SimpliRFP, published on this site, is a React SPA.

A native-feel mobile app

Next.js is a web framework. If the product lives on phones and needs native capabilities, offline behavior, and app-store presence, React Native is the right member of the React family, and pretending a responsive web app is an app strategy helps nobody.

A CRUD product with a team that does not know React

If your engineers live in Rails, Laravel, or Django and the product is server-rendered forms over a database, those frameworks will ship it faster and your team can maintain what they built. Adopting React and Next.js at the same time doubles the learning curve for one project.

A product whose core is a long-lived stateful server

Multiplayer state, persistent websocket sessions, or anything that must hold memory between requests fights the serverless-first grain of the framework. Build that as a dedicated service; Next.js can be the excellent front of it, but it should not try to be it.

How it runs

Scoped, shipped, handed over.

No hourly meters. A discovery sprint produces a fixed quote; the work runs as milestones; you end up owning everything. The drivers of cost are the size of the page inventory, integrations and data sources, e-commerce complexity, design-system maturity, migration and redirect volume, and performance targets.

01
Discovery sprint

One to two weeks. We read the codebase or the content inventory, map every URL that matters, and produce a written scope with fixed-price milestones. For takeovers and migrations, this is where the audit findings and the redirect map land.

02
Fixed milestones

The build or migration runs as milestones with explicit deliverables and acceptance criteria. Every route ships with its rendering strategy and caching policy documented; bundle budgets hold in CI from the first milestone.

03
Handover or retainer

Full source, runbooks, and Core Web Vitals field data you can watch move. Stay on retainer for ongoing development and framework upgrades, or take the keys; either way the project is yours.

Focused engagements (performance pass, migration assessment) start in the low five figures
Full product and platform builds typically start from the mid five figures
Every quote is fixed before build work begins; never hourly
FAQ

Common questions about Next.js development.

What teams ask before handing us a Next.js project, answered the way we answer them on calls.

Yes, both are standard engagements. A WordPress migration moves content into typed data files or a headless CMS, rebuilds the templates as App Router routes, and treats the redirect map as a first-class deliverable so existing search equity survives the cutover. A CRA or Vite SPA migration is usually incremental: routes move across in slices, client-only pages keep working, and each slice picks up server rendering and per-route metadata as it lands. In both cases the migration starts with an inventory of every URL that matters, because the pages you forget are the rankings you lose.

App Router for anything new. It has been the default since Next.js 13, the ecosystem has consolidated around server components, and the newest capabilities land there first. This page is served by an App Router build. That said, a working Pages Router app is not an emergency: it remains supported, and the honest advice is to migrate when a redesign, a major version upgrade, or a feature that needs server components gives you a reason, not because a blog post said so. When we do migrate one, it goes route by route, not as a rewrite.

No. Next.js self-hosts on any Node server or container using standalone output. The honest tradeoff: on Vercel, ISR, image optimization, edge middleware, and preview deployments work with zero configuration; self-hosted, you own each of those, including a shared cache handler if you run multiple instances. We deploy production builds to Vercel daily, including this site, and when a client needs to self-host we plan the caching, image, and CDN pieces explicitly instead of discovering them in production.

It is the strongest fit we know for that job, and this site is the receipt: bearplex.com is a Next.js App Router build with 440+ indexable routes, most of them programmatic pages generated from typed data files with generateStaticParams, each with its own metadata, JSON-LD, and Open Graph image. Server rendering means crawlers get complete HTML, ISR keeps generated pages fresh without full rebuilds, and the sitemap is code, so it never drifts from the routes that actually exist.

We price by outcome, not by the hour. A focused engagement (a performance and Core Web Vitals pass, or a migration assessment with a redirect map) is the smallest thing we sell and typically starts in the low five figures. A full product or platform build usually lands from the mid five figures, and large programmatic or e-commerce builds go beyond that. The drivers are the size of the page inventory, the number of integrations and data sources, e-commerce complexity, design-system maturity, migration and redirect volume, and how aggressive the performance targets are. A short discovery sprint produces a fixed quote before any build work starts.

Yes. Retainers cover new feature development, dependency and framework upgrades, and Core Web Vitals monitoring against real field data. The upgrade line matters more than it sounds: Next.js caching behavior has changed across major versions, so version bumps get route-by-route verification, not a version number change and a prayer. Our own site runs on the same continuous model, so the discipline we sell is one we live with.

Yes. A takeover starts with an audit: bundle composition per route, where the server/client boundaries actually sit, what each route's caching and rendering behavior really is (not what the comments claim), Core Web Vitals field data, and the upgrade path from whatever version the project froze on. You get a written findings report first, then a fixed-scope plan. No rewrite pitch unless the audit genuinely supports one, and most of the time it does not.

Not always, and we will tell you when you do not. An internal tool or a dashboard behind a login has no SEO surface and no need for server rendering; a Vite SPA is simpler to build and simpler to operate. We ship both: SimpliRFP, published on this site, is a React SPA because that was the right shape for it. Next.js earns its complexity when public pages, search visibility, per-route rendering strategy, or a large content surface are part of the product. If they are not, we will say so in the first call.

New builds start on the current major; this site runs Next.js 16. Existing apps should upgrade deliberately, not reflexively, because the majors have changed real semantics: caching defaults moved between versions 13 and 15, so code written against one major's implicit behavior can silently change freshness on the next. We handle upgrades as engineering work: read the release notes against your codebase, make every route's caching policy explicit, then verify behavior route by route before it ships.

Discipline, not tricks. Server components stay the default so client bundles carry only what interactivity needs; heavy dependencies stay out of client components; images go through next/image with real dimensions; fonts load through next/font so text never swaps late. Then we measure field data (what real visitors experience, not just lab runs) and hold a per-route budget. Most Next.js performance problems we see are bundle problems wearing a framework costume.

Bring us the project

Your Next.js build, run like this one.

New build, migration, or takeover: the first conversation is with an engineer who has shipped this framework, and it starts with your routes and your rankings, not a slide deck.