unjs/unhead/unhead-vue
Claude Code and agent skill by unjs/unhead
- community
Checking that the SKILL.md file is still in the repository.
Manages head tags in Vue 3 SSR and SPA apps with @unhead/vue v3 through createHead, transformHtmlTemplate, useHead, useSeoMeta, useHeadSafe, useScript, and streaming SSR. Use when a task sets titles, meta, Open Graph, or scripts in a Vue app, upgrades from @vueuse/head or Unhead v1 or v2, or hits a useHead provide context error, template params printed literally in the title, or hid and vmid attributes in the HTML.
Install
npx vskill@latest install unjs/unhead/unhead-vueSKILL.md
@unhead/vue
Tested with @unhead/vue 3.4.2, unhead 3.4.2, Vue 3.5, Vite 8, and TypeScript 6.0.3 (vue-tsc 3.3.12) and 7.0.2. Import from @unhead/vue and its subpaths, which re-export unhead. In Nuxt, Nuxt creates and installs the head. Skip Setup and use the composables.
Setup
Create one head in the browser. On the server, create a new head for each request; a shared one leaks tags between requests.
- If the template has no
<head>,transformHtmlTemplatesilently drops every tag. - A client head on the server makes
transformHtmlTemplatethrowCannot read properties of undefined (reading 'htmlAttrs'). - The Options API
head()option needsapp.mixin(VueHeadMixin)in both entries. Without it, Vue ignoreshead().
Automatic behaviour
- The server head adds
<meta charset="utf-8">, the viewport meta, and<html lang="en">. Override them withuseHeadordisableDefaults: true. The client head adds none. - Tags dedupe on
title,name,property, canonicalrel, andkey. The last entry wins.htmlAttrsandbodyAttrsmerge. - Matching tags in
index.htmlare replaced, never duplicated. When the replacing entry goes away, they stay gone, except<title>, which reverts to the first document title. For site fallbacks, calluseHead(fallback, { tagPriority: 'low' })in the root component. - The client writes the DOM one macrotask after a change, so
document.titleis still old afterawait nextTick(). To read the result, use theonRenderedentry option. - On the server, refs and getters resolve at the first
transformHtmlTemplateorhead.render()call. The result is then cached. Unhead()from@unhead/vue/viteis optional. In dev it addsValidatePlugin, which logs[unhead]warnings. In dev and build it rewrites staticuseSeoMetainput touseHead. Optionsvalidate,transformSeoMeta, andtreeshaketakefalse.
Common tasks
Reactive and async values
- Pass the ref or a getter.
- Call
useHeadsynchronously in setup. After anawaitin a callback, or in an asyncsetup()outside<script setup>, it throwsuseHead() was called without provide context. Update a ref instead, or callpatch()on an entry made in setup. Top-levelawaitin<script setup>keeps the context.
Titles
- A string template
'%s | Acme'needs no plugin. If no entry sets a title, it renders| Acme. titleTemplate: computed(title => ...)gets the previous computed value and rendersundefined | Acme, with no type error.titleTemplate: nullon a page removes an inherited template.%separator,%siteName, and othertemplateParamsneedTemplateParamsPlugin. Without it they print as text. Register it in the client entry and in each servercreateHead:
SEO meta
robots: { index: false, follow: false }renders no robots tag. Usenoindexandnofollow, or a string.content: nullremoves an inherited meta tag.useHeaddoes not sanitize. For values from users or APIs, useuseHeadSafe. It keeps only JSON scripts. It dropson*,http-equiv,javascript:anddata:URLs, and canonical, preload, prefetch, preconnect, and manifest links; set a canonical withuseHead.
Third-party scripts
- In a component, the script loads on mount with
deferandfetchpriority="low". An absolute URL also getscrossorigin="anonymous"andreferrerpolicy="no-referrer". SSR renders nothing for it unless you passtrigger: 'server'. - If the script host sends no CORS headers, the browser blocks the load. Pass
useScript({ src, crossorigin: false }). trigger: 'manual'waits forload(). ARef<boolean>or getter trigger loads when it becomes true.- Unmount does not remove the script.
proxyexists only withuseorresolve.
Streaming SSR
On the server, createStreamableHead() from @unhead/vue/stream/server returns { head, wrapStream }; return wrapStream(renderToWebStream(app), template). On the client, use createStreamableHead() from @unhead/vue/stream/client, and add Unhead({ streaming: true }) to the Vite config.
- Without the stream bootstrap, the client call returns
undefined. Throw then; otherwise eachuseHeadthrows the provide-context error. - A
useHeadcall reaches the shell<head>only if noawaitran before it, in its component or any ancestor. Later calls become inline patch scripts, which most bots ignore. Set canonical, robots, description, and Open Graph in the root or layout. wrapStreamkeeps the<title>,<meta>, and charset tags of the template, so the shell has two of each. Remove them fromindex.html.- On the client, streamed patch tags stay after their component unmounts. Set title and description on every page.
Traps
- v2 names are not converted:
hid,vmid,children, andbody: truerender as literal attributes, such as<meta hid="description">or an empty<script children="...">. The table below has the new names. - Promise values are not awaited. A promise title is dropped; a promise
contentrenders[object Promise].PromisesPluginresolves them on the client, but on the server it drops every entry that holds a promise. Await the data first. tagPriority: 'before:...'and'after:...'needAliasSortingPlugin, or Unhead ignores them.useServerHead,useServerHeadSafe, anduseServerSeoMetaare deprecated aliases that also run in the browser. WithUnhead(), only a production client build removes them. For server-only tags, useif (import.meta.env.SSR). The upgrade guide'simport.meta.serverexists only in Nuxt.- Type errors name the wrong property.
Type '"description"' is not assignable to type 'ResolvableValue<undefined>'meanscontentis missing or a v2 key is present. A font preload withoutcrossoriginfails onreloras, not oncrossorigin. Wrap a non-standardrelor scripttypeindefineLink()ordefineScript(). - The install guide says
@unhead/vue@next, which is 3.0.0-beta.9. Install@unhead/vue.
Version limits
In 3.4.2, a templateParams value of 0 renders empty. A numeric templateParams value used in a JSON script with processTemplateParams: true throws in a hook: the HTML comes back unprocessed, then Node exits on an unhandled rejection that try/catch misses. Pass strings. unhead#1002 fixes both after 3.4.2.
Upgrading from v1, v2, or @vueuse/head
| Old | 3.x | |
|---|---|---|
createHead from @unhead/vue or @vueuse/head | createHead from @unhead/vue/client or @unhead/vue/server | |
createServerHead() | createHead() from @unhead/vue/server | |
Head from @vueuse/head | Head from @unhead/vue/components | |
hid, vmid / children / body: true | key / innerHTML or textContent / tagPosition: 'bodyClose' | |
await renderSSRHead(head) | head.render(), synchronous | |
useHead(input, { mode: 'server' }) | the server entry, or import.meta.env.SSR | |
disableCapoSorting: true | tagWeight(tag) on the server createHead; lower sorts first | |
import unhead from '@unhead/vue/vite' | import { Unhead } from '@unhead/vue/vite' | |
script.then(), script.track() | script.onLoaded(), script.proxy.track() |
Debug
Without the Vite plugin, add ValidatePlugin() from @unhead/vue/plugins when import.meta.env.DEV is true; it also logs in production. It flags a missing TemplateParamsPlugin only if templateParams is set.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingpackages/vue/skills/unhead-vue/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/unjs/unhead/unhead-vue)