0
# Head Management
1
2
Document head management with reactive updates, SEO optimization, and server-side rendering support. Nuxt provides comprehensive utilities for managing meta tags, titles, and other head elements with full SSR support.
3
4
## Capabilities
5
6
### Basic Head Management
7
8
Manage document head elements with reactive updates.
9
10
```typescript { .api }
11
/**
12
* Manage document head with reactive updates
13
* @param meta - Meta object or reactive reference to meta object
14
*/
15
function useHead(meta: MaybeComputedRef<MetaObject>): void;
16
17
/**
18
* Safe version of useHead that sanitizes input
19
* @param meta - Meta object or reactive reference to meta object
20
*/
21
function useHeadSafe(meta: MaybeComputedRef<MetaObject>): void;
22
23
/**
24
* Inject head client directly for advanced usage
25
* @returns HeadClient instance
26
*/
27
function injectHead(): HeadClient;
28
29
interface MetaObject {
30
/** Page title */
31
title?: MaybeComputedRef<string>;
32
/** Title template for dynamic titles */
33
titleTemplate?: MaybeComputedRef<string | ((title?: string) => string)>;
34
/** Meta tags */
35
meta?: MaybeComputedRef<MetaObjectRaw[]>;
36
/** Link tags */
37
link?: MaybeComputedRef<LinkObject[]>;
38
/** Style tags */
39
style?: MaybeComputedRef<StyleObject[]>;
40
/** Script tags */
41
script?: MaybeComputedRef<ScriptObject[]>;
42
/** Noscript tags */
43
noscript?: MaybeComputedRef<NoscriptObject[]>;
44
/** Base tag */
45
base?: MaybeComputedRef<BaseObject>;
46
/** Body attributes */
47
bodyAttrs?: MaybeComputedRef<Record<string, any>>;
48
/** HTML attributes */
49
htmlAttrs?: MaybeComputedRef<Record<string, any>>;
50
}
51
52
interface MetaObjectRaw {
53
name?: string;
54
property?: string;
55
"http-equiv"?: string;
56
content?: string;
57
charset?: string;
58
[key: string]: any;
59
}
60
```
61
62
**Usage Examples:**
63
64
```typescript
65
// Basic title and meta
66
useHead({
67
title: "My Page Title",
68
meta: [
69
{ name: "description", content: "Page description" },
70
{ name: "keywords", content: "nuxt, vue, ssr" }
71
]
72
});
73
74
// Reactive head management
75
const pageTitle = ref("Dynamic Title");
76
const pageDescription = ref("Dynamic description");
77
78
useHead({
79
title: pageTitle,
80
meta: [
81
{ name: "description", content: pageDescription }
82
]
83
});
84
85
// Title template
86
useHead({
87
titleTemplate: (title) => title ? `${title} - My App` : "My App"
88
});
89
90
// Complex head configuration
91
useHead({
92
title: "Article Title",
93
meta: [
94
{ name: "description", content: "Article description" },
95
{ name: "author", content: "John Doe" },
96
{ name: "robots", content: "index,follow" },
97
{ property: "og:title", content: "Article Title" },
98
{ property: "og:description", content: "Article description" },
99
{ property: "og:image", content: "/images/article.jpg" },
100
{ property: "og:type", content: "article" },
101
{ name: "twitter:card", content: "summary_large_image" }
102
],
103
link: [
104
{ rel: "canonical", href: "https://example.com/article" },
105
{ rel: "alternate", hreflang: "es", href: "https://example.com/es/article" }
106
]
107
});
108
109
// Safe head management (auto-sanitized)
110
useHeadSafe({
111
title: userInput, // Will be sanitized
112
meta: [
113
{ name: "description", content: userDescription } // Will be sanitized
114
]
115
});
116
```
117
118
### SEO Meta Management
119
120
Specialized utilities for SEO-focused meta tag management.
121
122
```typescript { .api }
123
/**
124
* Manage SEO-specific meta tags
125
* @param meta - SEO meta object
126
*/
127
function useSeoMeta(meta: MaybeComputedRef<SeoMetaObject>): void;
128
129
interface SeoMetaObject {
130
/** Page title */
131
title?: MaybeComputedRef<string>;
132
/** Meta description */
133
description?: MaybeComputedRef<string>;
134
/** Keywords */
135
keywords?: MaybeComputedRef<string | string[]>;
136
/** Author */
137
author?: MaybeComputedRef<string>;
138
/** Robots directive */
139
robots?: MaybeComputedRef<string>;
140
/** Copyright */
141
copyright?: MaybeComputedRef<string>;
142
/** Language */
143
language?: MaybeComputedRef<string>;
144
/** Theme color */
145
themeColor?: MaybeComputedRef<string>;
146
/** Color scheme */
147
colorScheme?: MaybeComputedRef<string>;
148
/** Viewport */
149
viewport?: MaybeComputedRef<string>;
150
/** Canonical URL */
151
canonical?: MaybeComputedRef<string>;
152
153
// Open Graph
154
/** OG title */
155
ogTitle?: MaybeComputedRef<string>;
156
/** OG description */
157
ogDescription?: MaybeComputedRef<string>;
158
/** OG image */
159
ogImage?: MaybeComputedRef<string | OgImageObject>;
160
/** OG URL */
161
ogUrl?: MaybeComputedRef<string>;
162
/** OG type */
163
ogType?: MaybeComputedRef<string>;
164
/** OG site name */
165
ogSiteName?: MaybeComputedRef<string>;
166
/** OG locale */
167
ogLocale?: MaybeComputedRef<string>;
168
169
170
/** Twitter card type */
171
twitterCard?: MaybeComputedRef<string>;
172
/** Twitter title */
173
twitterTitle?: MaybeComputedRef<string>;
174
/** Twitter description */
175
twitterDescription?: MaybeComputedRef<string>;
176
/** Twitter image */
177
twitterImage?: MaybeComputedRef<string>;
178
/** Twitter site */
179
twitterSite?: MaybeComputedRef<string>;
180
/** Twitter creator */
181
twitterCreator?: MaybeComputedRef<string>;
182
}
183
184
interface OgImageObject {
185
url: string;
186
width?: number;
187
height?: number;
188
alt?: string;
189
type?: string;
190
}
191
```
192
193
**Usage Examples:**
194
195
```typescript
196
// Basic SEO meta
197
useSeoMeta({
198
title: "My Page",
199
description: "Comprehensive description of my page content",
200
keywords: ["nuxt", "vue", "ssr", "framework"],
201
author: "John Doe",
202
robots: "index,follow"
203
});
204
205
// Social media optimization
206
useSeoMeta({
207
title: "Amazing Article",
208
description: "This article will change your perspective on web development",
209
210
// Open Graph
211
ogTitle: "Amazing Article - My Blog",
212
ogDescription: "This article will change your perspective on web development",
213
ogImage: {
214
url: "https://example.com/images/article-cover.jpg",
215
width: 1200,
216
height: 630,
217
alt: "Article cover image"
218
},
219
ogUrl: "https://example.com/articles/amazing-article",
220
ogType: "article",
221
ogSiteName: "My Blog",
222
ogLocale: "en_US",
223
224
225
twitterCard: "summary_large_image",
226
twitterTitle: "Amazing Article",
227
twitterDescription: "This article will change your perspective",
228
twitterImage: "https://example.com/images/article-cover.jpg",
229
twitterSite: "@myblog",
230
twitterCreator: "@johndoe"
231
});
232
233
// Reactive SEO meta
234
const article = ref({
235
title: "Dynamic Article",
236
description: "Dynamic description",
237
image: "/images/default.jpg"
238
});
239
240
useSeoMeta({
241
title: () => article.value.title,
242
description: () => article.value.description,
243
ogImage: () => article.value.image,
244
twitterImage: () => article.value.image
245
});
246
247
// E-commerce product SEO
248
const product = await useFetch(`/api/products/${route.params.id}`);
249
250
useSeoMeta({
251
title: () => `${product.data.value?.name} - Shop`,
252
description: () => product.data.value?.description,
253
keywords: () => product.data.value?.tags,
254
ogType: "product",
255
ogImage: () => product.data.value?.images[0],
256
ogPrice: () => product.data.value?.price,
257
ogCurrency: "USD"
258
});
259
```
260
261
### Server-Side Head Management
262
263
Server-only head management utilities.
264
265
```typescript { .api }
266
/**
267
* Server-only head management
268
* @param meta - Meta object for server-side rendering
269
*/
270
function useServerHead(meta: MaybeComputedRef<MetaObject>): void;
271
272
/**
273
* Safe server-only head management
274
* @param meta - Meta object for server-side rendering
275
*/
276
function useServerHeadSafe(meta: MaybeComputedRef<MetaObject>): void;
277
278
/**
279
* Server-only SEO meta management
280
* @param meta - SEO meta object for server-side rendering
281
*/
282
function useServerSeoMeta(meta: MaybeComputedRef<SeoMetaObject>): void;
283
```
284
285
**Usage Examples:**
286
287
```typescript
288
// Server-only head management
289
if (process.server) {
290
useServerHead({
291
script: [
292
{
293
innerHTML: `
294
window.serverData = ${JSON.stringify(serverData)};
295
`
296
}
297
]
298
});
299
}
300
301
// Server-side SEO optimization
302
useServerSeoMeta({
303
title: () => `${pageData.title} - ${siteName}`,
304
description: () => pageData.description,
305
canonical: () => `${baseUrl}${route.path}`,
306
307
// Generate structured data on server
308
script: [
309
{
310
type: "application/ld+json",
311
innerHTML: JSON.stringify({
312
"@context": "https://schema.org",
313
"@type": "Article",
314
"headline": pageData.title,
315
"description": pageData.description,
316
"author": pageData.author,
317
"datePublished": pageData.publishedAt
318
})
319
}
320
]
321
});
322
323
// Server-side analytics
324
useServerHead({
325
script: [
326
{
327
src: "https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID",
328
async: true
329
},
330
{
331
innerHTML: `
332
window.dataLayer = window.dataLayer || [];
333
function gtag(){dataLayer.push(arguments);}
334
gtag('js', new Date());
335
gtag('config', 'GA_MEASUREMENT_ID');
336
`
337
}
338
]
339
});
340
```
341
342
### Advanced Head Management Patterns
343
344
```typescript
345
// Conditional head management
346
const isDarkMode = useCookie("theme", { default: () => "light" });
347
348
useHead({
349
htmlAttrs: {
350
"data-theme": isDarkMode
351
},
352
meta: [
353
{
354
name: "theme-color",
355
content: () => isDarkMode.value === "dark" ? "#1a1a1a" : "#ffffff"
356
}
357
]
358
});
359
360
// Localized head management
361
const { locale, t } = useI18n();
362
363
useHead({
364
htmlAttrs: {
365
lang: locale
366
},
367
title: () => t("page.title"),
368
meta: [
369
{ name: "description", content: () => t("page.description") },
370
{ property: "og:locale", content: locale }
371
]
372
});
373
374
// Progressive enhancement
375
const supportsWebP = ref(false);
376
377
onMounted(async () => {
378
supportsWebP.value = await checkWebPSupport();
379
});
380
381
useHead({
382
link: [
383
{
384
rel: "preload",
385
as: "image",
386
href: () => supportsWebP.value ? "/hero.webp" : "/hero.jpg"
387
}
388
]
389
});
390
391
// Performance optimization
392
useHead({
393
link: [
394
// DNS prefetch
395
{ rel: "dns-prefetch", href: "//fonts.googleapis.com" },
396
{ rel: "dns-prefetch", href: "//api.example.com" },
397
398
// Preconnect
399
{ rel: "preconnect", href: "https://fonts.gstatic.com", crossorigin: "" },
400
401
// Resource hints
402
{ rel: "prefetch", href: "/next-page" },
403
{ rel: "preload", href: "/critical.css", as: "style" },
404
{ rel: "preload", href: "/hero.jpg", as: "image" }
405
]
406
});
407
408
// Error page head
409
const error = useError();
410
411
watch(error, (newError) => {
412
if (newError) {
413
useHead({
414
title: `Error ${newError.statusCode}`,
415
meta: [
416
{ name: "robots", content: "noindex,nofollow" }
417
]
418
});
419
}
420
});
421
```
422
423
### Dynamic Script and Style Management
424
425
```typescript
426
// Dynamic script loading
427
const loadGoogleMaps = ref(false);
428
429
useHead({
430
script: [
431
{
432
src: "https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY",
433
async: true,
434
onload: "window.initMap()",
435
condition: () => loadGoogleMaps.value
436
}
437
]
438
});
439
440
// Conditional styles
441
const isHighContrast = useCookie("high-contrast", { default: () => false });
442
443
useHead({
444
style: [
445
{
446
innerHTML: `
447
:root {
448
--text-color: ${isHighContrast.value ? "#000" : "#333"};
449
--bg-color: ${isHighContrast.value ? "#fff" : "#f5f5f5"};
450
}
451
`
452
}
453
]
454
});
455
456
// Third-party integrations
457
const enableAnalytics = ref(true);
458
459
useHead({
460
script: [
461
{
462
src: "https://www.googletagmanager.com/gtag/js?id=GA_ID",
463
async: true,
464
condition: () => enableAnalytics.value
465
},
466
{
467
innerHTML: `
468
window.dataLayer = window.dataLayer || [];
469
function gtag(){dataLayer.push(arguments);}
470
gtag('js', new Date());
471
gtag('config', 'GA_ID');
472
`,
473
condition: () => enableAnalytics.value
474
}
475
]
476
});
477
```
478
479
## Types
480
481
```typescript { .api }
482
type MaybeComputedRef<T> = T | Ref<T> | ComputedRef<T> | (() => T);
483
484
interface HeadClient {
485
push(input: MetaObject): ActiveHeadEntry;
486
resolveTags(): HeadTag[];
487
}
488
489
interface ActiveHeadEntry {
490
dispose(): void;
491
patch(input: MetaObject): void;
492
}
493
494
interface HeadTag {
495
tag: string;
496
attrs: Record<string, any>;
497
innerHTML?: string;
498
textContent?: string;
499
}
500
501
interface LinkObject {
502
rel?: string;
503
href?: string;
504
type?: string;
505
media?: string;
506
sizes?: string;
507
color?: string;
508
title?: string;
509
as?: string;
510
crossorigin?: string;
511
referrerpolicy?: string;
512
integrity?: string;
513
hreflang?: string;
514
[key: string]: any;
515
}
516
517
interface StyleObject {
518
innerHTML?: string;
519
textContent?: string;
520
media?: string;
521
type?: string;
522
[key: string]: any;
523
}
524
525
interface ScriptObject {
526
src?: string;
527
innerHTML?: string;
528
textContent?: string;
529
type?: string;
530
async?: boolean;
531
defer?: boolean;
532
crossorigin?: string;
533
integrity?: string;
534
nomodule?: boolean;
535
nonce?: string;
536
referrerpolicy?: string;
537
onload?: string;
538
onerror?: string;
539
condition?: () => boolean;
540
[key: string]: any;
541
}
542
543
interface NoscriptObject {
544
innerHTML?: string;
545
textContent?: string;
546
[key: string]: any;
547
}
548
549
interface BaseObject {
550
href?: string;
551
target?: string;
552
[key: string]: any;
553
}
554
```