Hire Next.js Developers

Next.js Developers Who Know Where the Boundary Is

Server components, caching behaviour and rendering strategy are where Next.js projects go wrong, and they are exactly what a portfolio does not show. We vet on real production scenarios and send two or three profiles within three business days.

  • Profiles in 3 business days
  • Two-week replacement guarantee
  • You brief the developer directly
Frontend developer working on a Next.js application with the component tree open
Day to Day

What the Job Is Once the Demo Is Over

Building a page is the part everyone can do. The work that takes experience is deciding which parts of a route render on the server, what the caching behaviour should be on each one, and why the page is shipping four hundred kilobytes of JavaScript when most of it never needed to reach the browser.

Then there is the unglamorous half: making a loading state that does not shift the layout, keeping the mutation path and the cache in agreement, and working out why the production build behaves differently from the development server. These are the things that turn up in your sprint, and none of them appear in a portfolio.

A developer we place joins your standups, your board and your code review. You brief them yourself, because an account manager in the middle adds delay and loses detail.

React developers more broadly
The First Question

App Router or Pages Router, and What the Answer Reveals

We do not ask this to find out which one they prefer. We ask it because the answer dates a candidate and shows how they handle a model shift.

Only Ever Used Pages

Comfortable with a data-fetching function per page and a clear split between what runs on the server and what runs in the browser. Dropped into an App Router codebase, they tend to mark everything as a client component so familiar hooks work, which removes most of the reason you moved. Not a problem if your codebase is Pages. A real ramp-up cost if it is not.

Only Ever Used App

Fluent with server components and colocated data fetching, and often unable to work in a Pages codebase without friction, because the older data model is not a subset of the newer one. Many were also taught caching as defaults rather than as decisions, so they struggle the first time a page serves stale content.

Has Shipped Both

The answer we look for. They can name what the newer model improved, what it made harder, and where they still reach for a client component deliberately. They talk about the migration as a series of trade-offs rather than an upgrade. This is the person you want if your codebase contains both, which many do.

Tell us which router your application uses when you send the brief. It is one line and it changes the shortlist more than any other detail except seniority.

The Boundary

Server Components, Client Components and the Mistakes in Between

Almost every Next.js performance complaint we investigate traces back to this line being drawn in the wrong place.

The Boundary Pushed Too High

One interactive element needs state, so the developer marks its parent as a client component. Everything below it becomes client code too, including the parts that only render text. The page now ships a bundle nobody intended and renders on the server for no benefit. The fix is to push the boundary down to the smallest interactive piece, and it is usually a half-hour change with a large effect.

Non-Serialisable Props

A function, a class instance or a date-like object passed from a server component into a client one. Only serialisable values cross that boundary, and the failure is not always legible from the message. Experienced developers pass identifiers and primitives across and let the client component do its own work, rather than handing it behaviour.

Composition Instead of Conversion

A client component can still render server-rendered children if they are passed in rather than imported. Developers who know this keep large, static subtrees on the server even inside an interactive wrapper. Developers who do not convert the whole branch and then wonder why the bundle grew.

Secrets Across the Line

Code that reads an environment secret must stay on the server, and a careless import can pull it into a client bundle. We check whether a candidate thinks about this unprompted, because it is the kind of mistake that is invisible until somebody reads the shipped JavaScript.

Data and Caching

The Reason Your Page Is Showing Yesterday

Next.js caches in several places at once. A developer who cannot name them will eventually ship a page that serves stale content and not know why.

A route rendered statically at build time when the developer assumed it was rendering per request, so the data is frozen at the last deploy.
A cached fetch result reused across users because the request that produced it was not keyed on anything user-specific.
A mutation that succeeds on the server while the client router still shows the previous version, because nothing invalidated the path.
Time-based revalidation used as a substitute for invalidation, so correctness depends on how long a user is willing to wait.
A CDN in front of the application caching a response the application intended to be private.
Data fetched sequentially in nested components when the requests were independent, turning one slow page into a much slower one.
One dynamic value read at the top of a route, quietly making the entire route dynamic and undoing the static rendering below it.
Behaviour that differs between the development server and the production build, discovered by users rather than by the team.

What we look for is not memorised defaults, which change between releases. It is whether a developer treats caching as something they decide per route and can explain, rather than something that happens to them.

Rendering Strategy

Choosing Per Route, Not Per Project

The useful skill is knowing that different routes in the same application should be rendered differently, and being able to say why for each one.

Strategy Fits Costs you Typical mistake
Static at build Marketing pages, documentation, anything identical for every visitor and changing rarely A deploy is required for a content change unless revalidation is wired up Using it for a page whose data changes daily, then wondering why it is stale
Static with revalidation Catalogues, listings and article pages where a short delay after a change is acceptable Correctness now depends on a time window somebody chose Setting a long window because it is cheaper, and inheriting support tickets about stale prices
Server rendered per request Personalised pages, dashboards, anything that depends on who is asking Every request does work, so a slow data source is now a slow page Applying it to the whole route when only one small section is personal
Streamed with suspense Pages where a fast shell plus a slower panel beats waiting for everything Loading states have to be designed properly or the page visibly jumps Streaming without stable placeholders, producing layout shift that feels worse than waiting
Client fetched Highly interactive views behind a login where the first paint matters less than the interaction The data is invisible to crawlers and arrives after the JavaScript does Reaching for it out of habit on a page that would have been simpler rendered on the server

In a vetting session we hand over a small application with the wrong strategy on three routes and ask which ones to change and why. The reasoning is the assessment; the change itself takes minutes.

Mutations and the Edge

Server Actions and Middleware

Two features that make things dramatically easier and are routinely used for things they should not be.

Server Actions

  • Genuinely good for forms and mutations when the Next.js app is the only consumer of that operation
  • An action is a public endpoint. It needs authorisation and input validation exactly like an API route would
  • Pending and error states still have to be designed, or the interface simply looks broken for a second
  • Revalidating the affected path after the mutation is what keeps the interface honest
  • When a mobile app or a partner needs the same operation, build an API instead and have the action call it

Middleware

  • Runs before the request reaches a route, which makes it right for redirects, locale handling and coarse auth gates
  • Wrong for anything expensive: it is on the path of every matching request, including static assets if the matcher is careless
  • Frequently runs on an edge runtime where familiar Node APIs and database drivers are unavailable
  • Doing a full session lookup here is a common cause of latency added to every single navigation
  • Authorisation decided only in middleware and not enforced where the data is read is a security problem, not a shortcut

If the backend work behind those actions is growing past what a route handler should hold, that is usually the point to add a Node developer rather than stretching the frontend hire.

Deployment

Beyond the Obvious Host

Next.js is easiest on the platform built for it. Plenty of teams cannot or will not use it, and that is where developer experience genuinely differs.

Self-Hosted in a Container

Entirely workable, and you inherit the things the managed platform was doing quietly: image optimisation, cache headers, revalidation storage that survives a restart, and making sure multiple instances agree on what is cached.

Behind Your Own CDN

Now two caches have opinions about the same response. Getting headers and invalidation right across both is a real piece of work, and it is where stale-content incidents come from in self-hosted setups.

Static Export

Viable for a genuinely static site and immediately limiting: no per-request rendering, no server actions, no middleware. Fine if you chose it deliberately, painful if you discover the constraint halfway through.

Edge or Node Runtime

Middleware and some routes may run on a runtime without full Node APIs. Knowing which of your code paths is affected, before deploying, is a mark of someone who has shipped this rather than read about it.

Build and Environment

Values baked in at build time versus read at runtime is a distinction that produces confusing incidents. A developer who has debugged a wrong environment value in production explains it without hesitating.

Observability

Server rendering means errors happen on the server, where users cannot see them and neither can you unless you set that up. We ask what they would want logged before they would call a Next.js deployment production-ready.

Honest Advice

When Next.js Is Overkill

We place developers, so recommending a framework you do not need would be easy and would cost you more than it costs us. Here is where we would push back.

Probably not

An Internal Tool Behind a Login

Nothing needs indexing, nobody is waiting on a first paint from a cold visit, and every user is authenticated. A plain React application with a router and a data-fetching library is simpler to build, cheaper to host anywhere, and has far fewer behaviours to learn. Choosing Next.js here buys complexity and returns nothing.

Probably not

A Content Site That Rarely Changes

If the content is written in files and published on a schedule, a static site generator does the job with a fraction of the moving parts and a hosting bill close to nothing. Next.js makes sense when content and interactivity have to live in the same application, not when the pages are documents.

Probably not

A Backend With a Thin Interface

If the real product is data processing, integrations or scheduled work with a small dashboard on top, put the logic in a proper Node service and keep the interface simple. Route handlers are a poor home for background jobs, queues and long-running processes, and building them there is a decision you will unpick later.

Good fit

Public Pages That Must Be Fast and Indexed

Marketing, catalogue, listings, articles. Server rendering and static generation are exactly what the framework is for, and the caching model stops being a burden and starts being the feature.

Good fit

Mixed Public and Authenticated

An application with a public catalogue and a private account area, where different routes want different rendering strategies inside one codebase. Very little else handles that split as cleanly.

Worth checking

Already on Next.js and Unhappy

Before concluding the framework is wrong, it is worth finding out whether the problem is the boundary, the caching or the data layer. A fixed-scope audit answers that in writing, and it is cheaper than either a migration or another hire made on a guess.

Vetting

How We Test Next.js Candidates

Live coding and system design on real production scenarios. Nothing that rewards memorising an API that will have changed by next year.

01

Shrink the Bundle

A page with the client boundary drawn far too high. Reduce what ships to the browser without changing what the user sees. Most candidates find something; the good ones explain the tree.

02

Find the Stale Page

A route serving old data after a mutation. We are watching whether they reason about which cache is responsible or start changing settings at random.

03

Review a Mutation

A server action with no authorisation check, no validation and no revalidation afterwards. Whether they treat it as an endpoint is the whole question.

04

Argue a Strategy

Five routes, and they choose a rendering approach for each and defend it, including the one where they would refuse to use Next.js at all.

FAQ

Hiring Next.js Developers

App Router or Pages Router: what should we be hiring for?

Hire for whichever one your codebase uses, and treat the answer to the question as a signal rather than a filter. A candidate who has only worked in the App Router often struggles in a Pages codebase because the data-fetching model is genuinely different. A candidate who has only worked in Pages tends to write client components everywhere in an App codebase, which quietly undoes the reason you chose it. The strongest candidates have shipped both and can say which parts of the newer model they think are an improvement and which they find awkward.

What boundary mistakes do people make with server and client components?

The common one is marking a component as a client component high in the tree, which makes everything beneath it a client component too, so the page ships far more JavaScript than intended and the server rendering benefit disappears. The other frequent mistake is passing something non-serialisable across the boundary, such as a function or a class instance, which fails in a way that is not always obvious from the error. We give candidates a page with exactly these problems and ask them to reduce the client bundle without changing behaviour.

Why did our Next.js page show stale data after a deployment?

Almost always caching, and almost always caching the team did not know was switched on. Next.js caches at several levels: the fetch result, the rendered route, the client-side router, and whatever your host puts in front of all of it. A page can be statically rendered at build time when the developer assumed it was rendered per request. The fix is to be deliberate about which routes are static, which revalidate on a schedule and which must be dynamic, and to invalidate on write rather than hoping a time window is short enough.

Are server actions ready for real applications?

They work well for form submissions and mutations in an application where the Next.js app is the only consumer. They remove a lot of boilerplate and keep the mutation next to the component that triggers it. The things to be careful about are that a server action is a public endpoint and therefore needs its own authorisation and validation exactly like an API route, that error and pending states still have to be designed properly, and that if a mobile app or a third party also needs the same operation, you want a real API rather than an action. We screen for whether a candidate treats actions as endpoints or as function calls.

When is Next.js the wrong choice?

When the application sits behind a login and nothing needs indexing or fast first paint for anonymous visitors, a plain React build with a router is simpler, cheaper to host and easier to reason about. When the site is mostly content and rarely changes, a static site generator does the job with less machinery. When the product is genuinely a backend with a thin interface, a proper Node service plus a small frontend beats putting business logic into route handlers. Next.js earns its complexity when server rendering, routing and data fetching genuinely need to cooperate.

Can your Next.js developers deploy somewhere other than the obvious host?

Yes, and we screen for it because it is where teams get stuck. Self-hosting in a container, running behind your own CDN or reverse proxy, or deploying to another cloud all work, but you become responsible for things the managed platform did silently: image optimisation, cache headers and invalidation, whether your middleware runs on an edge runtime or in Node, and how build output maps onto your infrastructure. A developer who has only ever deployed to the default platform can learn this, and you should know that is what you are asking for.

Can one Next.js developer cover both frontend and backend?

Up to a point, and the point arrives sooner than people expect. Route handlers and server actions cover a lot of application backend work. They are a poor home for background jobs, queues, scheduled work, long-running processes and anything a second consumer needs. If your roadmap includes those, plan for a Node developer alongside the Next.js one. We will say so in the profile rather than letting you find out in month three.

Tell Us Which Router and We Will Send People

App Router, Pages Router or a codebase running both. Two or three vetted profiles within three business days, and a replacement at no cost if the fit is wrong in the first two weeks.