Index of every page on this site: llms.txt
TypeScript
Core Concepts

Page Titles with Unhead

Use useHead({ title: 'Your Title' }) for a title that works in both server and client rendering. Add titleTemplate: '%s | Site Name' when pages share the same suffix.

<head>
  <title>Mastering Titles · My App</title>
</head>

The title element

The <title> tag labels the document in browser tabs and is one of several sources Google may use to generate a search-result title link.

Setting document.title directly works only in a browser:

// Browser-only: document is unavailable during SSR
document.title = 'Home'
document.title is unavailable during server-side rendering and bypasses Unhead's server output.

Google documents how page titles and other signals can influence title links in search results.

Dynamic Page Titles with useHead()

Use useHead() to register a title with the active head instance:

import { useHead } from 'unhead'

useHead(unheadInstance, {
  title: 'Home'
})

The entry is included in server output and kept in sync on the client. The same entry can include other head tags:

import { useHead } from 'unhead'

useHead(unheadInstance, {
  title: 'Home',
  meta: [
    { name: 'description', content: 'Welcome to MyApp' }
  ]
})
Unhead automatically deduplicates title tags set by multiple entries. With equal priorities, the most recently registered title takes precedence.

Reactivity follows the conventions of each framework adapter; the useHead() input shape stays the same.

Shared site names

Set a shared site name and separator with a title template:

<head>
  <title>Home | MySite</title>
</head>
import { useHead } from 'unhead'

useHead(unheadInstance, {
  title: 'Home',
  titleTemplate: '%s | MySite'
})

The %s placeholder in a string titleTemplate is replaced with the page title. Additional template params require TemplateParamsPlugin.

Template Params

Template params are an opt-in feature for making tags more dynamic. Register TemplateParamsPlugin when creating the head instance, then provide templateParams with your entry. The plugin supplies %s, %separator, and your custom parameters:

Input
import { useHead } from 'unhead'

useHead(unheadInstance, {
  title: 'Home',
  titleTemplate: '%s %separator %siteName',
  templateParams: {
    separator: '·',
    siteName: 'My Site'
  }
})
Output
<title>Home · My Site</title>
Template params are processed automatically in titles, meta content, link href, and the lang HTML attribute. Other inline content requires processTemplateParams: true on the tag.

See Template Params for the complete placeholder rules.

Resetting the Title Template

Pass null to titleTemplate to disable an inherited template for one page.

<script lang="ts" setup>
import { useHead } from 'unhead'

useHead({
  title: 'Home',
  titleTemplate: null
})
</script>

Social Share Titles

Social platforms use different meta tags for sharing titles.

Nuxt X Share
Nuxt X Share

The example preview uses X-specific title metadata alongside the standard og:title field. Use useSeoMeta() to set these fields by name:

import { useSeoMeta } from 'unhead'

useSeoMeta(unheadInstance, {
  titleTemplate: '%s | Health Tips',
  title: 'Why you should eat more broccoli',
  // ogTitle is not affected by titleTemplate; use template params here if needed
  ogTitle: 'Hey! Health Tips - 10 reasons to eat more broccoli.',
  // Legacy X-specific override; twitterTitle is deprecated in favor of ogTitle
  twitterTitle: 'Hey X! Health Tips - 10 reasons to eat more broccoli.',
})

The useSeoMeta input shape is the same across Vue, React, Svelte, Solid, and Angular.

Common Use Cases

Reactive Titles

Pass a getter to update a title when component state changes:

import { useHead } from 'unhead'
import { ref } from 'vue'

const productName = ref('Widget X')
const isLoading = ref(true)

useHead(unheadInstance, {
  title: () => isLoading.value
    ? 'Loading...'
    : `Product: ${productName.value}`
})

Hierarchical Titles

For nested pages like documentation, show hierarchy:

import { useHead } from 'unhead'

// Works in any framework
useHead(unheadInstance, {
  title: 'Installation',
  titleTemplate: '%s | Documentation | MyApp'
})

Language-Specific Titles

For multilingual sites:

import { useHead } from 'unhead'

// In a real app, you'd get this from your i18n library
const locale = 'en'

const titles = {
  en: 'Welcome',
  fr: 'Bienvenue',
  es: 'Bienvenido'
}

useHead(unheadInstance, {
  title: titles[locale] || titles.en,
  htmlAttrs: {
    lang: locale
  }
})

Writing useful titles

Google recommends descriptive, concise, page-specific title text. Search results truncate titles as needed for the device, so there is no fixed character limit.

  • Keep titles concise and descriptive rather than targeting a fixed character count
  • Make each page title unique across your site
  • Keep shared branding brief so the page-specific text remains distinct
  • Ensure titles accurately describe the page content
Did this page help you?