Fix: Importing from @unhead/vue Directly in Nuxt

Error message:
Importing `{function}` from `@unhead/vue` is not recommended. Use the auto-imported composables instead.
head 2025-01-25

What Causes This Warning?

This warning appears when you import head management functions directly from @unhead/vue instead of using Nuxt’s auto-imported composables. Nuxt provides these functions automatically with proper integration.

The Problem

<script setup>
// ❌ Wrong - direct import
import { useHead, useSeoMeta } from '@unhead/vue'

useHead({
  title: 'My Page'
})
</script>

The Fix

Use Auto-Imports

<script setup>
// ✅ Correct - no import needed, auto-imported by Nuxt
useHead({
  title: 'My Page'
})

useSeoMeta({
  title: 'My Page',
  description: 'Page description'
})
</script>

Available Auto-Imports

These are automatically available in Nuxt without imports:

<script setup>
// All auto-imported - no import statement needed

// Basic head management
useHead({
  title: 'Page Title',
  meta: [
    { name: 'description', content: 'Description' }
  ]
})

// SEO meta
useSeoMeta({
  title: 'SEO Title',
  ogTitle: 'Open Graph Title',
  description: 'Meta description',
  ogDescription: 'OG Description',
  ogImage: 'https://example.com/image.jpg'
})

// Server-only head
useServerHead({
  link: [{ rel: 'canonical', href: 'https://example.com' }]
})

// Head with template
useHeadSafe({
  title: userInput  // Sanitized automatically
})
</script>

Why Use Auto-Imports?

1. Proper Context

Nuxt’s auto-imports are integrated with the Nuxt context:

<script setup>
// ✅ Auto-import - has Nuxt context
useHead({
  title: 'Works with SSR and client'
})
</script>

2. Type Safety

<script setup lang="ts">
// ✅ Types work correctly with auto-imports
useHead({
  title: 'My Page',
  meta: [
    { name: 'description', content: 'Description' }
  ]
})
</script>

3. SSR Support

Auto-imported functions work seamlessly with Nuxt’s SSR:

<script setup>
// ✅ Properly handles server and client rendering
useSeoMeta({
  title: 'Server-rendered meta tags'
})
</script>

Composables Pattern

// composables/usePage.ts
export function usePageMeta(options: { title: string; description: string }) {
  // ✅ Auto-imports work in composables too
  useHead({
    title: options.title
  })

  useSeoMeta({
    title: options.title,
    description: options.description
  })
}

Usage:

<script setup>
// ✅ Use custom composable
usePageMeta({
  title: 'Products',
  description: 'Browse our products'
})
</script>

Dynamic Head

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

// ✅ Reactive head using computed
useHead({
  title: computed(() => product.value?.name || 'Loading...')
})

useSeoMeta({
  title: computed(() => product.value?.name),
  ogImage: computed(() => product.value?.image)
})
</script>

In nuxt.config.ts

For global head configuration:

// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      title: 'Default Title',
      meta: [
        { charset: 'utf-8' },
        { name: 'viewport', content: 'width=device-width, initial-scale=1' }
      ],
      link: [
        { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
      ]
    }
  }
})

If You Must Import

In rare cases (like testing or library code), explicitly import from #imports:

// ✅ Import from #imports if needed
import { useHead, useSeoMeta } from '#imports'

Not from @unhead/vue:

// ❌ Don't do this in Nuxt
import { useHead } from '@unhead/vue'

Suppressing the Warning

If you have a valid reason to import directly:

// @ts-expect-error - Using direct import intentionally
import { useHead } from '@unhead/vue'

But this is almost never necessary in Nuxt applications.

Quick Checklist

  • Don’t import from @unhead/vue directly
  • Use auto-imported useHead, useSeoMeta, etc.
  • Auto-imports work in components and composables
  • Use #imports if explicit import needed
  • Configure global head in nuxt.config.ts
  • Use computed() for reactive head values