> For the complete documentation index, see [llms.txt](https://ascribed-dev.com/docs/llms.txt). This documentation describes Ascribe 0.4.4. Anything marked in main, not yet released isn't in that release yet.

# Page templates

> How-to · Starting a page of a known kind, such as a how-to, from a template and a guide to what goes in it, written into your project by ascribe templates eject.

A page of a known kind has a shape: a how-to has what to do before you start, then numbered steps, then what to do next. A template is a page with that shape and things to fill in, and its guide says what belongs in each part. Ascribe carries a set of six, and writes them into your project with one command, where they're your files.

## Where the templates come from

The templates are [The Good Docs Project](https://www.thegooddocsproject.dev/template)'s, from their repository, [gitlab.com/tgdp/templates](https://gitlab.com/tgdp/templates), at their release v1.6.0. Their work is under the MIT No Attribution License, which asks for no credit; this is it anyway, with thanks.

Ascribe converts each one into an Ascribe page and changes nothing of their wording: each `{placeholder}` is written as `\{placeholder}`, so it shows as written and isn't read as a phrase. Each guide says at its top where it came from, and `ascribe templates list` shows the set and its release.

A template's instructions to the writer, such as `{This section is optional}`, are [memos](https://ascribed-dev.com/docs/writing/directives.md#memo): `@memo: This section is optional`. A [memo](https://ascribed-dev.com/docs/glossary.md#memo) is never published: follow it, then delete it or keep it. A paragraph that marks where the page's own text goes, such as the how-to's `{Optional: Explanatory text}` in a step, stays a placeholder.

The set has six templates, for a how-to, a concept, a tutorial, a reference, a troubleshooting page, and release notes. Each is one of theirs, and has a type of the same name.

## Take the templates

To start a project with the set, run `ascribe init --templates` in an empty folder: it writes the project's first `ascribe.toml` and takes the six templates as `eject` would ([command reference](https://ascribed-dev.com/docs/install.md#ascribe-init)).

In a project that has its `ascribe.toml` already, take the whole set:

```sh
ascribe templates eject
```

It writes each template, its guide, and Ascribe's notes on its type into `templates/`, beside `ascribe.toml`, with `templates/templates.lock`, which records what each was copied from, and adds the six types to `ascribe.toml`, below what's there. A type is declared like this:

```toml
[types.how-to]

[types.how-to.frontmatter]
title = "string"
description = "string"
```

The type names no template: a type with no `template` and no `guide` takes both from the lock, which records them under the type's name. A type that names either keeps what it names, which is how a project without the lock, or with a template written by hand, gives a type its template. In VS Code, the hover on the type's name in `ascribe.toml` says where its template comes from.

A page says what type it is in its frontmatter, `type: how-to`, as each template does, so a page of any type can go in any folder. Commit the files, the lock with them. The rules [`ascribe agents sync`](https://ascribed-dev.com/docs/agents/instructions.md) writes say what each type is for; to say it your own way, give the type a [`purpose`](https://ascribed-dev.com/docs/content-model.md#41-page-types).

To take only some, name them: `ascribe templates eject how-to concept`. A type the project declares already is refused, and nothing is written; to keep it and take its template, add `--keep-type`. The [command reference](https://ascribed-dev.com/docs/templates/command.md#ascribe-templates-eject) has the rest.

## Change a template

From then on the files are your project's, and nothing in Ascribe writes over them. Change a template as you'd change any page: take out a section your project never has, add one it always does, or write your own placeholder as `\{What goes here}`. Add to the guide or the notes, or add a file of your own to the type's `guide` list.

The check compares a page with the template as it is now, so a placeholder you take out isn't looked for any more, and one you add is.

## See what's changed in the set

A later `ascribe` carries The Good Docs Project's newer release. Nothing changes your copies: to see what's different, run:

```sh
ascribe templates status
```

For each template you took, it says whether the set has changed it since your copy, and whether you've changed it. To take a change, see it, then copy what you want by hand:

```sh
ascribe templates status --diff how-to
```

The [command reference](https://ascribed-dev.com/docs/templates/command.md#ascribe-templates-status) has its options, for a CI job too, and its JSON.

## In a project that has pages

A project with pages written already can take the set too; Ascribe's own docs did. Its pages name no type yet if the project declared none, and `ascribe check` offers a fix for each. Pages written before their template have none of its placeholders, so the check reports nothing on them, and a page that's none of the six, such as a home page that lists the others, gets a type of your own with no template. A guide says what a kind of page is for; a page that already does its job needn't match its template heading for heading.

## Ascribe's notes

Their guide says what belongs in a page of each kind, for any tool. Ascribe's notes, `<type>.ascribe.md`, are a minute's reading after it: only what's particular to writing that kind of page in Ascribe, such as a how-to's alternatives by platform as a [variant](https://ascribed-dev.com/docs/glossary.md#variant) group, and a step's command taken from tested code with [`@snippet`](https://ascribed-dev.com/docs/writing/directives.md#snippet).

## Start a page

In VS Code, run **Ascribe: New Page**. It asks for the type and the page's title, then makes the page from the type's template, with the first thing to fill in selected; **Ascribe: Go to Next Placeholder** selects the next ([editor guide](https://ascribed-dev.com/docs/editor/actions.md#start-a-page)).

From the command line, `ascribe new` does the same.

### `ascribe new`

Available: Ascribe (in main, not yet released, 0.4.5)

Starts a page of a type from the type's template, with its `type` and `title` set, as a draft, as **New Page** does, and writes it where `PATH` says. It never writes over a file.

```sh
ascribe new how-to docs/guides --title "Rotate keys"
```

- `TYPE`: The page's type, as `ascribe model --section types` names it.
- `PATH`: Where the page goes, from the current folder, in the content root: a page's path, ending in .md, or a folder, where the page is named for its title.
- `--title <TITLE>`: The page's title, set in its frontmatter. Without one, the page keeps the template's, to fill in with the rest, and PATH names the page itself.
- `--dry-run`: Say where the page would go, and print its text, writing nothing.
- `--force`: Taken as by every command that writes. `new` changes no file that's there, only adds one, so the git guard has nothing to refuse.
- `--format <FORMAT>`: How to show what was written.
  - `text` (the default): Where the page went, and what to do next, for people and agents.
  - `json`: One JSON document, for tools.

`PATH` is from the current folder, in the content root: a page's path, ending in `.md`, or a folder, where the page is named for its title as a route's segment is, `docs/guides/rotate-keys.md` above. The folders it names are made. Without `--title`, the page keeps the template's title, to fill in with the rest, and `PATH` must name the page itself. A type with no template starts with its frontmatter alone: its type, the title, and each field it requires, empty.

The page starts as a [draft](https://ascribed-dev.com/docs/writing/frontmatter.md#a-draft), with `draft: true` in its frontmatter, which no build publishes, so what it has left of its template is advice while you write it. Take the line out to publish it: from then on, a placeholder left in it is an error ([What's left to fill in](https://ascribed-dev.com/docs/templates.md#whats-left-to-fill-in)).

It says where the page went, the type's guide to read before writing, and how many placeholders are left, which [`ascribe check`](https://ascribed-dev.com/docs/checks/check.md#ascribe-check) lists:

```text
wrote docs/guides/rotate-keys.md, a page of type `how-to`, from templates/how-to.md
Read its guide before you write: templates/how-to.guide.md, templates/how-to.ascribe.md
It has 13 placeholders left to fill in, which `ascribe check docs/guides/rotate-keys.md` lists
It's a draft, with `draft: true`, which no build publishes: take the line out to publish it
```

With `--dry-run`, it says where the page would go and prints its text, and writes nothing. With `--format json`, it writes [one document](https://ascribed-dev.com/docs/contracts/json-reports/templates.md#ascribe-new) with the page's path, its text, and the count.

| Exit code | Meaning |
| --- | --- |
| `0` | The page was written, or with `--dry-run` would be |
| `2` | Nothing was written: a type the [content model](https://ascribed-dev.com/docs/glossary.md#content-model) doesn't have, a path outside the content root, a file where the page would go, no title to name a page in a folder, or a template that can't be read |

An agent starts from the template too. Ask it for a page with the plugin's `/ascribe:new-page`, or the prompt `ascribe agents prompt new-page` prints ([agents guide](https://ascribed-dev.com/docs/agents/prompts.md#from-the-command-line)), which gives it the template and sends it to the guide and the notes before it writes:

```sh
ascribe agents prompt new-page --arg type=how-to --arg title="Rotate keys"
```

## What's left to fill in

`ascribe check` compares a page with its type's template and reports what it still has of it: a placeholder or a frontmatter field the page has word for word, and a section the template gives only memos that the page leaves empty ([`template-section-empty`](https://ascribed-dev.com/docs/checks/diagnostics/content-checks.md#asc229-template-section-empty), advice).

A placeholder left is advice in a [draft](https://ascribed-dev.com/docs/writing/frontmatter.md#a-draft), a page with `draft: true` ([`template-placeholder-left`](https://ascribed-dev.com/docs/checks/diagnostics/content-checks.md#asc195-template-placeholder-left)), so a page you're still writing isn't covered in errors. In a page that publishes, it's an error ([`template-placeholder-published`](https://ascribed-dev.com/docs/checks/diagnostics/content-checks.md#asc286-template-placeholder-published)): readers would read the template's words, so `ascribe check` fails, `ascribe build` writes nothing, and the editor, the agents' hook, and the MCP tools report it the same way. A page started with `ascribe new` or **New Page** is a draft until you take the line out. A memo the page keeps isn't reported. In VS Code, the sidebar's [This page](https://ascribed-dev.com/docs/editor/sidebar.md#this-page) says how many are left, and **Go to Next Placeholder** goes to the next one.

The check finds only what was never touched, so read a page through before publishing it. To turn any of these checks off, or set another level, set its level in [`[checks]`](https://ascribed-dev.com/docs/content-model/checks.md#22-checks).

## See also

- [`ascribe templates`](https://ascribed-dev.com/docs/templates/command.md): `list`, `eject`, and `status`, their options, and their output.
- [Page types](https://ascribed-dev.com/docs/content-model.md#41-page-types): a type's `template`, `guide`, and `purpose`, and the template it takes from the lock.
