Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/routes/solid-meta/(0)index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ description: >-
meta tags at any component level for flexible SEO and metadata control.
---

:::note[Using Solid 2.0?]
This documentation covers `@solidjs/meta` 0.29.x for Solid 1.x. For Solid 2.x, use `@solidjs/meta` 1.x and the [v1 documentation](/solid-meta/v1).
:::

Solid Meta offers asynchronous SSR-ready Document Head management for Solid Applications, based on [React Head](https://github.com/tizmagik/react-head)

With Solid Meta, you can define `document.head` tags at any level of your component hierarchy.
Expand Down
34 changes: 34 additions & 0 deletions src/routes/solid-meta/v1/(0)index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: Overview
titleTemplate: ":title"
mainNavExclude: true
use_cases: >-
managing head tags, seo optimization, document metadata, dynamic meta tags,
ssr meta management, streaming head updates
tags:
- meta
- head
- seo
- ssr
- overview
version: "1.0"
description: >-
Solid Meta 1.0 provides document head management for Solid 2.0 — declare
head tags anywhere with streaming-correct SSR and flicker-free hydration.
---

:::note[Solid Meta 1.0 is for Solid 2.0]
Solid Meta 1.x requires Solid 2.x (currently in beta). If you are using Solid 1.x, use `@solidjs/meta` 0.29.x and the [latest documentation](/solid-meta) instead.
:::

Solid Meta provides document head management for Solid applications — declare `<title>`, `<meta>`, `<link>`, and other head elements anywhere in your component tree, with streaming-correct server rendering and flicker-free hydration.

Solid Meta 1.x is a thin component layer over Solid 2.0's built-in head registry (`useHead` in `@solidjs/web`). There is **no provider** — the registry is ambient. Render a head component anywhere and it registers under the current reactive owner, and server rendering splices the winning tags into your document automatically.

| Solid version | @solidjs/meta version |
| ------------- | --------------------- |
| Solid 2.x | 1.x |
| Solid 1.x | 0.27.x – 0.29.x |
| Solid 0.x | 0.26.x |

If you are upgrading an existing app from `@solidjs/meta` 0.x, start with the [migration guide](/solid-meta/v1/migrating-from-v0).
84 changes: 84 additions & 0 deletions src/routes/solid-meta/v1/(1)getting-started.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
title: Getting started
use_cases: >-
installation, setup, first head tags, page titles, meta tags, ssr setup
tags:
- setup
- installation
- quickstart
- head
- meta
version: "1.0"
description: >-
Install Solid Meta 1.0 and manage document head tags from anywhere in your
Solid 2.0 application.
---

## Installation

```package-install
@solidjs/meta
```

Solid Meta 1.x requires `solid-js` and `@solidjs/web` 2.0 (`2.0.0-beta.31` or later).

## Usage

There is no provider and no other setup.
Render head components anywhere in your component tree:

```tsx
import { Title, Link, Meta } from "@solidjs/meta";

function Home() {
return (
<div class="Home">
<Title>Title of page</Title>
<Link rel="canonical" href="https://solidjs.com/" />
<Meta name="description" content="A description of this page" />
</div>
);
}
```

Head tags follow a few consistent rules:

- **Later wins.**
Tags deduplicate by identity (each [component's reference page](/solid-meta/v1/reference/meta/title) documents its identity rule); the last-registered tag for an identity is the one in the document.
- **Disposal restores.**
When the winning tag's component unmounts, the previous registration for that identity is restored — navigating away from a page undoes its head changes automatically.
- **Reactive.**
Attribute values and text children can be reactive expressions; updates apply in place without losing the tag's position in the override order.

Every component accepts a `key` prop that overrides the default identity — use it to make otherwise-distinct tags override each other, or to fork an identity that would otherwise collide:

```tsx
{/* These override each other despite different attributes: */}
<Meta key="social-image" name="twitter:image" content="/twitter.png" />
<Meta key="social-image" property="og:image" content="/og.png" />
```

To manage a _set_ of tags as one unit — several `og:image`s, a block of social tags that should override together — wrap them in [`<Head>`](/solid-meta/v1/reference/meta/head).

## Server rendering

Server rendering requires no wiring.
Render your document with Solid and the head manages itself:

```tsx
import { renderToStream } from "@solidjs/web";
import App from "./App";

// ... within the context of a request ...
renderToStream(() => <App />).pipe(res);
```

Winning tags are spliced into `<head>` on the first flush (`<base>` and `<meta charset>` go right after `<head>` opens; resource links go early).
Tags registered under a suspense boundary that completes later stream to the client as patches that apply when the boundary reveals.
If you assemble the document yourself, use the `onHead` render option to receive the head markup instead.

On the client, hydration adopts server-rendered head tags in place — there is no removal/re-insertion flicker.

:::note[Static shell tags]
A static `<title>` in your server shell acts as the fallback when no `<Title>` is mounted. Don't hardcode other tags that Solid Meta should manage — the registry leaves foreign head tags alone, so a hardcoded `<meta name="description">` would coexist with a rendered one.
:::
82 changes: 82 additions & 0 deletions src/routes/solid-meta/v1/(2)migrating-from-v0.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
title: Migrating from 0.x
use_cases: >-
existing project, migration, upgrade, metaprovider removal
tags:
- migration
- upgrade
- metaprovider
- breaking-changes
version: "1.0"
description: >-
Migrate your application from @solidjs/meta 0.x to 1.0.
---

Solid Meta 1.0 was rebuilt as a thin layer over Solid 2.0's built-in head registry.
Most components keep their names and props, but the provider, the server plumbing, and the deduplication semantics changed.

## Migration steps

### Delete `<MetaProvider>`

The head registry is ambient — the provider and `MetaContext` no longer exist.
Remove the wrapper:

```tsx del={1,5,7}
import { MetaProvider } from "@solidjs/meta";

export default function App() {
return (
<MetaProvider>
<Layout />
</MetaProvider>
);
}
```

### Delete server plumbing

The 0.x server flow — passing a `tags={[]}` array into `MetaProvider` and splicing `renderTags(tags)` into your template — is gone.
Rendering the document with `renderToString` / `renderToStream` splices the winning tags into `<head>` automatically, and tags registered under suspense boundaries stream to the client as patches.
If you assemble the HTML document yourself, use the `onHead` render option to receive the head markup instead.

### Review duplicate-tag semantics

0.x kept multiple `<Meta>` tags with the same `name` if their other attributes differed.
1.x dedupes by `name`/`property`/`http-equiv` (qualified by `media`) with last-wins.

For deliberate sets — multiple `og:image`s that should coexist — wrap them in [`<Head>`](/solid-meta/v1/reference/meta/head):

```tsx
<Head>
<Meta property="og:image" content="/image-1.png" />
<Meta property="og:image" content="/image-2.png" />
</Head>
```

To fork an identity that would otherwise collide, give each tag a distinct `key`.

### Update `useHead` calls

`useHead` is no longer exported from `@solidjs/meta` — the primitive belongs to Solid 2.0 itself.
Import it from `@solidjs/web`; it takes `HeadTag` descriptors (`{ tag, props, key? }`) — a single tag, an array (a group), or a function (a reactive group):

```tsx
import { useHead } from "@solidjs/web";

useHead({ tag: "meta", props: { name: "description", content: () => desc() } });
```

### Removed features

- **`escape` prop** — everything is escaped now; text is applied via `textContent`, so markup injection isn't possible.
- **`ref` and event handlers on head tags** — head tags are data, not managed elements. Query the DOM directly for the rare case that needs it.
- **Client-dynamic `<Base>` / `<Meta charset>`** — these are rendered into the server shell only, and are ignored (with a dev warning) on the client. A base or charset that changes after the document loaded is incoherent.
- **`noscript`** — excluded from the core tag union: author it statically in your document shell.

### New capabilities

- [`<Script>`](/solid-meta/v1/reference/meta/script) is new — JSON-LD and other head scripts no longer need the `useHead` escape hatch.
- [`<Head>`](/solid-meta/v1/reference/meta/head) groups child tags into one replacement set with reactive membership.
- Icons (`rel="icon"` / `rel="apple-touch-icon"`) are replaceable: swapping the `href` replaces the favicon rather than accumulating, and unmounting restores the previous one.
- `theme-color` variants with different `media` queries coexist.
56 changes: 56 additions & 0 deletions src/routes/solid-meta/v1/reference/meta/base.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
title: Base
order: 7
use_cases: >-
base url, relative url resolution, document base
tags:
- base
- head
- url
- component
version: "1.0"
description: >-
Base sets the document base URL through Solid Meta during server rendering.
---

`Base` adds a [`<base>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base) element that specifies the base URL for all relative URLs in the document.

## Import

```tsx
import { Base } from "@solidjs/meta";
```

## Type

```tsx
const Base: Component<JSX.BaseHTMLAttributes<HTMLBaseElement>>;
```

## Props

Accepts attributes for [`<base>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base) (`href`, `target`).

## Behavior

- **Server shell only.**
`<base>` has hard placement constraints — it must appear before any relative URL resolves — so it is rendered into the head prelude on the first server flush.
- Registrations arriving after the shell has flushed are ignored with a dev warning, and `Base` is ignored (with a dev warning) on the client: a base that changes after relative URLs resolved is incoherent by definition.
- `Base` does not accept a `key` and does not participate in cascade/restore semantics.

## Examples

### Basic usage

```tsx
import { Base } from "@solidjs/meta";

export default function App() {
return <Base href="https://example.com/app/" target="_blank" />;
}
```

## Related

- [`Link`](/solid-meta/v1/reference/meta/link)
- [`Meta`](/solid-meta/v1/reference/meta/meta)
96 changes: 96 additions & 0 deletions src/routes/solid-meta/v1/reference/meta/head.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
title: Head
order: 8
use_cases: >-
grouped meta tags, multiple og images, social tag blocks, atomic head
replacement
tags:
- head
- group
- og-tags
- component
version: "1.0"
description: >-
Head groups its child head tags into one replacement set through Solid Meta.
---

`Head` groups its child head tags into one replacement set.
Some head state is a _set_, not a single tag — multiple `og:image`s, or a block of social tags that should override together.

:::note[New in 1.0]
`Head` did not exist in `@solidjs/meta` 0.x.
:::

## Import

```tsx
import { Head } from "@solidjs/meta";
```

## Type

```tsx
const Head: ParentComponent;
```

## Props

### `children`

- **Type:** `JSX.Element`
- **Optional:** Yes

Head tag components (and any components that render them).

## Behavior

- **Within the group, same-identity tags coexist.**
Two `<Meta property="og:image">` tags inside one `<Head>` both render.
- **Groups replace wholesale.**
A later group replaces an earlier group's set for an identity as a unit, and unmounting restores the earlier set.
- **Membership is reactive.**
Tags rendered conditionally (or by child components) inside a `<Head>` join and leave the set as they mount and unmount.
Group scope propagates via context through component calls.
- **Nesting starts a new group.**
A `<Head>` inside another `<Head>`'s children forms its own independent group; to contribute tags _into_ the surrounding group, render bare tag components instead.

## Examples

### Overriding a default set

```tsx
// Layout
<Head>
<Meta property="og:image" content="/default-1.png" />
<Meta property="og:image" content="/default-2.png" />
</Head>

// Page — replaces BOTH defaults while mounted, restores them on leave
<Head>
<Meta property="og:image" content={product().image} />
</Head>
```

### Social tag block

```tsx
import { Head, Meta, Title } from "@solidjs/meta";

export default function Article(props: {
article: () => { title: string; image: string };
}) {
return (
<Head>
<Title>{props.article().title}</Title>
<Meta property="og:title" content={props.article().title} />
<Meta property="og:image" content={props.article().image} />
<Meta name="twitter:card" content="summary_large_image" />
</Head>
);
}
```

## Related

- [`Meta`](/solid-meta/v1/reference/meta/meta)
- [`Title`](/solid-meta/v1/reference/meta/title)
Loading
Loading