# 自定义路由

> 添加拥有独立外观框架的页面：任何 .html 文件都是一个路由，.htmlpress/layouts/ 中的布局为它提供外观。

在 htmlpress 中，每个 `.html` 文件本身就是一个路由：页面会以其文件名命名的文件夹提供服务，无需注册，也无需修改配置。自定义路由增加的是独立的外观框架：位于 `.htmlpress/layouts/` 中的专属布局，由页面通过 `<meta name="layout">` 选择。

## 最小示例

**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>
```

保存后访问 `/about/`。如果没有这个 meta，页面会使用站点的布局，即与其他所有页面相同的外观框架：公告栏、页眉、侧边栏、目录和翻页器。

## 选择外观框架

布局是像 `layout.html` 一样的普通 HTML，并且从**空白**开始：在你添加之前，页面周围不会绘制任何东西。按页面需要组合任意多个布局元素：

| 在布局中放入                    | 得到                                                  |
| ------------------------- | --------------------------------------------------- |
| `<htmlpress-content>`     | 页面的内容                                               |
| `<htmlpress-brand>`       | 站点标题（设置了 `logo` 时位于其后），链接到首页                        |
| `<htmlpress-banner>`      | `htmlpress.yaml` 中的 `banner`                        |
| `<htmlpress-links>`       | 页眉中的 `links`                                        |
| `<htmlpress-nav>`         | 所有页面，按顶层文件夹分组，然后是侧边栏中的 `links`                      |
| `<htmlpress-breadcrumbs>` | 首页、页面上层的每个文件夹，然后是页面本身                               |
| `<htmlpress-page-toc>`    | 页面的 `<h2>` 和 `<h3>`                                 |
| `<htmlpress-pager>`       | 上一页和下一页                                             |
| `<htmlpress-edit>`        | 来自 `edit` 的"编辑此页"链接                                 |
| `<htmlpress-toolbar>`     | 页面的 Markdown 副本，可查看、复制或在聊天中打开                       |
| `<htmlpress-footer>`      | "Created with Htmlpress" 署名                         |
| `<htmlpress-language>`    | 语言选择器，用于启用了[翻译](/zh/customization/translations/)的站点 |
| `<htmlpress-shortcuts>`   | 键盘快捷键菜单，在手机上隐藏                                      |
| `<htmlpress-skip>`        | 指向 `#content` 的"跳到内容"链接，使用页面的语言                     |
| 只有 `<htmlpress-content>`  | 一个完全由你掌控的空白页面                                       |

包裹它们的框架同样是元素，而不是类： `<htmlpress-shell>`、`<htmlpress-sidebar>`、 `<htmlpress-main>`、`<htmlpress-header>`、 `<htmlpress-page>` 和 `<htmlpress-aside>`；参见 [Layout](/zh/authoring/rich-elements/#layout)。

Htmlpress 对每个布局都以相同方式填充其 `<head>`，因此主题、站点元数据和页面自身的 head 标签总是存在。落地页通常只需要页眉，就像上面的示例那样。本站的 [首页](https://github.com/datisthq/htmlpress/tree/main/.htmlpress) 就是这样构建的。

## 与站点其余部分的配合

- **路径即 URL。** 文件路径与 URL 路径一一对应，每个页面都在自己的文件夹下： `guide/quickstart.html` 就是 `/guide/quickstart/`，而 `index.html` 在其所在文件夹处提供，`guide/index.html` 对应 `/guide/`，每个名称都会转换为 slug。页面之间的相对链接仍然有效。
- **根路径 `/`。** 根目录下的 `index.html` 是首页；为它设置专属布局，即可用一个主视觉区替换文档外观框架。
- **导航中仍会列出它。** 拥有专属布局的页面和其他页面一样：它会出现在侧边栏、`llms.txt` 和站点地图中。
- **布局名称。** 名称由小写字母、数字和连字符组成。页面指定了不存在的布局会导致构建失败。
- **未找到。** 根目录下的 `404.html` 是托管服务在 URL 缺失时显示的页面；它不会出现在导航中，没有该文件的项目会获得一个内置的 "Page not found" 页面。

## 引入 htmlpress 基础组件

布局和页面使用的都是 htmlpress 自身所用的组件：任何 `htmlpress-*` 组件，无论是内置的，还是来自 `.htmlpress/components/` 的自定义组件，在两者中的渲染方式都相同，且只在使用处链接其样式和脚本。可以用布局自己的组件为其设置样式，就像本站首页使用其 `htmlpress-landing-*` 组件那样，也可以使用 `--htmlpress-*` 设计令牌。

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

## 静态资源

项目中所有不是页面的文件都会按原样复制到输出目录的相同路径下。把 `robots.txt`、自定义的 `favicon.svg` 或 `og-image.png` 放在页面旁边即可；与生成文件同名的项目文件（`robots.txt`、`sitemap.xml`、`llms.txt`）会优先于生成的文件。

## 另请参阅

- [覆盖/弹出](/zh/customization/overriding-escaping/)：替换站点的布局或组件，而不是新增一个。
- [站点元数据](/zh/customization/site-metadata/)：同样显示在自定义路由上的站点标题和 favicon。
