Head Management
τjs provides flexible document head management through a headContent function defined in your entry-server.tsx.
The headContent Function
Section titled “The headContent Function”import { createRenderer } from "@taujs/react";import { App } from "./App";
export const { renderSSR, renderStream } = createRenderer({ appComponent: ({ location }) => <App location={location} />, headContent: ({ data, meta }) => { const title = data.title || meta.title || "My App"; const description = data.description || meta.description || "";
return ` <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>${title}</title> <meta name="description" content="${description}"> `; },});Data Sources
Section titled “Data Sources”Result from your route’s attr.data handler:
// Route config{ path: '/products/:id', attr: { render: 'ssr', data: async (params) => { const product = await db.products.findById(params.id); return { title: product.name, description: product.description, image: product.imageUrl }; } }}From your route’s attr.meta configuration:
// Route config{ path: '/about', attr: { render: 'ssr', meta: { title: 'About Us', description: 'Learn about our company' } }}Data Availability by Mode
Section titled “Data Availability by Mode”SSR Mode
Section titled “SSR Mode”Data is always fully resolved before headContent runs:
headContent: ({ data }) => { // data.product is guaranteed to exist return ` <title>${data.product.name}</title> <meta property="og:image" content="${data.product.imageUrl}"> `;};Streaming Mode
Section titled “Streaming Mode”Data may not be ready when headContent runs. Use meta for reliable SEO:
headContent: ({ data, meta }) => { // Use meta for guaranteed values return ` <title>${meta.title}</title> <meta name="description" content="${meta.description}"> ${ data.ogImage ? `<meta property="og:image" content="${data.ogImage}">` : "" } `;};Common Patterns
Section titled “Common Patterns”Open Graph Tags
Section titled “Open Graph Tags”headContent: ({ data, meta }) => { const title = data.title || meta.title; const description = data.description || meta.description; const image = data.ogImage || meta.ogImage;
return ` <title>${title}</title> <meta property="og:title" content="${title}"> <meta property="og:description" content="${description}"> ${image ? `<meta property="og:image" content="${image}">` : ""} `;};Structured Data (JSON-LD)
Section titled “Structured Data (JSON-LD)”headContent: ({ data, meta }) => { const jsonLd = data.jsonLd || meta.jsonLd;
return ` <title>${meta.title}</title> ${ jsonLd ? `<script type="application/ld+json">${JSON.stringify( jsonLd )}</script>` : "" } `;};Canonical URLs
Section titled “Canonical URLs”headContent: ({ data, meta }) => { const canonical = data.canonical || meta.canonical;
return ` <title>${meta.title}</title> ${canonical ? `<link rel="canonical" href="${canonical}">` : ""} `;};Best Practices
Section titled “Best Practices”1. Prioritise Meta Over Data in Streaming
Section titled “1. Prioritise Meta Over Data in Streaming”// ✅ Good - reliable in streamingheadContent: ({ data, meta }) => { return ` <title>${meta.title}</title> ${ data.ogImage ? `<meta property="og:image" content="${data.ogImage}">` : "" } `;};2. Provide Fallbacks
Section titled “2. Provide Fallbacks”const title = data.title || meta.title || "Default Title";3. Escape User Content
Section titled “3. Escape User Content”function escapeHtml(str: string): string { return str .replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, """);}4. Use SSR for Data-Dependent Head
Section titled “4. Use SSR for Data-Dependent Head”If your head content critically depends on fetched data, use render: 'ssr'.