Normally when we are building UIs for our apps, we are dealing with DOM elements that are going to be rendered in the body of the document. But there are cases where we want to customize what's going to be rendered in the head of the document.
The common elements used in the head are:
title: Specifies the title of the page, used by the browser tab and headings of search results.
meta: Specifies a variety of metadata about the page specified by name, ranging from favicon, character set to OG tags for SEO.
link: Adds assets like stylesheets or scripts for the browser to load for the page.
In SolidStart, we ship with actual components representing these tags. So: title -> Title, meta -> Meta, etc. They can be used, not only as children of Head in root.tsx, but anywhere in your app, even deep in your component tree.
Powered by @solidjs/meta, we can interpret these tags and update the document.head appropriately. There are two main places we recommend adding these tags to your page.
root.tsx
As part of the Head component there, you can pass in the Title, Meta and Link tags that you want to be used for all of your routes. This is useful for:
Adding a default fallback title to be used by all pages (if they don't specify their own).
Adding common meta tags like charset and viewport for consistent behavior across the app.
Adding links to external stylesheets, fonts, manifests, favicon.
root.tsx
tsx
import { Suspense
tracks all resources inside a component and renders a fallback until they are all resolved
```typescript
const AsyncComponent = lazy(() => import('./component'));
<Suspense fallback={<LoadingIndicator />}>
<AsyncComponent />
</Suspense>
```
(alias) function Suspense(props: {
fallback?: JSX.Element;
children: JSX.Element;
}): JSX.Element
import Suspense
} from"solid-js";
import {
Html
(alias) function Html(props: ComponentProps<"html">): JSX.Element
import Html
, Head
(alias) function Head(props: ComponentProps<"head">): JSX.Element
import Head
, Title
(alias) const Title: Component<JSX.HTMLAttributes<HTMLTitleElement>>
import Title
, Meta
(alias) const Meta: Component<JSX.MetaHTMLAttributes<HTMLMetaElement>>
import Meta
, Link
(alias) const Link: Component<JSX.LinkHTMLAttributes<HTMLLinkElement>>
import Link
, Body
(alias) function Body(props: ComponentProps<"body">): JSX.Element
import Body
tracks all resources inside a component and renders a fallback until they are all resolved
```typescript
const AsyncComponent = lazy(() => import('./component'));
<Suspense fallback={<LoadingIndicator />}>
<AsyncComponent />
</Suspense>
```
(alias) function Suspense(props: {
fallback?: JSX.Element;
children: JSX.Element;
}): JSX.Element
import Suspense
tracks all resources inside a component and renders a fallback until they are all resolved
```typescript
const AsyncComponent = lazy(() => import('./component'));
<Suspense fallback={<LoadingIndicator />}>
<AsyncComponent />
</Suspense>
```
(alias) function Suspense(props: {
fallback?: JSX.Element;
children: JSX.Element;
}): JSX.Element
import Suspense
(alias) function Scripts(): JSX.Element
import Scripts
/>
</Body
(alias) function Body(props: ComponentProps<"body">): JSX.Element
import Body
>
</Html
(alias) function Html(props: ComponentProps<"html">): JSX.Element
import Html
>
);
}
root.tsx
tsx
import { Suspense
tracks all resources inside a component and renders a fallback until they are all resolved
```typescript
const AsyncComponent = lazy(() => import('./component'));
<Suspense fallback={<LoadingIndicator />}>
<AsyncComponent />
</Suspense>
```
(alias) function Suspense(props: {
fallback?: JSX.Element;
children: JSX.Element;
}): JSX.Element
import Suspense
} from"solid-js";
import {
Html
(alias) function Html(props: ComponentProps<"html">): JSX.Element
import Html
, Head
(alias) function Head(props: ComponentProps<"head">): JSX.Element
import Head
, Title
(alias) const Title: Component<JSX.HTMLAttributes<HTMLTitleElement>>
import Title
, Meta
(alias) const Meta: Component<JSX.MetaHTMLAttributes<HTMLMetaElement>>
import Meta
, Link
(alias) const Link: Component<JSX.LinkHTMLAttributes<HTMLLinkElement>>
import Link
, Body
(alias) function Body(props: ComponentProps<"body">): JSX.Element
import Body
tracks all resources inside a component and renders a fallback until they are all resolved
```typescript
const AsyncComponent = lazy(() => import('./component'));
<Suspense fallback={<LoadingIndicator />}>
<AsyncComponent />
</Suspense>
```
(alias) function Suspense(props: {
fallback?: JSX.Element;
children: JSX.Element;
}): JSX.Element
import Suspense
tracks all resources inside a component and renders a fallback until they are all resolved
```typescript
const AsyncComponent = lazy(() => import('./component'));
<Suspense fallback={<LoadingIndicator />}>
<AsyncComponent />
</Suspense>
```
(alias) function Suspense(props: {
fallback?: JSX.Element;
children: JSX.Element;
}): JSX.Element
import Suspense
(alias) function Scripts(): JSX.Element
import Scripts
/>
</Body
(alias) function Body(props: ComponentProps<"body">): JSX.Element
import Body
>
</Html
(alias) function Html(props: ComponentProps<"html">): JSX.Element
import Html
>
);
}
Inside a Route component
These tags will be applied for that specific route only and are removed from document.head once a user navigates away from the page. You can use routeData here to create titles and SEO metadata that is specific to the dynamic parts of the route.
tsx
import { Title } from"solid-start";
exportdefaultfunctionAbout() {
return (
<>
<Title>About</Title>
<h1>About</h1>
</>
);
}
tsx
import { Title } from"solid-start";
exportdefaultfunctionAbout() {
return (
<>
<Title>About</Title>
<h1>About</h1>
</>
);
}
Adding a site-suffix in Title
You can create custom components that wrap Title to add a site-specific prefix to all the titles, e.g.
You can use routeData to create titles that are specific to the dynamic parts of the route. For example, if you have a route that looks like /users/:id, you can use routeData to get the id and fetch the user's name from the server. Then you can use that name in the Title component.
tsx
import { Title
(alias) const Title: Component<JSX.HTMLAttributes<HTMLTitleElement>>
import Title
Conditionally render its children or an optional fallback component
(alias) function Show<T>(props: {
when: T | undefined | null | false;
keyed: true;
fallback?: JSX.Element;
children: JSX.Element | ((item: NonNullable<T>) => JSX.Element);
}): () => JSX.Element (+1 overload)
import Show
>
);
}
Similarly, you can use other information to build up other OG tags for SEO.
Adding SEO tags
For SEO tags like og:title, og:description, og:image, twitter:title, twitter:description, twitter:image, you can use the Meta component. For tags that you want to apply to all the routes, you should add them inside Head in your root.tsx file:
content="Solid Docs, rehauled. Very much in progress. Contribute to solidjs/solid-docs-next development by creating an account on GitHub."
/>
<Metaproperty="og:image:width"content="1200" />
<Metaproperty="og:image:height"content="600" />
<Metaproperty="og:site_name"content="GitHub" />
</Head>
</Html>
);
}
You can add tags with route specific information inside your route files. Just like with the Title, Meta tags used inside a Route component will override the Meta tags used in the Head component.