---
title: "Installing Unhead with Svelte"
description: "Set up Unhead in Svelte with createHead() and useHead(). Advanced features beyond svelte:head for SEO, structured data, and scripts."
canonical_url: "https://unhead.unjs.io/docs/svelte/head/guides/get-started/installation"
last_updated: "2026-06-11T01:58:01.615Z"
---

## Introduction

Unhead has first-class support for Svelte, improving the developer experience and performance of using head tags in your app.

**Quick Start:** Install `@unhead/svelte`, create head with `createHead()`, and use `setContext()` to provide it. Use `useHead()` in components with `$effect()` for reactivity.

It provides advanced features in comparison to Svelte's in built `<svelte:head>` component, supporting a more diverse set of use cases from SEO, structured data and
script loading.

It's designed to work with any Svelte setup, however this guide assumes you're following a similar structure to the [Vite: ssr-svelte-ts](https://github.com/bluwy/create-vite-extra/tree/master/template-ssr-Svelte-ts) template
or a Vite SPA.

<note>

Using [SvelteKit](https://kit.svelte.dev/)? See the dedicated [SvelteKit integration guide](/docs/svelte/head/guides/get-started/sveltekit) instead.

</note>

### Demos

- [StackBlitz - Unhead + Vite + Svelte SSR](https://stackblitz.com/edit/github-ckbygkxk)
- [StackBlitz - Unhead + Vite + Svelte SPA](https://stackblitz.com/edit/vitejs-vite-tfv9egtq)

## Setup

### 1. How do I install Unhead for Svelte?

Install `@unhead/svelte` dependency to your project.

<module-install name="@unhead/svelte@next">



</module-install>

### 2. How do I set up client-side rendering?

To begin with, we'll import the function to initialize Unhead in our *client* Svelte app from `@unhead/svelte/client`.

In Vite this entry file is typically named `entry-client.ts`. If you're not server-side rendering, you can add this to your main Svelte app entry instead.

<code-block>

```ts [src/entry-client.ts]
import { createHead, UnheadContextKey } from '@unhead/svelte/client'
import { hydrate } from 'svelte'
import App from './App.svelte'
import './app.css'

// SSR or SPA usage

const unhead = createHead()
const context = new Map()
context.set(UnheadContextKey, unhead)

hydrate(App, {
  target: document.getElementById('app')!,
  context
})
```

```ts [src/main.ts]
import { createHead, UnheadContextKey } from '@unhead/svelte/client'
import { mount } from 'svelte'
import App from './App.svelte'
import './app.css'

// SPA usage

const unhead = createHead()
const context = new Map()
context.set(UnheadContextKey, unhead)

const app = mount(App, {
  target: document.getElementById('app')!,
  context,
})

export default app
```

</code-block>

### 3. How do I set up server-side rendering?

<note>

Serving your app as an SPA? You can [skip](#4-how-do-i-add-head-tags) this step.

</note>

Setting up server-side rendering is more complicated as it requires rendering out the tags to the HTML string before sending it to the client.

We'll start with setting up the plugin in the *server* entry this time. Make sure to import from `@unhead/svelte/server` instead
and add the `head` in the return object.

```tsx [src/entry-server.ts]
import { createHead, UnheadContextKey } from '@unhead/svelte/server'
import { render as _render } from 'svelte/server'
import App from './App.svelte'

export function render(_url: string) {
  const unhead = createHead()
  const context = new Map()
  context.set(UnheadContextKey, unhead)
  return {
    render: _render(App, {
      context,
    }),
    unhead,
  }
}
```

Now we need to render out the head tags *after* Svelte has rendered the app.

Within your `server.js` file or wherever you're handling the template logic, you need to transform the template data
for the head tags using `transformHtmlTemplate()`.

```ts [server.ts]
import { transformHtmlTemplate } from '@unhead/svelte/server'
// ...

// Serve HTML
app.use('*all', async (req, res) => {
  try {
    // ...

    const rendered = await render(url)
    const html = await transformHtmlTemplate(
      rendered.unhead,
      template
        .replace(`<!--app-head-->`, rendered.head ?? '')
        .replace(`<!--app-html-->`, rendered.html ?? '')
    )

    res.status(200).set({ 'Content-Type': 'text/html' }).send(html)
  }
  catch (e) {
    // ...
  }
})
// ..
```

### 4. How do I add head tags?

Done! Your app should now be rendering head tags on the server and client.

To improve your apps stability, Unhead will now insert important default tags for you.

- `<meta charset="utf-8">`
- `<meta name="viewport" content="width=device-width, initial-scale=1">`
- `<html lang="en">`

You may need to change these for your app requirements, for example you may want to change the default language. Adding
tags in your server entry means you won't add any weight to your client bundle.

```ts [src/entry-server.ts]
import { createHead } from '@unhead/svelte/server'

export function render(_url: string) {
  const head = createHead({
    // change default initial lang
    init: [
      {
        htmlAttrs: { lang: 'en' },
        title: 'Default title',
        titleTemplate: '%s - My Site',
      },
    ]
  })
  const html = `<!-- your html -->`
  return { html, head }
}
```

For adding tags in your components, you can use the `useHead()` or `useSeoMeta()` composables.

```sveltehtml [App.svelte]
<script lang="ts">
  import { useHead } from '@unhead/svelte'

  // a.
  useHead({
    title: 'My Awesome Site',
    meta: [
      { name: 'description', content: 'My awesome site description' }
    ]
  })

  // b.
  useSeoMeta({
    title: 'My Awesome Site',
    description: 'My awesome site description'
  })
</script>
```

For handling reactive input, check out the [Reactivity](/docs/svelte/head/guides/core-concepts/reactivity) guide.

### 5. How do I enable auto-imports? (Optional)

If you're using  [unplugin-auto-import](https://github.com/antfu/unplugin-auto-import), you can automatically import the composables.

```ts [vite.config.ts]
import { autoImports } from '@unhead/svelte'
import AutoImport from 'unplugin-auto-import/vite'

export default defineConfig({
  plugins: [
    AutoImport({
      imports: [
        autoImports,
      ],
    }),
    // ...
  ]
})
```

## Next Steps

Your Svelte app is now setup for head management, congrats! 🎉

You can get started with [reactive input](/docs/svelte/head/guides/core-concepts/reactivity) for any of the hooks or components:

- [`useHead()`](/docs/head/api/composables/use-head)
- [`useSeoMeta()`](/docs/head/api/composables/use-seo-meta)

Or explore some of the optional extras:

- Add [`useSchemaOrg()`](/docs/schema-org/api/composables/use-schema-org) for structured data
- Use [`useScript()`](/docs/head/api/composables/use-script) for performance optimized script loading
