Installing Unhead with Solid.js
Install @unhead/solid-js, wrap the application with UnheadContext.Provider, and call useHead() in components.
The adapter uses Solid context for the head instance and exposes hooks for head tags, SEO metadata, and scripts. The examples follow Vite's SSR structure; SPAs use the same client entry.
Install Unhead
1. Add Dependency
Install the @unhead/solid-js dependency in your project.
pnpm add @unhead/solid-js2. Set Up Client-Side Rendering
Create the browser instance from @unhead/solid-js/client. In a Vite SSR app this usually belongs in entry-client.ts; in an SPA, put it in the main entry.
import { createHead, UnheadContext } from '@unhead/solid-js/client'
import { hydrate } from 'solid-js/web'
import App from './App'
/* @refresh reload */
import './index.css'
hydrate(() => {
const head = createHead()
return (<UnheadContext.Provider value={head}><App /></UnheadContext.Provider>)
}, document.getElementById('root'))
3. Set Up Server-Side Rendering
For SSR, create a fresh instance from @unhead/solid-js/server for each request and return it with the rendered app.
import { createHead, UnheadContext } from '@unhead/solid-js/server'
import { renderToString } from 'solid-js/web'
import App from './App'
export function render(_url: string) {
const unhead = createHead()
const html = renderToString(() => <UnheadContext.Provider value={unhead}><App /></UnheadContext.Provider>)
return { html, unhead }
}
After Solid renders, pass the instance and complete HTML template to transformHtmlTemplate():
import { transformHtmlTemplate } from '@unhead/solid-js/server'
// ...
// Serve HTML
app.use('*', async (req, res) => {
try {
// ...
const rendered = await render(url)
const html = transformHtmlTemplate(
rendered.unhead,
template
.replace(`<!--app-head-->`, generateHydrationScript())
.replace(`<!--app-html-->`, rendered.html ?? '')
)
res.status(200).set({ 'Content-Type': 'text/html' }).send(html)
}
catch (e) {
// ...
}
})
// ...
4. Add Head Tags
The server head inserts three defaults:
<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><html lang="en">
Set server-only defaults through init. Keeping them in the server entry also keeps them out of the client bundle.
import { createHead, UnheadContext } from '@unhead/solid-js/server'
import { renderToString } from 'solid-js/web'
import App from './App'
export function render(_url: string) {
const unhead = createHead({
// change default initial lang
init: [
{
htmlAttrs: { lang: 'en' },
title: 'Default title',
titleTemplate: '%s - My Site',
},
]
})
const html = renderToString(() => <UnheadContext.Provider value={unhead}><App /></UnheadContext.Provider>)
return { html, unhead }
}
Call useHead() inside a component to add tags:
import { useHead } from '@unhead/solid-js'
export default function App() {
useHead({
title: 'Example Site',
meta: [
{ name: 'description', content: 'An example page description.' }
]
})
return (
<div>
<h1>Hello World</h1>
</div>
)
}
Next Steps
Hooks:
useHead()useSeoMeta()useScript()for loading triggers and script lifecycle hooks
Optional integrations:
- Add
useSchemaOrg()for structured data