unhead
Manage document head tags, meta, and SEO data reactively across any JavaScript framework
Repository Health
Technical Analysis
unhead is a framework-agnostic document <head> manager for building reactive, SSR-friendly title, meta, link, and script tags in JavaScript applications. It provides a plugin-driven core (deduplication, tag sorting, template params, minification) consumed by dedicated bindings for Vue, React, Svelte, Solid, and Angular.
Originally built to power Nuxt’s useHead composable, unhead is now a standalone package used across the broader JavaScript ecosystem for managing SEO-critical head tags with proper server-side rendering support and conflict resolution between competing tag declarations.
What You Get
- A framework-agnostic core (
unhead) for managing document head tags with SSR support - Official bindings for Vue, React, Svelte, Solid, and Angular built on the same underlying engine
- Automatic tag deduplication, priority-based sorting, and conflict resolution between multiple
useHead()calls - A plugin system (
aliasSorting,templateParams,minify,inferSeoMetaPlugin,canonical, and more) for extending head-processing behavior - A
schema-orgcompanion package for structured-data (JSON-LD) generation alongside head tags
Common Use Cases
- Managing page titles, meta descriptions, and Open Graph tags reactively across route changes in an SPA or SSR app
- Powering
useHead()-style composables in meta-frameworks like Nuxt that need consistent, SSR-safe head tag rendering - Injecting canonical URLs, structured data (JSON-LD), and social preview tags for SEO across a multi-framework codebase
- Deduplicating and merging head tags contributed by multiple nested components without manual coordination
Under The Hood
Architecture — The core unhead package (11,400+ lines across client/, server/, parser/, plugins/, scripts/, stream/, utils/, and validate/) resolves a queue of head-tag “entries” contributed by different call sites into a single deduplicated, priority-sorted output, applying the plugins/ pipeline (alias sorting, template-param interpolation, minification, safe-mode filtering) before rendering client-side or streaming server-side. Framework packages (packages/react, packages/vue, etc.) are thin adapters that hook into each framework’s reactivity/lifecycle system and delegate the actual tag-processing logic back to this shared core, keeping behavior consistent across frameworks.
Tech Stack — TypeScript-first (93% of the codebase) monorepo managed with pnpm workspaces, with a small Vue-specific slice (6%) for the Vue package’s own tooling. The repo includes bench/ for performance benchmarking, examples/ demonstrating each framework integration, and a devtools-app/ for a dedicated Vue DevTools-style inspector.
Code Quality — The monorepo contains 197 .test.ts files spanning the core engine and every framework adapter, indicating substantial automated coverage across an unusually wide integration surface (5 frameworks sharing one engine). The project maintains an extremely active release cadence (100 tagged releases, ~51 commits/month) with continuous point releases through mid-2026, and ships dedicated eslint-plugin and cli packages as first-class tooling around the core library.
API Design — The useHead() composable pattern (borrowed from and popularized via Nuxt) lets any component contribute head tags declaratively without needing to know about other contributors, while the plugin system exposes hooks (templateParams, inferSeoMetaPlugin) for common SEO patterns without requiring consumers to hand-roll tag merging logic themselves.