Pages
Both pages are created by adding a new index.tsx
file in the src/routes
directory. Pages exports a default
Qwik component, which will be rendered as the content of the page.
import { component$ } from '@builder.io/qwik';
// Notice the default export
export default component$(() => {
return <h1>Hello World!</h1>;
});
The only difference between a page and an endpoint is that an endpoint only exports a
onRequest
,onGet
,onPost
,onPut
,onDelete
,onPatch
,onHead
function, which will be used to handle the incoming request.
head
export
Every page can export a head
property (or function) that returns a DocumentHead
object. The DocumentHead
object is used to resolve the title of the page, as well as the meta, links and styles.
This API allows you to set the title of the page, as well as the meta, open graph, twitter tags and links. This is useful for SEO and social sharing.
import { component$ } from '@builder.io/qwik';
import type { DocumentHead } from '@builder.io/qwik-city';
export default component$(() => {
return <h1>About page</h1>;
});
export const head: DocumentHead = {
// This will used to resolve the <title> of the page
title: 'About page',
meta: [
{
name: 'description',
content: 'This is the about page',
},
// Open graph
{
property: 'og:title',
content: 'About page',
},
{
property: 'og:description',
content: 'This is the about page',
},
],
link: [
{
rel: 'canonical',
href: 'https://example.com/about',
},
],
};
The example above sets the title, as well as some Open Graph meta and the canonical link.
HTML places the
<head>
tag as the first element within<html>
(at the very top of the HTML content). The<head>
section is not something that your route component renders directly because it would break the HTML streaming.
Look into useDocumentHead()
to read and consume the DocumentHead
object from within your component.
Dynamic head
You can also export a function that returns a DocumentHead
object, allowing to programmatically set the <title>
, <meta>
or <link>
tags.
This allows to configure the <head>
, including the title, meta or links using data from routeLoader$()
or routeAction$()
.
We can use the resolveValue
method to get the value of a routeLoader$()
or routeAction$()
within the head
function.
import { component$ } from '@builder.io/qwik';
import { routeLoader$ } from '@builder.io/qwik-city';
import type { DocumentHead } from '@builder.io/qwik-city';
export const useJoke = routeLoader$(async (requestEvent) => {
// Fetch a joke from a public API
const jokeId = requestEvent.params.jokeId;
const response = await fetch(`https://api.chucknorris.io/jokes/${jokeId}`);
const joke = await response.json();
return joke;
});
// Now we can export a function that returns a DocumentHead object
export const head: DocumentHead = ({resolveValue, params}) => {
const joke = resolveValue(useJoke);
return {
title: `Joke "${joke.title}"`,
meta: [
{
name: 'description',
content: joke.text,
},
{
name: 'id',
content: params.jokeId,
},
],
};
};
Nested layouts and head
An advanced case is that a layout may want to modify the document title of an already resolved document head. In the example below, the page component returns the title of Foo
. Next, the containing layout component can read the value of the page's document head and modify it. In this example, the layout component is adding MyCompany -
to the title, so that when rendered, the title will be MyCompany - Foo
. Every layout in the stack has the opportunity to return a new value.
──src/
└─routes/
├─index.tsx
└─layout.tsx
export const head: DocumentHead = {
title: `Foo`,
};
export const head: DocumentHead = ({ head }) => {
return {
title: `MyCompany - ${head.title}`,
};
};