Fix: Title Can Take Only One String in Nuxt

Error message:
<Title> can take only one string in its default slot.
head 2025-01-25

What Causes This Error?

This error occurs when you pass multiple elements or non-string content to the <Title> component from @unhead/vue or Nuxt’s head management.

The Problem

<!-- ❌ Wrong - multiple elements -->
<template>
  <Title>
    <span>My Site</span>
    <span> - Home</span>
  </Title>
</template>

<!-- ❌ Wrong - component inside Title -->
<template>
  <Title>
    <MyTitleComponent />
  </Title>
</template>

<!-- ❌ Wrong - mixed content -->
<template>
  <Title>
    Home
    <span>Page</span>
  </Title>
</template>

The Fix

Pass only a single string:

<!-- ✅ Correct - simple string -->
<template>
  <Title>My Site - Home</Title>
</template>

<!-- ✅ Correct - interpolated string -->
<template>
  <Title>{{ pageTitle }} - My Site</Title>
</template>

<!-- ✅ Correct - computed string -->
<template>
  <Title>{{ fullTitle }}</Title>
</template>

<script setup>
const pageTitle = ref('Home')
const fullTitle = computed(() => `${pageTitle.value} - My Site`)
</script>

Alternative: Use useHead

For dynamic titles, useHead is often cleaner:

<script setup>
const pageTitle = ref('Home')

useHead({
  title: computed(() => `${pageTitle.value} - My Site`)
})
</script>

<template>
  <!-- No Title component needed -->
  <div>Content</div>
</template>

Alternative: Use useSeoMeta

For SEO-focused titles:

<script setup>
useSeoMeta({
  title: 'Home - My Site',
  ogTitle: 'Home - My Site'
})
</script>

With Title Template

Use titleTemplate for consistent formatting:

// nuxt.config.ts or app.vue
useHead({
  titleTemplate: '%s - My Site'
})

Then in pages:

<script setup>
useHead({
  title: 'Home'  // Becomes "Home - My Site"
})
</script>

Dynamic Titles

<script setup>
const route = useRoute()
const { data: post } = await useFetch(`/api/posts/${route.params.id}`)

useHead({
  title: computed(() => post.value?.title || 'Loading...')
})
</script>

Similar Error: Style Component

The same rule applies to <Style>:

<!-- ❌ Wrong -->
<template>
  <Style>
    <span>.class { color: red; }</span>
  </Style>
</template>

<!-- ✅ Correct -->
<template>
  <Style>.class { color: red; }</Style>
</template>

Quick Reference

UsageValid?
<Title>Simple Text</Title>✅ Yes
<Title>{{ variable }}</Title>✅ Yes
<Title>{{ a }} - {{ b }}</Title>✅ Yes
<Title><span>Text</span></Title>❌ No
<Title>Text<br/>More</Title>❌ No
useHead({ title: 'Text' })✅ Yes

Best Practices

  1. Prefer useHead - More flexible and composable
  2. Use titleTemplate - For consistent site-wide formatting
  3. Compute titles - Use computed() for reactive titles
  4. Keep it simple - Titles should be plain strings

Quick Checklist

  • Title contains only text, no HTML elements
  • No components inside Title
  • Use string interpolation for dynamic parts
  • Consider using useHead instead
  • Check <Style> components for same issue