unhead@betaQuick Start:
import { useHead } from '@unhead/vue' // or your framework
useHead({
title: 'Page Title',
meta: [{ name: 'description', content: 'Page description' }]
})
The useHead() composable is for managing the document head. It provides a type-safe, reactive API to define, update, and remove head elements like title, meta tags, scripts, and more. It's the core composable used across all frameworks in the Unhead ecosystem.
import { useHead } from '@unhead/svelte'
const entry = useHead({
title: 'My Page',
})
// update
entry.patch({ title: 'new Title' })
// remove
entry.dispose()
The composable works by queuing your input to be resolved when the head is rendered:
This queue-based approach enables powerful features like deduplication, async resolution, and priority-based rendering while maintaining optimal performance.
useHead() provides reactivity through two main mechanisms:
ActiveHeadEntry object with patch() and dispose() methods lets you manually update or remove head entriesfunction useHead(input: UseHeadInput, options?: HeadEntryOptions): ActiveHeadEntry
| Parameter | Type | Required | Description |
|---|---|---|---|
input | Head | Yes | The head configuration object |
options | HeadEntryOptions | No | Configuration options for the head entry |
interface ActiveHeadEntry {
/**
* Update the head entry with new values
*/
patch: (input: Partial<UseHeadInput>) => void
/**
* Remove the head entry
*/
dispose: () => void
}
The input object accepts the following properties:
interface Head<E extends MergeHead = SchemaAugmentations> {
// Document title
title?: string | Promise<string>
// Title template (function or string with %s placeholder)
titleTemplate?: string | null | ((title?: string) => string | null)
// Template parameters for dynamic replacements
templateParams?: { separator?: string } & Record<string, string | Record<string, string>>
// HTML tag collections
base?: Base<E['base']>
link?: Link<E['link']>[]
meta?: Meta<E['meta']>[]
style?: (Style<E['style']> | string)[]
script?: (Script<E['script']> | string)[]
noscript?: (Noscript<E['noscript']> | string)[]
// Element attributes
htmlAttrs?: HtmlAttributes<E['htmlAttrs']>
bodyAttrs?: BodyAttributes<E['bodyAttrs']>
}
The input is deeply resolved allowing you to provide any value as a function. This can be useful for lazily resolving values when the head tags are being rendered.
import { useHead } from '@unhead/svelte'
const title = useMyTitle()
useHead({
// just works
title: () => 'Dynamic Title',
meta: [
() => ({
name: 'description',
content: () => `Description for ${title.value}`
}),
]
})
The options parameter allows you to configure the behavior of the head entry:
export interface HeadEntryOptions {
// Whether to process template parameters in the input
// - Requires the TemplateParams plugin
processTemplateParams?: boolean
// Priority of tags for determining render order
tagPriority?: number | 'critical' | 'high' | 'low' | `before:${string}` | `after:${string}`
// Where to position tags in the document
tagPosition?: 'head' | 'bodyClose' | 'bodyOpen'
// Custom head instance
head?: Unhead
}
Setting any of these will apply that rule to all tags within the entry. For example if we want to push several meta tags with low priority, we can do:
import { useHead } from '@unhead/svelte'
useHead({
meta: [
{ name: 'description', content: 'fallback description' },
{ name: 'author', content: 'fallback author' }
]
}, {
tagPriority: 'low'
})
tagPriority option is particularly useful for controlling render order when you have multiple head entries that might contain similar tags.For more granular control, you can use the returned API:
import { useHead } from '@unhead/svelte'
// Create the head entry
const headControl = useHead({
title: 'Initial Title'
})
// Later update specific fields
headControl.patch({
title: 'Updated Title',
meta: [
{ name: 'description', content: 'New description' }
]
})
// Remove the entry entirely when needed
headControl.dispose()
Use cases for manual control:
For framework-specific reactivity details, see the guides for each specific framework.
useHead() function applies minimal sanitization to improve developer experience.Do not use this function with untrusted or third-party input. It cannot guarantee safety when handling unknown content.For XSS protection, either:
useHead()Use a reactive value or the patch() method:
const entry = useHead({ title: 'Initial' })
entry.patch({ title: 'Updated Title' })
Call dispose() on the returned entry:
const entry = useHead({ title: 'Temporary' })
entry.dispose() // removes all tags from this entry
import { useHead } from '@unhead/svelte'
useHead({
titleTemplate: title => `${title} - My Site`,
title: 'Home Page'
})
// Results in: "Home Page - My Site"
For more details on title templates, see the Titles guide.
import { useHead } from '@unhead/svelte'
// Global site defaults
useHead({
titleTemplate: '%s | My Website',
meta: [
{ name: 'og:site_name', content: 'My Website' }
]
})
// Page-specific entries (will be merged with globals)
useHead({
title: 'Product Page',
meta: [
{ name: 'description', content: 'This product is amazing' }
]
})
import { useHead } from '@unhead/svelte'
import { computed, ref } from 'vue'
// Initial setup
const data = ref(null)
const loading = ref(true)
const error = ref(null)
const headControl = useHead({
title: computed(() => data.value
? `${data.value.name} - Product`
: loading.value
? 'Loading...'
: 'Product Not Found')
})
// Fetch data and update head
async function fetchProduct(id) {
try {
loading.value = true
data.value = await api.getProduct(id)
}
catch (err) {
error.value = err
}
finally {
loading.value = false
}
}
import { useHead } from '@unhead/svelte'
// Critical meta tags (early in <head>)
useHead({
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
]
}, { tagPriority: 'critical' })
// Default priority tags (middle of <head>)
useHead({
meta: [
{ name: 'description', content: 'My website description' }
]
})
// Low priority tags (end of <head>)
useHead({
meta: [
{ name: 'author', content: 'Jane Doe' }
]
}, { tagPriority: 'low' })
Here are some common use cases for useHead():
For ready-to-use implementations of common patterns, see our Starter Recipes.