<head>
meta tagsTo add <head>
tags, such as <title>
and <meta name="description">
, you can use:
These options are implemented by the UI framework Vike extension (vike-react
/vike-vue
/vike-solid
). See Without Vike extension if you don't use such extension.
Head
To add <head>
tags to all your pages:
// /pages/+Head.jsx or
// /pages/+Head.vue
// Environment: server
export { Head }
import socialImage from '../assets/images/socialImage.jpg'
import favicon from '../assets/images/favicon.png'
function Head () {
return <>
< meta charset = "utf-8" >
< title >SpaceX</ title >
< meta name = "description" content = "We deliver payload to space." >
< meta property = "og:image" content = {socialImage}>
< link rel = "icon" href = {favicon}>
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
</>
}
Example: React / Vue / Solid .
Setting <head>
tags only to one page and based on fetched data :
// /pages/rocket/starship/+data.js
// Environment: server
export { data }
async function data () {
const rocket = await sql. run (
'SELECT { title, description, social_image } FROM rockets WHERE name = "starship";'
)
return rocket
}
// /pages/rocket/starship/+Head.jsx
// Environment: server
export { Head }
import { useData } from 'vike-react/useData' // or 'vike-vue' / 'vike-solid'
function Head () {
const rocket = useData ()
return <>
< meta name = "description" content = {rocket.description}>
< meta property = "og:image" content = {rocket.social_image}>
</>
}
title
& favicon
If your pages can have different <title>
values, then use the setting title
instead of the Head
setting:
// /pages/rocket/starship/+title.js
// Environment: server, client
export const title = 'SpaceX | Rocket Starship'
// /pages/rocket/falcon-9/+title.js
// Environment: server, client
export const title = 'SpaceX | Rocket Falcon 9'
Upon client-side navigating from the URL /rocket/starship
to /rocket/falcon-9
, the page's title is dynamically updated from SpaceX | Rocket Starship
to SpaceX | Rocket Falcon 9
. (By mutating the DOM with document.title = 'SpaceX | Rocket Falcon 9'
.)
While defining <title>
by using the Head
setting correctly sets the page's title for the first page the user visits, it doesn't update the page's title upon client-side navigation .
Most <head>
tags, such as the social image tag <meta property="og:image">
, don't need to be updated upon client-side navigation because they are only used by crawlers. (Browsers don't do anything with <meta property="og:image">
.) Crawlers don't execute JavaScript and, therefore, don't client-side navigate.
Likewise, if your favicon can change from page to page, then define /pages/rocket/starship/+favicon.png
instead of using the Head
setting.
You can set title
and favicon
based on fetched data , for example:
// /pages/rocket/starship/+title.js
// Environment: server, client
export function title ( pageContext ) {
const rocket = pageContext.data
return rocket.title
}
// With TypeScript:
import type { Data } from './+data'
import type { PageContext } from 'vike/types'
export function title ( pageContext : PageContext < Data >) {
const rocket = pageContext.data
return rocket.title
}
As shown here you can define the logic, of using data.title
to set the page's title, once and apply it to all your pages.
useHead()
The upcoming useHead()
component hook will enable any UI component to add <head>
tags, see: New component hook useHead()
.
Internationalization
Example of internationalizing (i18n) <head>
tags:
// /pages/+Head.js
// Environment: server
export { Head }
import { usePageContext } from 'vike-react/usePageContext' // or 'vike-vue' / 'vike-solid'
function Head () {
const pageContext = usePageContext ()
const description = pageContext.locale === 'de-DE' ?
'Wir liefern zum Weltall.' :
'We deliver payload to space.'
return <>
< meta name = "description" content = {description}>
</>
}
// /pages/+title.js
// Environment: server, client
export function title ( pageContext ) {
const title = pageContext.locale === 'de-DE' ?
'SpaceX | Das Weltall Unternehmen' :
'SpaceX | The space company'
return title
}
See also:
Without Vike extension
If you don't use a Vike extension, then you have direct control over <head>
tags in your onRenderHtml()
hook .
// /renderer/+onRenderHtml.js
// Environment: server
import { escapeInject, dangerouslySkipEscape } from 'vike/server'
import { renderToHtml } from 'some-ui-framework'
export { onRenderHtml }
async function onRenderHtml ( pageContext ) {
return escapeInject `<html>
<head>
<title>SpaceX</title>
<meta name="description" content="We deliver payload to space.">
</head>
<body>
<div id="root">
${ dangerouslySkipEscape ( await renderToHtml ( pageContext . Page )) }
</div>
</body>
</html>`
}
By page
To define <head>
tags on page-by-page basis, we recommend creating new settings, for example title
and description
as shown at API > meta
> Example: title
and description
.
By component
To define <head>
tags by any UI component:
Add 'headProps'
to passToClient
.
Use usePageContext()
so that pageContext.headProps
can be accessed and modified by any component.
For example:
// /renderer/+onRenderHtml.js
// Environment: server
export { onRenderHtml }
import { escapeInject, dangerouslySkipEscape } from 'vike/server'
import renderToHtml from 'some-ui-framework'
async function onRenderHtml ( pageContext ) {
// We use our UI framework to pass `pageContext.headProps` to all components
// of our component tree. (E.g. React Context or Vue's `app.config.globalProperties`.)
const pageHtml = await renderToHtml (
< ContextProvider headProps = {pageContext.headProps} >
< Page />
</ ContextProvider >
)
// 1. One of our UI component modified pageContext.headProps while rendering components.
// 2. We now render `headProps` to HTML meta tags.
return escapeInject `<html>
<head>
<title>${ pageContext . headProps . title }</title>
<meta name="description" content="${ pageContext . headProps . description }">
</head>
<body>
<div id="app">
${ dangerouslySkipEscape ( pageHtml ) }
</div>
</body>
</html>`
}
// SomeComponent.js
// Inside a UI component
const pageContext = usePageContext ()
const { headProps } = pageContext
headProps.title = 'I was set by some component.'
headProps.description = 'Me too.'
Client Routing
If you use Client Routing, make sure to update document.title
upon page navigation:
// /renderer/+config.js
// Environment: config
export default {
// Make pageContext.headProps available on the client-side.
passToClient: [ 'headProps' ]
}
// /renderer/+onRenderClient.js
// Environment: client
export { onRenderClient }
async function onRenderClient ( pageContext ) {
if ( ! pageContext.isHydration) {
// Client-side navigation — we update the page's title
document.title = pageContext.headProps.title
}
// ...
}
Libraries
You can also use libraries such as @vueuse/head or react-helmet .
But we recommend using such library only if you have a rationale as the aforementioned solutions are simpler.
Head libraries already sanitize the HTML <head>
, this means you can skip escapeInject
and wrap the overall result with dangerouslySkipEscape()
.
// /renderer/+onRenderHtml.js
// Environment: server
export { onRenderHtml }
import { dangerouslySkipEscape } from 'vike/server'
import { renderToHtml } from 'some-ui-framework'
async function onRenderHtml ( pageContext ) {
return dangerouslySkipEscape ( await renderToHtml (pageContext.Page))
}
See also