The Head component lets you render elements into the document <head> on web, and integrates with native platform features like Apple Handoff and Spotlight Search on iOS.
import { Head, useLoader } from 'one'
export async function loader({ params }) { const post = await getPost(params.slug) return { post }}
export default function BlogPost() { const { post } = useLoader()
return ( <> <Head> <title>{post.title}</title> <meta name="description" content={post.excerpt} /> <meta property="og:title" content={post.title} /> <meta property="og:description" content={post.excerpt} /> <meta property="og:image" content={post.image} /> </Head>
<article> <h1>{post.title}</h1> {/* ... */} </article> </> )}| Prop | Type | Description |
|---|---|---|
children | ReactNode | Standard HTML head elements like <title>, <meta>, <link>, etc. |
The Head component accepts standard HTML head elements:
<title> - Page title<meta> - Meta tags (description, Open Graph, Twitter Cards, etc.)<link> - Stylesheets, favicons, preload hints<script> - External scripts<style> - Inline styles<Head> {/* Page title */} <title>My Page Title</title>
{/* Meta tags */} <meta name="description" content="Page description" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
{/* Open Graph */} <meta property="og:title" content="My Page" /> <meta property="og:description" content="Page description" /> <meta property="og:image" content="https://example.com/image.png" /> <meta property="og:url" content="https://example.com/page" />
{/* Twitter Cards */} <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:title" content="My Page" />
{/* Favicon */} <link rel="icon" href="/favicon.ico" />
{/* Preload fonts */} <link rel="preload" href="/fonts/custom.woff2" as="font" type="font/woff2" crossOrigin="" /></Head>Use loader data or component state to set dynamic metadata:
import { Head, useLoader, useParams } from 'one'
export async function loader({ params }) { const product = await getProduct(params.id) return { product }}
export default function ProductPage() { const { product } = useLoader()
const ogImageUrl = `/api/og?title=${encodeURIComponent(product.name)}&price=${product.price}`
return ( <> <Head> <title>{product.name} | My Store</title> <meta name="description" content={product.description} /> <meta property="og:title" content={product.name} /> <meta property="og:image" content={ogImageUrl} /> <meta property="og:image:width" content="1200" /> <meta property="og:image:height" content="630" /> <meta property="product:price:amount" content={String(product.price)} /> <meta property="product:price:currency" content="USD" /> </Head>
{/* Page content */} </> )}On web, Head renders its children directly into the document’s <head> element. Multiple Head components can be used across your app - they will all contribute to the final head content.
On iOS, Head integrates with native platform features:
Enable these features using special meta properties:
<Head> <title>My Article</title> <meta property="og:title" content="My Article" /> <meta property="og:description" content="Article description" /> <meta property="og:url" content="https://example.com/article" />
{/* Enable Apple Handoff */} <meta property="expo:handoff" content="true" />
{/* Enable Spotlight Search indexing */} <meta property="expo:spotlight" content="true" /></Head>| Meta Property | Description |
|---|---|
expo:handoff | Set to "true" to enable Apple Handoff for this page |
expo:spotlight | Set to "true" to index this page in iOS Spotlight Search |
On Android, Head currently has no effect. Native metadata features may be added in future versions.
For consistent metadata across your app, create a wrapper component:
import { Head } from 'one'
type HeadInfoProps = { title: string description?: string image?: string url?: string}
export function HeadInfo({ title, description, image, url }: HeadInfoProps) { const fullTitle = `${title} | My App`
return ( <Head> <title>{fullTitle}</title> {description && <meta name="description" content={description} />}
{/* Open Graph */} <meta property="og:title" content={fullTitle} /> {description && <meta property="og:description" content={description} />} {image && <meta property="og:image" content={image} />} {url && <meta property="og:url" content={url} />}
{/* Twitter */} <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:title" content={fullTitle} /> {description && <meta name="twitter:description" content={description} />} {image && <meta name="twitter:image" content={image} />} </Head> )}Use it in your pages:
import { HeadInfo } from '~/features/HeadInfo'
export default function AboutPage() { return ( <> <HeadInfo title="About Us" description="Learn about our company" image="/images/about-og.png" />
{/* Page content */} </> )}Edit this page on GitHub.