SvelteKit and Dato Head component

Hi,
I’ve been working with your SvelteKit Starter Kit template and encountered an issue. After removing your imported styles and replacing them with local ones, I noticed that the local styles would load for a second and then get overridden. The console logs the following error:

[svelte] hydration_mismatch
Hydration failed because the initial UI does not match what was rendered on the server

After debugging, I traced the issue to the component inside the /routes/+page.svelte:

<Head data={page._seoMetaTags} />

To resolve it, I implemented this workaround:

<script lang="ts">
	import { onMount } from 'svelte';

	let isClient = false;

	onMount(() => {
		isClient = true;
	});
</script>

{#if isClient}
	<Head data={page._seoMetaTags} />
{/if}

This fixes the hydration error, but I’m concerned about the implications for SEO, as the component should ideally render on the server for optimal metadata indexing. Could you provide insights or suggest a better approach to resolve this issue?

Thanks in advance for your help!

2 Likes

Hey @ivo,

Can you please share your changed code? How did you replace the styles with local ones?

Hi @roger
Thanks for the reply!

I really didn’t change anything. If you run the svelte starter you will be prompted with the hydration mismatch error.

As for my changes, in the /src/routes/+layout.svelte I removed the

<svelte:head>
  <link
    rel="stylesheet"
    href="https://cdn.jsdelivr.net/gh/datocms/nextjs-starter-kit/src/app/global.css"
  />
</svelte:head>

and imported

<script>
     import '../app.css';
</script>

The css file is in the /src/app.css. I’m also using tailwind and the same is happening.
When you open the website, everything loads then, you have the error and the styles are all gone. Somehow the mismatch is reloading the page and overriding all styles i have locally.

Also, in the /src/routes/+page.svelte if you remove the <Head data={page._seoMetaTags} /> component the error disappears and the styles load.

Let me know if this helps or if you need more info to debug the issue and thanks again!

Hey @ivo,

Thanks for the details! It looks like our <Head/> component is causing the hydration errors indeed, probably due to our use if conditionals inside <svelte:head>. I’m going to report this to the devs for a fix, but in the meantime, can you please try this experimental DehydratedHead.svelte component and see if it fixes the issue for you?

You can put the file somewhere in your repo, and then replace our <Head> component in page.svelte with it.

1 Like

Hi @roger

This solution worked perfectly!
Do you know where I can track updates on the official <Head/> component so I can apply any fixes once they’re released?

Thanks for your help!

Came across the same issue. The Meta tags are not being correctly closed. I left a comment here https://github.com/datocms/datocms-svelte/pull/14 on the pullrequest that changes the implementation.

Might be related to the sveltkit 5s changes to null and undefined values being converted to ‘’. Though i’m not sure when it does this.

2 Likes

It’s part of the datocms-svelte repo (@datocms/svelte on NPM). If you use SemVer in your package.json (like "@datocms/svelte": "^4.0.1",) it should auto-update once we release an official patch (still looking into it).

I’ll also post here once we fix it!

1 Like

We spent some time looking into this, and there are two fixes you can use:

  1. If you upgrade to "@datocms/svelte": "^4.0.1", it should fix the hydration error on its own. We changed the code of the <Head/> element there to work around the error. This should be a safe and limited fix with no side effects that we know of.

  2. Alternatively, you can upgrade "@sveltejs/vite-plugin-svelte": "^5.0.0", "vite": "^6.0.0". This will also fix the bug, but NPM might complain about a dependency mismatch. I had to delete the lockfile on my project (package-lock.json) and clear node_modules and then reinstall to get this to work. Be sure to test your project thoroughly to make sure nothing broke, if you choose to do this.

Sorry about that!

Hi @roger
This worked! Thanks for your support.