Edit this page

<head> tags

Use following settings to set <head> tags (aka document metadata).

SettingHTML <head> tags
+title
<title>
<meta property="og:title">
+description
<meta name="description">
<meta property="og:description">
+image

Preview image upon sharing URLs:

<meta property="og:image">
<meta name="twitter:card" content="summary_large_image">
+viewport

For mobile responsive design:

<meta name="viewport">
+Head

Other <head> tags, for example:

<link rel="icon"> <!-- Favicon -->
<link rel="apple-touch-icon"> <!-- Mobile icon -->
<script></script>
<!-- ... -->

See API > Settings > HTML shell for other settings that also modify the page's HTML shell.

These settings are provided by vike-react/vike-vue/vike-solid. If you don't use vike-react/vike-vue/vike-solid then see <head> tags without vike-{react,vue,solid}.

Global / per-page

You can set <head> tags that apply globally to all pages:

// pages/+config.js
 
import image from './previewImage.jpg'
 
// Applies to all pages (can be overridden)
export default {
  // Default <title>
  title: 'Awesome Rockets',
  // Default <meta name="description">
  description: 'We deliver payload to space',
  // Default <meta property="og:image">
  image
}
// pages/+Head.js
// Environment: server
 
import favicon from './favicon.png'
 
// Applies to all pages (cannot be overridden)
export function Head() {
  return <>
    {/* Icon shown in the browser tab (aka favicon) */
    <link rel="icon" href={favicon} type="image/svg+xml">
  </>
}

You can also set <head> tags only for a single page or a group of pages:

// pages/movies/+config.js
 
import previewImage from './previewImage.jpg'
 
// Overrides the defaults defined above
export default {
  title: 'Movies',
  description: 'List of movies.',
  image
}
// pages/movies/+Head.js
// Environment: server
 
import iconMobile from './iconMobile.jpg'
 
// This doesn't override the favicon defined at /pages/+Head.js above
export function Head() {
  return <>
    {/* Icon shown on mobile homescreens (PWA) */
    <link rel="apple-touch-icon" href={iconMobile} type="image/svg+xml">
  </>
}

While +title, +description, and +image can be overridden (they aren't cumulative), the +Head setting is cumulative and cannot be overridden — see API > Head > Cumulative.

See also: API > Config Files > Inheritance

Data

You can set <head> tags based on fetched data, using either:

  • useConfig(), or
  • pageContext functions.

useConfig()

You can use the useConfig() hook to set <head> tags dynamically inside your +data hook.

// pages/movies/+data.js
 
import { useConfig } from 'vike-react/useConfig' // or vike-{vue,solid}
 
export async function data(pageContext) {
  const config = useConfig()
 
  const response = await fetch('https://star-wars.brillout.com/api/films.json')
  let { movies } = await response.json()
 
  config({
    title: `${movies.length} movies`,
    description: `List of all ${movies.length} Star Wars movies.`
  })
 
  return { movies }
}

Make sure to call useConfig() before any await:

export async function data(pageContext) {
  const response = await fetch('https://star-wars.brillout.com/api/films.json')
  // ❌ Doesn't work: useConfig() must be called before `await fetch()`
  const config = useConfig()
}

You can also use it inside UI components, see API > useConfig() > UI components.

pageContext functions

You can set +title, +description and +image using a pageContext function.

// pages/movies/+title.ts
 
import type { PageContext } from 'vike/types'
import type { Data } from './+data'
 
export default (pageContext: PageContext<Data>) => `${pageContext.data.movies.length} movies`
// pages/movies/+data.ts
 
export type Data = Awaited<ReturnType<typeof data>>
export async function data(pageContext) {
  const response = await fetch('https://star-wars.brillout.com/api/films.json')
  let { movies } = await response.json()
  return { movies }
}

You can define some default logic that applies to all pages:

// pages/+title.js
 
// Applies to all pages: if a page fetches data and data.title is defined then
// use it to set the page's title.
export default (pageContext) => pageContext.data?.title || 'Some Default Title'

The +Head setting is a UI component — you can use useData() and usePageContext() as usual:

// pages/movie/@id/+Head.js
 
import { useData } from 'vike-react/useData' // or vike-{vue,solid}
 
export function Head() {
  const data = useData()
  return <>
    {/* Image shown when sharing on social sites (Twitter, WhatsApp, ...) */}
    <meta property="og:image" content={data.movie.image}>
  </>
}

Custom settings

You can create your own custom settings.

You can also create custom components hooks, see for example vike-metadata.

For example, in the following, we create a new setting +dynamicFavicon that allows different favicons to be set for different pages. (Note that +Head can only be used for setting a global favicon, see API > Head > Only HTML.)

Setting creation

// pages/+config.js
 
export default {
  meta: {
    dynamicFavicon: {
      env: { server: true, client: true }
    }
  }
}

See: API > meta

// pages/+Head.jsx
 
import { usePageContext } from 'vike-react/usePageContext' // or vike-{vue,solid}
 
export default () => {
  const pageContext = usePageContext()
  const { dynamicFavicon } = pageContext.config
  return <>
    { dynamicFavicon && <link rel="icon" href={dynamicFavicon} type="image/svg+xml"> }
  <>
}
// pages/+onAfterRenderClient.js
 
export default (pageContext) => {
  if (!pageContext.isHydration) {
    const { dynamicFavicon } = pageContext.config
    updateFavicon(dynamicFavicon)
  }
}
 
// https://stackoverflow.com/questions/260857/changing-website-favicon-dynamically
function updateFavicon(dynamicFavicon) {
  let link = document.querySelector("link[rel~='icon']")
  if (!dynamicFavicon) {
    if (link) document.head.removeChild(link)
    return
  }
  if (!link) {
    link = document.createElement('link')
    link.rel = 'icon'
    document.head.appendChild(link)
  }
  link.href = dynamicFavicon
}

For TypeScript users:

// pages/+config.js
 
declare global {
  namespace Vike {
    interface Config {
      dynamicFavicon?: string
    }
  }
}

See: API > meta > Typescript

Setting usage

// pages/+config.js
 
import favicon from './favicon.svg'
 
export {
  // Default favicon
  dynamicFavicon: favicon
}
// pages/premium-members/+config.js
 
import favicon from './favicon.svg'
 
export {
  // Favicon for /premium-members
  dynamicFavicon: favicon
}

Internationalization

Example of internationalizing (i18n) <head> tags:

// pages/movies/+Head.js
// Environment: server
 
export { Head }
 
import { usePageContext } from 'vike-react/usePageContext' // or vike-{vue,solid}
 
function Head() {
  const pageContext = usePageContext()
  const description = pageContext.locale === 'de-DE' ?
    'List von Star Wars Filme.' :
    'List of Star Wars Movies.'
  return <>
    <meta name="description" content={description}>
  </>
}
// pages/movies/+title.js
// Environment: server, client
 
export function title(pageContext) {
  const title = pageContext.locale === 'de-DE' ?
    'Star Wars Filme' :
    'Star Wars Movies'
  return title
}

See also:

Markdown

See Integration > Markdown > Metadata.

See also