In a client-rendered app one index.html serves every route, so every URL ships the homepage's title, description and canonical. Google reads that first.
A Vite, Create React App or client-rendered Vue build has one index.html. Every route is served from it. Whatever title, description and canonical tag are in that file go out with every URL on the site.
Your head library fixes this in the browser, a moment after the page loads. Google reads the raw response before that happens, and AI crawlers never run the JavaScript that would do it at all. So to both of them, every page on your site looks like a copy of your homepage: the same title, the same description, every canonical tag pointing at the homepage.
Why it costs you more than a wrong tab label
- A canonical tag pointing somewhere else tells Google that the page is a duplicate and should not be ranked on its own.
- Identical titles and descriptions give an answer engine nothing to tell your pages apart with, so none of them is the obvious one to cite.
- Your sitemap lists URLs whose canonical points elsewhere, which is a contradiction: you are asking for them to be indexed and telling Google not to.
How to check
- Pick any page that is not your homepage.
- Run
curl -s https://yoursite.com/your-page | grep -iE "<title|canonical|description" - If what comes back is your homepage's title and a canonical pointing at
/, this is your problem.
How to fix it
- Keep one source of truth for head data: a map from route path to title, description and canonical URL. One file, not a tag scattered in each component.
- Render the head on the server. With a framework that supports it, use its metadata API. With a plain client-rendered build, add a prerender step that writes one HTML file per public route with that route's own head baked in.
- Make every canonical self-referencing. A page's canonical should be its own absolute URL, unless it genuinely is a duplicate of another page.
- Update Open Graph and Twitter tags from the same map, so link previews stop showing the homepage too.
- Verify with the curl from the check above, on three different pages. Three different titles, three self-referencing canonicals.
- Then make sure your sitemap lists only pages that are indexable and canonical to themselves.
Keep the client library if you like
There is no harm in a head library updating the title during client-side navigation. It is good for people moving around your app. It is simply not what Google and the AI crawlers read, so it cannot be the only thing doing the job.