Technical SEO for Next.js Websites

  • Home
  • <
  • Blog
  • <
  • Technical SEO for Next.js Websites
Search performance review for a Next.js website
SEO & WEB PERFORMANCE

Technical SEO for Next.js Websites

Neo Hives IT Solutions· 5 September 2026·9 min read

There is a particular kind of frustration that shows up about three months after a rebuild. The new site is fast. Lighthouse is green. The code is clean, the design finally looks like the brand. And organic traffic is flat — or worse than the old site it replaced. Nobody did anything wrong, exactly. But nobody did technical SEO either.

Next.js gives you almost everything you need to build a site search engines are happy to crawl, and switches on almost none of it by default. Technical SEO for Next.js websites comes down to a handful of deliberate decisions: what renders on the server, what URL a page lives at, what a crawler sees before any JavaScript runs, and whether the same content is quietly reachable at four different addresses. This is the list we work through on every build, in roughly the order that matters.

Technical SEO is plumbing, not content

It helps to keep three things separate. There is content — whether a page answers the thing someone typed. There is authority — whether anyone else on the internet vouches for you. And there is technical SEO — whether a search engine can reach the page, render it, understand it and pick the right version of it to index.

Technical work does not make you rank. It removes the reasons not to. That makes it the cheapest of the three to fix and by far the most expensive to ignore, because a crawling or indexing problem puts a ceiling on everything else you spend. No amount of good writing outruns a page that Google has decided is a duplicate.

Rendering: the decision that changes everything downstream

Google does execute JavaScript, and people quote that fact as though it settles the argument. It does not. Rendering happens on a second pass, on a budget, and that budget is not distributed evenly across the web. If your headline only exists after a client-side fetch resolves, you are betting your indexing on a queue you cannot see. On a site with authority you will probably get away with it. On a new site you often do not.

  • Static generation is the default worth defending. Marketing pages, service pages, case studies, blog posts — all of it can be built at deploy time. The crawler gets complete HTML on the first request, and so does the visitor.
  • ISR for content that changes without a deploy. A revalidate value on the page or fetch gives you fresh content without giving up pre-rendered HTML.
  • SSR when the page genuinely differs per request. Logged-in dashboards, personalised pricing. These are usually pages you would not want indexed anyway.
  • Client-side fetching for anything you want ranked is the one to avoid. Not because it never works, but because it turns a solved problem into a gamble.

In the App Router, components are server components until you say otherwise, which is the right default. Adding "use client" does not remove your text from the HTML — the initial render still happens on the server — but it does ship more JavaScript, and it invites the real mistake: pulling content in a useEffect. The fastest way to know where you stand is to stop looking at browser DevTools, which shows you the page after hydration, and check the raw response instead:

curl -s https://yoursite.com/services | grep -o "your exact headline"

If that comes back empty, the first pass of a crawler sees an empty page too.

Use the Metadata API, and set metadataBase

Next.js replaced the old habit of hand-rolling <Head> tags with a metadata export — a static metadata object for fixed pages, and generateMetadata() for dynamic routes where the title depends on the record being displayed. It is a genuine improvement, and it has a few sharp edges.

  • Set a title template once, then stop repeating your brand. A root template: "%s | Brand" plus a page title that already ends in your brand name produces Page | Brand | Brand. Google truncates around 60 characters, so you spend your budget twice on the same word.
  • Every indexable route needs its own description. Around 150 to 155 characters. Shipping the template's default description across twenty pages is one of the most common findings on a purchased theme.
  • Set metadataBase in the root layout. Without it, alternates.canonical emits a relative URL. Browsers resolve that fine, but canonicals are one of the places where being explicit and absolute costs nothing and prevents a category of ambiguity.
  • Give Open Graph its own image per template, not per page. One good branded OG image beats twenty missing ones, and missing OG tags are why your link previews look broken in WhatsApp.

One page, one URL

Duplicate content on a Next.js site is rarely someone copying text. It is the same page being reachable more than one way: with and without a trailing slash, on www and bare domain, over http and https, at / and /home, and — the big one — at every combination of filter and sort parameters your listing page supports.

  • A canonical tag on every indexable page, pointing at the version you want to win.
  • Pick one trailing-slash convention in next.config.mjs and let a single permanent redirect enforce it. Do not leave both live.
  • Route groups do not appear in URLs. A folder like (defaultLayout) is invisible to the router, which is useful — but it means your folder tree is not your URL tree, so read the URLs from the built output rather than the file explorer.
  • Filter and sort parameters should either canonical back to the clean URL or be excluded from indexing. Left alone, one listing page becomes hundreds of near-identical ones competing with each other.
  • When you retire a URL, redirect it. Deleting a page that has links and history pointing at it throws away the only asset it had. A redirects() entry with permanent: true takes one line and passes the signal to whatever replaced it.

Structured data, done honestly

JSON-LD in a <script type="application/ld+json"> tag is how you tell a search engine what a page is rather than making it infer. Because App Router pages render on the server, you can inline the script in the page component and it lands in the HTML with no client-side work. The types worth the effort for most businesses: Organization on the homepage, LocalBusiness if you have a real address, BreadcrumbList on nested pages, BlogPosting on articles, and Service on service pages.

One firm rule: never mark up something that is not visible on the page. No review stars you did not receive, no FAQ schema for questions the reader cannot see, no aggregate ratings assembled out of optimism. Structured data that misrepresents a page is one of the few SEO shortcuts that can earn a manual penalty instead of simply being ignored, and the upside was never worth it.

Core Web Vitals: where Next.js sites quietly lose points

A React site can feel instant to the developer who built it on a fast laptop and still fail its field metrics on a mid-range Android phone on 4G, which is what Google actually measures. Four things account for most of the gap.

  • Images. Use next/image with explicit width and height so the browser reserves space and your layout does not shift. Put priority on the one image that is your largest element above the fold — and only that one, because marking everything as priority is the same as marking nothing.
  • Check whether image optimisation is actually on. Setting unoptimized: true is common when exporting to a static host, and it silently switches off resizing and modern-format conversion. It is a legitimate choice, but it means the compression is now your job, not the framework's.
  • Fonts. next/font self-hosts and preloads, which is the right behaviour. Every extra weight and family is still another file on the critical path — most sites need two or three weights, not nine. Worth knowing: these are fetched at build time, so your build environment needs outbound network access to the font source.
  • Third-party scripts. A tag manager, a chat widget and two pixels will usually cost you more interaction latency than all of your own code combined. Load them through next/script with a deferred strategy, and measure INP on mobile before and after.

Sitemaps and robots belong in code

A hand-maintained sitemap.xml drifts from reality within a month of launch. Generating it from the same data that generates your routes — through app/sitemap.js, with app/robots.js alongside it — means a new page cannot be missing from the sitemap, because both read from one source. Include a real lastModified so it carries information rather than noise, and check that your preview and staging deployments are not indexable, which is a surprisingly frequent way for a duplicate of an entire site to end up in the index.

A note on AI search

Answer engines and AI assistants are increasingly a route to your site, and there is no separate trick for them. They read the same HTML. What they reward is being easy to quote: semantic markup rather than a wall of nested divs, headings phrased the way a person asks the question, the actual answer in the first sentence beneath the heading rather than four paragraphs later, and specific facts — numbers, dates, versions — stated next to the claim they support instead of gestured at. Every one of those is also just good writing, which is the convenient part. We go deeper into how these systems retrieve and cite content in our guide on choosing an AI agent development company in India, and in what we build around retrieval on our AI and agentic services page.

The twelve-point check you can run this week

  • curl two important pages and grep for their headline text. Empty result means a rendering problem, and nothing else on this list matters until it is fixed.
  • Every indexable route has a unique title under 60 characters and a unique description around 155.
  • metadataBase is set and canonicals resolve to absolute URLs.
  • One trailing-slash convention, one www convention, each enforced by a single permanent redirect.
  • Exactly one h1 per page, and heading levels descend without skipping.
  • Every image has width, height and alt text that describes the image rather than repeating the keyword.
  • The above-the-fold hero image is marked priority; nothing below the fold is.
  • sitemap.js and robots.js are generated from route data, not typed by hand.
  • Every retired URL returns a 301 to its closest replacement.
  • JSON-LD passes the Rich Results Test and describes only what is visible on the page.
  • Third-party scripts are deferred, and mobile INP was measured after adding them.
  • Search Console coverage shows no unexplained Crawled — currently not indexed entries.

How we handle this at Neo Hives IT Solutions

We build in Next.js, so technical SEO for Next.js websites is not theory for us — this list is the review we run before a site goes live. Pages are statically generated wherever the content allows it, metadata is defined per route rather than inherited from a template, retired URLs get redirects, and structured data describes what is genuinely on the page. On a recent travel site build that meant twenty pre-rendered routes shipping in roughly 94 KB of HTML, with no client-side fetch standing between a crawler and the content.

If you want the work itself, that sits under web development for builds and rebuilds, and digital marketing for the search and campaign side. We will say plainly which of the two your problem actually is — a technically perfect site with nothing worth reading does not rank either, and that is a content brief, not an engineering one.

Common questions

Does Next.js handle SEO automatically? It handles rendering and gives you a good metadata API, which is most of the hard part. It does not write your titles, choose your canonicals, generate your sitemap, redirect your old URLs or stop you shipping a 2 MB hero image. Those remain decisions.

Should we use static generation or server rendering for SEO? Static, for anything public and shareable, with incremental revalidation where content changes. Server rendering is not penalised — it is just slower to first byte and gives you nothing extra for a page that is identical for every visitor.

How long before technical fixes show up in traffic? Indexing changes such as fixing a canonical or restoring a redirect can move within days to a couple of weeks once the page is recrawled. Performance improvements feed a field-data metric that updates on a 28-day rolling window, so give those a month before judging. Neither one substitutes for having pages worth ranking.

Is our site too small for this to matter? Small sites are where it matters most, because they have the least authority to absorb a mistake. A twelve-page site with a duplicate-content problem is losing a larger share of its potential than a large site with the same bug.

Where to start

Run the first item on the checklist. It takes two minutes and it tells you whether you have a rendering problem or a content problem, and those need completely different people. Everything after that is ordinary, unglamorous work with an unusually good return.

If you would rather someone else ran the audit, send us the URL and we will go through this list and tell you what we find, including the finding that your technical setup is fine and the gap is somewhere else. If AI and automation are also on your roadmap, the same conversation can cover our free AI readiness audit.