# Custom Routes

> Add pages with their own chrome: any .html file is a route, and a layout in .htmlpress/layouts/ dresses it.

In htmlpress every `.html` file is already a route: a page is served at a folder named after its file, no registration, no config change. What a custom route adds is its own chrome: a layout of its own in `.htmlpress/layouts/`, picked by the page with `<meta name="layout">`.

## Minimal example

**HTML**

```html
<!-- about.html -->
<title>About</title>
<meta name="layout" content="landing">

<h1>About</h1>
<p>Anything you'd write in a normal HTML page, here.</p>

<!-- .htmlpress/layouts/landing.html -->
<body>
  <htmlpress-header role="banner">
    <htmlpress-brand></htmlpress-brand>
    <htmlpress-theme-toggle></htmlpress-theme-toggle>
  </htmlpress-header>
  <main><htmlpress-content></htmlpress-content></main>
</body>
```

**Markdown**

```md
<!-- about.md -->
---
title: About
layout: landing
---

# About

Anything you'd write in a normal Markdown page, here.

<!-- .htmlpress/layouts/landing.html -->
<body>
  <htmlpress-header role="banner">
    <htmlpress-brand></htmlpress-brand>
    <htmlpress-theme-toggle></htmlpress-theme-toggle>
  </htmlpress-header>
  <main><htmlpress-content></htmlpress-content></main>
</body>
```

Save and visit `/about/`. Without the meta, the page gets the site's layout, the same chrome as every other page: banner, header, sidebar, table of contents and pager. With it, the page's content carries no byline either: no author, date or "Updated" line under its title.

## Choosing the chrome

A layout is plain HTML like `layout.html`, and starts **bare**: nothing is drawn around the page until you add it. Compose as many layout elements as the page needs:

| You put in the layout             | You get                                                                                    |
| --------------------------------- | ------------------------------------------------------------------------------------------ |
| `<htmlpress-content>`             | the page's content                                                                         |
| `<htmlpress-brand>`               | the site title, after the `logo` when set, linking home                                    |
| `<htmlpress-banner>`              | the `banner` from `htmlpress.yaml`                                                         |
| `<htmlpress-links>`               | the header `links`                                                                         |
| `<htmlpress-nav>`                 | every page, grouped by top folder, then the sidebar `links`                                |
| `<htmlpress-breadcrumbs>`         | home, every folder above the page, then the page                                           |
| `<htmlpress-page-toc>`            | the page's `<h2>` and `<h3>`                                                               |
| `<htmlpress-pager>`               | the previous and next pages                                                                |
| `<htmlpress-edit>`                | the "Edit on GitHub" link from `edit`                                                      |
| `<htmlpress-toolbar>`             | the page's actions: its source link and its Markdown copy, to view, copy or open in a chat |
| `<htmlpress-footer>`              | a "Created with Htmlpress" credit                                                          |
| `<htmlpress-language>`            | the language picker, on a site with [translations](/customization/translations/)           |
| `<htmlpress-shortcuts>`           | the keyboard shortcuts menu, hidden on a phone                                             |
| `<htmlpress-skip>`                | a "Skip to content" link to `#content`, in the page's language                             |
| nothing but `<htmlpress-content>` | a blank page, all yours                                                                    |

The frame around them is elements too, never classes: `<htmlpress-shell>`, `<htmlpress-sidebar>`, `<htmlpress-main>`, `<htmlpress-header>`, `<htmlpress-page>` and `<htmlpress-aside>`; see [Layout](/authoring/rich-elements/#layout).

Htmlpress fills the layout's `<head>` the same way for every layout, so the theme, the site's metadata and the page's own head tags are always there. A landing page usually wants just the header, as in the example above. This site's [home page](https://github.com/datisthq/htmlpress/tree/main/.htmlpress) is built this way.

## How it fits with the rest of the site

- **Paths are URLs.** File paths mirror URL paths, each page at its own folder: `guide/quickstart.html` is `/guide/quickstart/`, and `index.html` is served at its folder, `guide/index.html` at `/guide/`, every name slugified. Relative links between pages keep working.
- **The root path `/`.** `index.html` at the root is the home page; give it its own layout to replace the docs chrome with a hero.
- **The navigation still lists it.** A page with its own layout is a page like any other: it appears in the sidebar, `llms.txt` and the sitemap.
- **Layout names.** A name is lowercase letters, digits and hyphens. A page naming a layout that is not there fails the build.
- **Not found.** A `404.html` at the root is the page a host shows for a missing URL; it is left out of the navigation, and a project without one gets a built-in "Page not found".

## Importing htmlpress primitives

A layout and a page both use the same components htmlpress uses itself: any `htmlpress-*` component, built in or your own from `.htmlpress/components/`, renders the same way in either, linking its styles and scripts only where used. Style a layout with its own components, as this site's home page does with its `htmlpress-landing-*` ones, or with the `--htmlpress-*` tokens.

```html
<!-- .htmlpress/layouts/landing.html -->
<body>
  <htmlpress-landing-hero></htmlpress-landing-hero>
  <main><htmlpress-content></htmlpress-content></main>
  <htmlpress-footer></htmlpress-footer>
</body>
```

## Static assets

Every file in the project that is not a page is copied to the output as-is, at the same path. Put a `robots.txt`, a custom `favicon.svg`, or an `og-image.png` beside your pages; a project file named like a generated one (`robots.txt`, `sitemap.xml`, `llms.txt`) wins over it.

## See also

- [Overriding/Escaping](/customization/overriding-escaping/): replace the site's layout or a component instead of adding a new one.
- [Site Metadata](/customization/site-metadata/): the site title and favicon that show on custom routes too.
