Why Next.js metadata can differ before and after rendering
Compare the initial HTML with the browser DOM when a client effect changes a title, canonical link, or indexing directive.
One route, two observations
In this controlled example, the server emits a staging title, staging canonical and noindex directive. A client effect changes all three after hydration. View Source and the rendered DOM therefore answer different questions. The supplied HTML files are deliberately constructed fixtures, not captures from a production site.
The accompanying TSX files reproduce the pattern in a Next.js App Router project. Keep the example on localhost: it intentionally demonstrates incorrect server metadata. Inspect the response before JavaScript, then inspect document.documentElement.outerHTML after hydration.
Compare the evidence
| Field | Initial HTML fixture | Rendered fixture | Corrected server output |
|---|---|---|---|
| Title | Staging coffee guide | Coffee guide | Example | Coffee guide | Example |
| Canonical | https://staging.example.com/coffee | https://example.com/coffee | https://example.com/coffee |
| Robots | noindex, follow | index, follow | index, follow |
Diagnose before changing the implementation
Paste initial.html and rendered.html into the rendered-HTML SEO comparison tool. Preserve the date, route, request context and build revision when collecting your own files. A browser extension, consent state or personalization can also change a DOM; compare like-for-like observations.
The diff proves that the supplied snapshots differ. It does not prove what Google rendered, whether a directive was processed, or which version was indexed. Use URL Inspection and server evidence for those questions.
Fix the server-side source of truth
In the supplied fixed-page.tsx, define the intended title, canonical and robots in the App Router metadata export. Remove the effect that rewrites head elements. Rebuild, inspect a fresh response and rendered DOM, and compare again. Route metadata, parent layouts and streamed metadata behavior can vary by Next.js version and request; test the version you deploy.
Verify the public hostname and response, not only localhost. Confirm robots.txt, HTTP headers and canonical targets separately. A clean metadata diff is a bounded release check, not an indexing guarantee.