In August 2026 we ran a full technical and content audit of the Zovintra website - our own Next.js 16 production site. Seven specialist reviews covered SEO, Core Web Vitals, structured data, content quality, and AI search readiness. What we found is directly useful to any team running a Next.js site with a blog, case studies, or service pages targeting organic search. These are field notes from that audit, not generic SEO advice.
The five critical failures we found
A high-level summary of the five issues the audit flagged as most urgent - things actively undoing the SEO work already done:
- GA4 completely dark in production: the measurement ID was an empty string in the environment variable, so all 23 coded analytics events were firing into a void
- Static sitemap.xml in /public shadowing the dynamic app/sitemap.js route, leaving 22 posts out of the sitemap and returning 404 on the live site
- Canonical domain contradiction: all canonical tags and sitemap URLs referenced the non-www domain, which returns a 308 redirect to the www domain - the canonical was pointing at a URL that redirects away from itself
- Homepage and entity schema did not mention the site's actual differentiator, so AI answer engines were categorising the site as a generic dev shop
- LCP failing the Poor threshold (over 4.0 seconds) on every page type, primarily due to Google Fonts loaded via a runtime stylesheet link instead of next/font
All five of these are common on Next.js sites. Three of them - the static sitemap shadow, the canonical contradiction, and the GA4 empty string guard - are specific to how Next.js handles static assets and environment variables. The others are general but easy to miss.
The static sitemap shadow: a Next.js-specific trap
Next.js serves files from the `public/` directory at the corresponding URL path. In our audit, a leftover `public/sitemap.xml` was served at `/sitemap.xml` in place of the dynamic `app/sitemap.js` route at the same path, so check for this on your own site.
What happens in practice: you set up a dynamic sitemap generator early in the project. It works correctly. At some point someone adds a static sitemap to /public (perhaps from a migration, an export, or a default scaffold). The dynamic generator stops running. The static file gets stale. New posts are added to the codebase and appear in `blogDetailData.js`, but the sitemap still references the older list. Google never learns about the new posts. On our site those posts returned 404 on the live domain.
The fix is to delete `public/sitemap.xml` and let `app/sitemap.js` run. Verify by hitting `/sitemap.xml` directly after deleting and confirming the dynamic output. Submit the sitemap URL fresh in Google Search Console after the fix. We cover this specific issue in more depth in launch-day sitemap and robots.txt mistakes.
The canonical domain contradiction
Our canonical tags and sitemap `<loc>` entries all referenced `https://zovintra.com` (non-www). But the actual production domain serving a 200 OK response is `https://www.zovintra.com` (www). The non-www address returns a 308 redirect to www.
This means every canonical tag on the site was asserting a canonical URL that immediately redirects away from itself. Google will still follow the chain and usually resolve the correct URL - but it creates two hops for every link equity signal, slows canonicalization, and can confuse AI citation systems that follow canonical tags as references to the authoritative version of a document.
The fix: standardise on www everywhere. Update `app/sitemap.js` base URL, the canonical tag generator (wherever `alternates.canonical` is set in your Next.js metadata), and the Sitemap line in `robots.txt`. Also collapse the two-hop redirect (`http://zovintra.com` to `https://zovintra.com` to `https://www.zovintra.com`) into a single hop at the infrastructure or Next.js middleware level.
LCP: the Google Fonts problem and how to fix it
Our site's Largest Contentful Paint was failing the Poor threshold (over 4.0s at the 75th percentile) on every page type. LCP is one of the three Core Web Vitals, and Google says they align with what its core ranking systems seek to reward. The root cause was not server speed - TTFB was 60-90ms on Vercel Edge, which is good. The cause, per our audit's lab measurements, was Google Fonts loading via a runtime stylesheet link.
A runtime `<link href='https://fonts.googleapis.com/css2?...' rel='stylesheet'>` creates a three-hop chain before text can paint: HTML download, then Google's CSS file, then Google's .woff2 font file. Every step is a network round trip. Measured savings available from fixing this were 944-1,018ms per page.
The fix is to migrate to `next/font/google`. Per the Next.js font docs, Google Fonts are self-hosted as static assets served from the same domain as your deployment, so the browser sends no requests to Google. Geist is the example font in those docs; check that any other family you use is available through `next/font/google`. This is a framework-level feature that most Next.js sites should be using by default.
AI search readiness: entity clarity and llms.txt
AI answer engines - Google AI Overviews, ChatGPT, Perplexity, Claude, Gemini - tend to rely on clear entity signals such as the homepage framing and `Organization` schema, which was our audit's working assumption rather than a documented rule. Our audit found that neither mentioned the service category the blog content was built around.
The homepage `<title>` and H1 described generic engineering services. The `knowsAbout` schema listed capabilities that any mid-sized dev shop might claim. The 22-post content cluster built around rescue and no-code-to-production work was completely absent from the entity-level signals. AI engines were categorising the site in the wrong bucket.
The fix at the entity level: rewrite the homepage title, H1, and `Organization.knowsAbout` to lead with the specific service positioning that the content depth actually reflects. Then make sure the `llms.txt` file leads with the same framing. llms.txt is a proposal for giving AI agents curated information about a site, not a standard that every crawler reads first, so treat it as a low-cost extra. This is the SEO equivalent of making sure your domain's most prominent signals match what you want to be known for. We write about the broader principle in how to show up in AI overviews.
Structured data gaps we found across the site
Several structured data gaps that are easy to miss in a Next.js site:
- Article dates formatted as 'Jan 8, 2026' instead of ISO 8601 '2026-01-08' - Google's Article guidance says datePublished and dateModified should use ISO 8601
- author.@type set to Person with name 'Zovintra Team' - a group typed as an individual; Google's guidance says to use Person for individuals and Organization for companies or groups, and not to assign the wrong type
- No Service schema on any solution pages - the commercial-intent pages had zero offer or service markup
- No CollectionPage or ItemList schema on blog list and case study list pages
- Canonical tag and sitemap URL mismatch (covered above)
None of these are catastrophic in isolation. Combined, they leave the structured data thinner than it could be across the entity types Google reads - article, organisation, service, and author. The fix for most of them is one template change, not a site-wide rewrite.
IndexNow: the fast path to Bing indexing
The August audit flagged that the site had not yet implemented IndexNow. Per indexnow.org, participating engines share submitted URLs with each other, and its engine list includes Bing, Yandex, Seznam, Naver, Yep, the Internet Archive and Amazonbot. Google is not on that list. For a site publishing new content regularly, submitting new URLs from a Vercel cron job asks those engines to crawl them sooner than their normal schedule would, with no guarantee of timing.
Implementation is straightforward: create a key of 8 to 128 hexadecimal characters, host it as a text file at your domain root, and POST new URLs (up to 10,000 per request) to the IndexNow endpoint. Vercel cron jobs make this automatable. The complete technical setup is documented in the Next.js sitemap and structured data checklist.
What this means for teams building with Next.js
The patterns from our audit are not unique to our site. They appear regularly when we look at other Next.js sites: static files shadowing dynamic routes, fonts loaded from Google's CDN instead of via next/font, canonical tags that do not match the serving domain, structured data that was never updated after initial setup. These are the failure modes the framework does not prevent by default.
The technical SEO checklist for startups covers the full pre-launch and post-launch verification sequence. If you want us to run the same audit against your site - checking for the specific patterns above plus the broader content and performance picture - request a technical SEO review.
Common questions
Why is my Next.js sitemap.xml not updating?
A leftover public/sitemap.xml is served at /sitemap.xml in place of a dynamic app/sitemap.js route at the same path, so the static file goes stale. Delete the static file, confirm the dynamic output at /sitemap.xml, and resubmit the sitemap in Google Search Console.
Does Google support IndexNow?
Not according to indexnow.org's engine list, which includes Bing, Yandex, Seznam, Naver, Yep, the Internet Archive and Amazonbot but not Google. Submitting new URLs asks those engines to crawl them sooner than their normal schedule, with no guarantee of timing.
Who can audit my Next.js site for the same SEO problems?
The post's issues, such as shadowed sitemaps, canonical mismatches, fonts loaded from Google's CDN and thin structured data, are failure modes the framework does not prevent by default. Zovintra can run the same audit against your site, including the broader content and performance picture.
Sources
- [Zovintra SEO, GEO & Content Strategy Audit - August 2026](Docs/seo-geo-content-audit-2026.md) - Zovintra (internal repo document, not public), 2026-08-25
- Largest Contentful Paint (LCP) - web.dev (Google), accessed 19 Oct 2026
- Understanding Core Web Vitals and Google Search results - Google Search Central, accessed 19 Oct 2026
- Font Optimization - Next.js documentation, last updated 2026-05-27
- public Folder - Next.js documentation, last updated 2025-06-16
- Article structured data - Google Search Central, accessed 19 Oct 2026
- IndexNow documentation - IndexNow, accessed 19 Oct 2026
- IndexNow participating search engines - IndexNow, accessed 19 Oct 2026
- The /llms.txt file - llmstxt.org (Answer.AI proposal), accessed 19 Oct 2026



