Skip to content
Twilight React Playground
ثيم رائدaren

resolveHead, setHeadAdapter

functionAdvancedserverbrowser

Converts a HeadDescriptor into the active framework's head format through a global adapter, which createRouter() installs for TanStack.

import { resolveHead, setHeadAdapter, HeadResult } from '@salla.sa/twilight-theme-engine/utils/head';

In plain words

A HeadDescriptor belongs to no framework, so something must translate it into what TanStack Router expects. That translator is the adapter. resolveHead(descriptor) runs the installed adapter; setHeadAdapter(fn) installs one.

Mostly platform plumbing: the engine's createRouter() installs the TanStack adapter, so a theme never calls setHeadAdapter.

Signature

type HeadResult = Record<string, unknown>;

function resolveHead(descriptor: HeadDescriptor): HeadResult
function setHeadAdapter(adapter: (descriptor: HeadDescriptor) => HeadResult): void
// the adapter type, HeadAdapter, is not exported

Example

app/routes/stores.tsx
import { createFileRoute } from '@tanstack/react-router';
import { resolveHead } from '@salla.sa/twilight-theme-engine/utils/head';
import { StoreLocator } from '../components/StoreLocator';

export const Route = createFileRoute('/{-$locale}/stores')({
  // createRouter() installed the TanStack adapter: this returns { meta, links, styles, scripts }.
  head: () => resolveHead({ title: 'Our branches', robots: 'index, follow' }),
  component: StoreLocator,
});

How it behaves

  • The default adapter returns the descriptor unchanged. createRouter() from @salla.sa/twilight-theme-engine/tanstack calls setHeadAdapter(head) every time it creates a router, and twilightReact() installs the TanStack (or Next.js) adapter in the Vite config process.

  • Under TanStack, resolveHead(d) returns the same as head(d) from @salla.sa/twilight-theme-engine/tanstack. The live demo on HeadDescriptor calls it.

  • The root route's head goes through resolveHead; withHead calls the TanStack adapter directly.

  • The adapter is one module-level variable, shared by every request the server handles.

Gotchas

  • setHeadAdapter is last call wins, and createRouter() calls it for every router it creates, per request on the server. An adapter a theme installs before that is replaced; one installed after it changes the root head of every page, and breaks <HeadContent /> if it returns another shape.

  • Without createRouter() (a unit test, a script) resolveHead returns its input unchanged, so a test expecting meta finds a descriptor. Call head() from @salla.sa/twilight-theme-engine/tanstack directly there.

  • docs/07-data-types.md imports HeadResult from @salla.sa/twilight-theme-engine, which does not export it.

Related

Source and docs