# Markdown Pages

> Write a page in Markdown: frontmatter for its metadata, directives for components.

A `.md` file is a page too. It is served where its `.html` twin would be, `guide.md` at `/guide/`, and goes through the same build as an HTML page: components, math, code blocks, includes, the table of contents and the Markdown copy for agents.

````md
---
title: Getting started
description: Install and run it in a minute.
order: 1
---

# Getting started

Install it, then build the docs:

```sh title="Terminal"
npx gethtmlpress build docs
```
````

The Markdown is GitHub's: tables, task lists, strikethrough, footnotes and bare links. Raw HTML works as in any page, so an `htmlpress-*` component can be written as a tag, with Markdown inside it after a blank line.

## Frontmatter

The YAML at the top of the file sets what an HTML page sets in its `<head>`, under the same names: `title`, `description`, `order`, `label`, `icon`, `layout`, `sidebar`, `breadcrumbs`, `toc`, `date`, `author`, `keywords`, `image`, `language`, `path`, `source-url` and `source-action`, as described in [Frontmatter](/authoring/frontmatter/). `author` and `keywords` take a list, and `head` is raw HTML added to the page's `<head>`:

```yaml
title: Release notes
author: [Ann, Bo]
keywords: [release, notes]
head: <link rel="alternate" type="application/rss+xml" href="/feed.xml">
```

Any other key fails the build, so a typo never passes for metadata.

## Components

A directive is a component: `:::name` wraps a block, `::name` stands on a line of its own and `:name[label]` sits inside text. Attributes go in braces. The directives are [Livemark](https://livemark.dev)'s, so a Livemark page reads the same here.

```md
:::warning[Back up first]
The build wipes its output folder.
:::

:::card{title="Install" href="/install/" icon="rocket"}
One command.
:::

The API is :badge[beta]{variant="warning"}.

### Write a page [step]
```

`:::note`, `tip`, `info`, `warning` and `danger` are callouts, a label their title, and so is a GitHub alert, `> [!NOTE]`. `:::card`, `:::column` and `:::tab` in a row group into cards, columns and tabs; `:::details`, `:::filetree`, `::button`, `::toc`, `::video{type="youtube"}`, `::audio{type="soundcloud"}`, `:badge`, `:icon` and `:abbr` are the rest. A heading takes `{#id}`, `[step]`, `[!toc]` (listed nowhere) and `[toc]` (listed only). Any other directive is the component of that name, the project's own too; a block one that names no component fails the build, and inside text something like `note:important` stays text.

## Code blocks

A fence's language highlights it, and what follows the language takes the [code block attributes](/authoring/code-blocks/) without their `data-`: `title`, `collapse`, `lines`, `line-numbers`, `add`, `remove`, `focus`, `error`, `warning` and `words`.

````md
```js title="build.js" lines="2" line-numbers
import { build } from "htmlpress"
await build("docs")
```
````

## Math, emoji and links

`$…$` and `$$…$$` are [math](/authoring/advanced-syntax/), and `:rocket:` shortcodes are emoji, as in an HTML page. Link to another page by its file, `[Setup](setup.md)`, and the link takes the page's URL.

## Which files are pages

Without an `include`, every `.html` and `.md` file in the project is a page, a `README.md` too. Exclude what is not a page in the [configuration file](/customization/configuration-file/). These files are never pages:

- an `.md` beside its `.html` page, which is that page's own Markdown copy for agents, published instead of the generated one;
- an `.md` that a page includes with `<htmlpress-include>`, a partial, whose directives and code blocks work as in a page;
- a changelog section's `source`, which its own pages show;
- the agent skills that `skills` names.
