Getting started

Install Ascribe, write a first page, check it, build it, and publish it with Astro.

Ascribe is documentation written as code: Markdown with a small set of directives for the structure documentation needs (notes, procedures, alternatives by platform or product, availability, includes), checked like code, and built into a website, plain Markdown, and JSON. This guide sets up a project, writes a first page, and publishes it with Astro.

You need Node.js 24 or later. Ascribe runs on macOS on Apple silicon, Linux (x64 and arm64, with glibc 2.28 or later, which includes the build images of Netlify, Vercel, Cloudflare Pages, and AWS Amplify), and Windows (x64).

Install the command

In your project’s directory:

npm install --save-dev @ascribed/cli
npx ascribe --version
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. If ascribe can’t find the binary, your package manager left out optional dependencies; reinstall with them enabled.

To try what’s on main before it’s released, install @ascribed/cli@next and @ascribed/astro@next instead: a build published every night, with no promise of stability.

Install the editor

Install the Ascribe extension for VS Code from the Marketplace:

code --install-extension Ascribe.ascribe-vscode

It checks your pages as you type, completes directives, phrases, and links, and previews pages as the site shows them. It uses the project’s ascribe when there is one. See Editing.

Create ascribe.toml

ascribe.toml is the content model: the project’s schema. It marks the project root, and the smallest one is a single line:

spec = "0.1"

With nothing else declared, pages live in docs/, output goes to .ascribe/build/, every page needs a title, and there’s one build, site. A more useful start declares a dimension your content varies by, and a few phrases:

spec = "0.1"

[dimensions.pm]
label = "Package manager"
values = ["npm", "pnpm", "yarn"]

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

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

The ascribe.toml reference covers every section: content types and their frontmatter, availability, features, the glossary, project widgets, and builds.

Add the output directory to .gitignore:

.ascribe/

Write a page

Create docs/install.md:

---
title: Install Quill
---

@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).
  • @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.
  • {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 describes every directive and inline construct.

Check it

npx ascribe check

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

[ASC036] Error: `configure.md` doesn't exist

Every diagnostic has a code, and the diagnostics reference 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 a title, and check again.

Build it

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 the command reference.

Format it

npx ascribe fmt

rewrites directives and attribute blocks into their canonical spelling, and changes nothing else. ascribe fmt --check reports what would change, for CI.

Publish it with Astro

In an Astro project (npm create astro@latest makes one), with ascribe.toml beside astro.config.mjs:

  1. Install the integration:

    npm install @ascribed/astro
  2. Add it to astro.config.mjs:

    // astro.config.mjs
    import { defineConfig } from "astro/config";
    import ascribe from "@ascribed/astro";
    
    export default defineConfig({
      site: "https://docs.example.com",
      integrations: [ascribe({ build: "site" })],
    });
  3. Define the content collection, a route, and a layout that loads the elements. Astro walks through each file.

Check it in CI

Run the same command the editor runs:

# .github/workflows/docs.yml
name: Docs
on: [pull_request]
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 24
      - run: npm ci
      - run: npx ascribe check --deny-warnings
      - run: npx ascribe fmt --check

Next