> 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.

# Getting started

> Tutorial · Install Ascribe, write a first page, check it, build it, see it, and publish it with Astro.

Ascribe is a toolchain for documentation written as code: Markdown with the structure docs need, checked as you write, and built into a website, plain Markdown, and JSON. This guide sets up a project and writes, checks, builds, and previews a first page. Its second half, [Astro](https://ascribed-dev.com/docs/astro.md), publishes the page as a site.

It's for someone new to Ascribe who knows Markdown and a terminal. By the end, you'll have a project with a [content model](https://ascribed-dev.com/docs/glossary.md#content-model), a page that the editor checks as you write it, and a build of it ready for a site.

## Before you start

You need [Node.js](https://nodejs.org) 24 or later, on a [platform Ascribe runs on](https://ascribed-dev.com/docs/install.md#platforms).

## Install the command

In your project's directory:

A reader sees one of the next 2 sections at a time, chosen by package manager.

### Package manager: npm

```sh
npm install --save-dev @ascribed/cli
npx ascribe --version
```

### Package manager: pnpm

```sh
pnpm add --save-dev @ascribed/cli
pnpm exec ascribe --version
```

`@ascribed/cli` installs the `ascribe` binary for your platform, and pins its version for everyone who works on the project, and for CI. The latest release is 0.4.4. To install it another way, such as without Node, see [Install](https://ascribed-dev.com/docs/install.md).

## Install the editor

Install the **Ascribe** extension for VS Code from the Marketplace:

```sh
code --install-extension Ascribe.ascribe-vscode
```

It checks your pages as you type, completes directives, [phrases](https://ascribed-dev.com/docs/glossary.md#phrase), and links, and previews pages as the site shows them. It uses the project's `ascribe` when there is one. See [Editing](https://ascribed-dev.com/docs/editor.md).

Format your pages with Ascribe, not a general Markdown formatter: one such as Prettier can change what a page builds to as it saves it. When another extension formats Markdown in your project's folder, the extension offers to be its Markdown formatter instead; choose **Use Ascribe**. See [Formatting](https://ascribed-dev.com/docs/editor/writing.md#formatting).

After you install it, its walkthrough, **Get Started with Ascribe**, shows the preview, the actions bar that writes directives for you, and the Ascribe sidebar. It's under **Help → Welcome** whenever you want it again.

## Create `ascribe.toml`

`ascribe.toml` is the content model: the project's schema. It marks the project root, and says what each kind of page must have in its frontmatter.

Start the project with the command:

A reader sees one of the next 2 sections at a time, chosen by package manager.

### Package manager: npm

```sh
npx ascribe init
```

### Package manager: pnpm

```sh
pnpm exec ascribe init
```

It writes the project's first `ascribe.toml` and `ascribe.addresses`, and makes `docs/`, the folder the pages go in. `ascribe.toml` says what each part is for:

```toml
# The project's content model: where its pages are, and what each kind of
# page must say in its frontmatter. `ascribe check` and the editor read it.
# Every section is in the reference: https://ascribed-dev.com/go/content-model/
spec = "0.1"

[project]
# The folder the pages are in. A link that starts with `/` starts here.
content-root = "docs"

# What most projects add next:
#
# - A phrase, such as the product's name, written once here and on a page as
#   {product}: https://ascribed-dev.com/go/phrases/
# - A dimension, such as the reader's platform, for content that's for some
#   readers only: https://ascribed-dev.com/go/dimensions/
# - [consumer], the site the pages are published as, and its address:
#   https://ascribed-dev.com/go/consumer/

# The one kind of page, `page`, with a title and a description. Each page
# says what type it is in its frontmatter: `type: page`.
[types.page.frontmatter]
title = "string"
description = "string"
```

Tested with ascribe 0.4.4 on Linux.

Every page is of the one type, `page`, and says so with `type: page` in its frontmatter, with a `title` and a `description`. Output goes to `.ascribe/build/`, and there's one build, `site`. `ascribe init --templates` starts the project with six page types too, each with a template to start a page from; see [Page templates](https://ascribed-dev.com/docs/templates.md).

### Add what the page uses

The page below uses what most projects add next: a [dimension](https://ascribed-dev.com/docs/glossary.md#dimension) the content varies by, a few phrases, and the address the site is published at. Add them at the end of `ascribe.toml`:

```toml
[dimensions.pm]
label = "Package manager"
values = ["npm", "pnpm", "yarn"]
labels = { npm = "npm", pnpm = "pnpm", yarn = "Yarn" }

[phrases]
product = "Quill"
version = "3.4.1"

[consumer]
site = "https://docs.example.com"
```

Tested with ascribe 0.4.4 on Linux.

`values` are what a page writes, and `label` and `labels` are what readers see: the dimension's name, and each value's. The site's tabs read **npm**, **pnpm**, and **Yarn**; without `labels`, a tab shows the value as written, so the last would read **yarn**.

The [`ascribe.toml` reference](https://ascribed-dev.com/docs/content-model.md) covers every section: content types and their frontmatter, [availability](https://ascribed-dev.com/docs/glossary.md#availability), features, the glossary, project widgets, and builds.

Add the output directory to `.gitignore`:

```text
.ascribe/
```

Commit `ascribe.addresses`; Ascribe writes it. It records where a page went when it moves, so the addresses your docs publish keep working ([Keep the addresses you've published](https://ascribed-dev.com/docs/publishing/redirects.md)). [Files Ascribe writes](https://ascribed-dev.com/docs/command/project-files.md) lists the other files Ascribe puts in a project, and which to commit.

## Write a page

Create `docs/install.md`:

````markdown
---
type: page
title: Install Quill
description: Install Quill with your package manager, and set it up.
---

@note {type=tip}: {product} {version} needs Node.js 22 or later.

## Install the package

@variant {pm=npm}:
```sh
npm install quill
```
@variant {pm=pnpm}:
```sh
pnpm add quill
```
@variant {pm=yarn}:
```sh
yarn add quill
```
@end

## Set it up

@steps
1. Create `quill.yaml`.
2. Run `quill init`.

Next, [configure it](configure.md).
````

Tested with ascribe 0.4.4 on Linux.

- `@note` is a callout; `{type=tip}` is its attribute.
- `@variant` marks alternatives by package manager. The site shows them as tabs, and a build can keep just one. See [Content that varies](https://ascribed-dev.com/docs/writing/variants.md).
- `type: page` says what kind of page it is: a type `ascribe.toml` declares. `title` and `description` are the fields that type asks for.
- `{product}` and `{version}` are phrases from `ascribe.toml`.
- `@steps` marks the list as a procedure.
- The link points at a **file**, `configure.md`. Ascribe writes the URL.

The [directive reference](https://ascribed-dev.com/docs/writing/directives.md) describes every directive, and [phrases, links, and images](https://ascribed-dev.com/docs/writing/inline.md) the rest of what a page writes.

## Check it

```sh
npx ascribe check
```

The link to `configure.md` is reported, since that page doesn't exist yet:

```text
[ASC036] Error: `configure.md` doesn't exist
    ╭─[ docs/install.md:31:22 ]
    │
 31 │ Next, [configure it](configure.md).
    │                      ──────┬─────
    │                            ╰─────── link-target-missing
    │
    │ Help: Fix the path, or create the file. Names must match exactly, including case, and the file must be inside the project.
────╯
checked 1 file for every build, 1 with problems: 1 error, 0 warnings, 0 advice
```

Tested with ascribe 0.4.4 on Linux.

Every diagnostic has a code, and the [diagnostics reference](https://ascribed-dev.com/docs/checks/diagnostics.md) says how to fix each. `ascribe check` exits with 1 when there are errors, so it can gate CI; add `--deny-warnings` to fail on warnings too. Create `docs/configure.md` with the same frontmatter fields as `install.md`, `type: page` among them, and check again.

## Format it

`ascribe fmt` rewrites directives and attribute blocks into their canonical spelling, and changes nothing else:

```sh
npx ascribe fmt
```

`ascribe fmt --check` reports what would change, for CI.

## Build it

```sh
npx ascribe build
```

Each build writes three outputs to `.ascribe/build/<build>/`:

- `site/`: Markdown with web components, for Astro;
- `plain/`: plain Markdown with everything resolved, for search indexes and LLMs;
- `json/`: the resolved pages as JSON, for your own tools.

See [`ascribe build`](https://ascribed-dev.com/docs/checks/check.md#ascribe-build) for its options, and the [command reference](https://ascribed-dev.com/docs/command.md) for the rest.

## See it

```sh
npx ascribe preview
```

renders the build's pages as a site into `.ascribe/preview/`, with the sidebar, the page's contents, and search, and serves it on this computer. It prints the check's problems, then the address to open:

```text
previewing build `site` at http://127.0.0.1:4880/
```

Open it in a browser to see `install.md` as a reader does, its note, its alternatives by package manager, and its steps. As you edit a page or `ascribe.toml`, it renders the pages again; reload to see the change. It needs nothing but the command: no Node, no editor, and no Astro. Ctrl-C stops it. The published site has its own look, which the next step gives it. See [`ascribe preview`](https://ascribed-dev.com/docs/checks/check.md#ascribe-preview).

## Publish it with Astro

Publishing the site is this guide's second half, on its own page: [Astro](https://ascribed-dev.com/docs/astro.md) adds Ascribe to an [Astro](https://astro.build) project, writes the site's files with one command, and ends with the site open in your browser. For a new site:

1. Create an Astro project: `npm create astro@latest`.
2. Move `ascribe.toml` and `docs/` into it, beside `astro.config.mjs`.
3. Follow the guide from its first step.

For an existing site, keep this project where it is, follow the guide in the Astro project, and set the integration's `project` option to this project's directory.

Either way:

- `ascribe.toml`'s `[consumer]` `site` and Astro's `site` must be the same address. The `ascribe.toml` above sets it, and the Astro build fails when the two differ.
- You don't run `ascribe build` yourself: the integration runs it before Astro loads the pages, and again as you edit in `astro dev`.

## Summary

You installed the command and the editor, declared a content model in `ascribe.toml`, and wrote a page with a note, alternatives by package manager, phrases, and a procedure. Then you checked it, formatted it, built its site output, plain Markdown, and JSON, and saw it as a site with `ascribe preview`, ready for Astro to publish.

## Next steps

The [docs' home page](https://ascribed-dev.com/docs/index.md) has a path for each kind of reader, a few pages in order from here:

- [For engineers](https://ascribed-dev.com/docs/index.md#for-engineers): checks in CI, code examples from tested files, and review in CI.
- [For writers](https://ascribed-dev.com/docs/index.md#for-writers): the editor and its preview, content that varies, reuse, a glossary and templates, and review in the editor.
- [For agent builders](https://ascribed-dev.com/docs/index.md#for-agent-builders): `ascribe agents sync`, the MCP server and hooks, and what the outputs give agents that read the docs.
