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

# `ascribe.toml`: what pages draw from

> Reference · How the content model names what pages draw from outside the content: the source folders and repositories snippets read, and the OpenAPI specs links point into.

Part of the [`ascribe.toml` reference](https://ascribed-dev.com/docs/content-model.md), whose [contents](https://ascribed-dev.com/docs/content-model.md#contents) list every section. The rules for a loader are in the contract's [what pages draw from](https://ascribed-dev.com/docs/contracts/content-model/sources.md).

## 20\. `[sources.<name>]`

A source is a folder outside the project's content, or another repository, that its pages may take code examples from, with [`@snippet`](https://ascribed-dev.com/docs/writing/directives.md#snippet) ([SPEC §7.3](https://github.com/ascribed-dev/ascribe/blob/main/SPEC.md#73-sources)). It's the only way a page can read a file outside the project's folder.

```toml
[sources.code]
path = ".."                               # relative to the folder ascribe.toml is in
include = ["crates/**", "examples/**"]    # what's readable; everything else isn't
ignore = ["**/target/**"]

[sources.api]
git = "https://github.com/acme/api.git"   # another repository
branch = "main"                           # what `ascribe sources update` follows
include = ["src/**", "examples/**"]
```

A page names a file through its source as `<source>:<path>`, with the path relative to the source's folder: `@snippet: code:examples/quill/ascribe.toml#dimensions`. Both kinds of source are addressed the same way, so moving code to another repository, or back, changes `ascribe.toml` and no page.

| Key | Type | Default | Description |
| --- | --- | --- | --- |
| `path` | string (path) | **required** without `git` | The source's folder, relative to the project root. It must exist, be a directory, and be inside the git repository the project is in, when the project is in one. |
| `git` | string (URL) | **required** without `path` | Another repository, as `git` takes it: `https://`, `http://`, `ssh://`, `git://`, `file://`, or `user@host:path`. |
| `branch` | string | the repository's default branch | The branch `ascribe sources update` moves the pin to. |
| `include` | array of patterns | every file | The files a snippet may read, matched against their paths relative to the source's folder (§1.3). |
| `ignore` | array of patterns | `node_modules` and `.git` folders, always | Files left out even when `include` matches them. Every `node_modules` and `.git` folder is left out whatever the list says, before the patterns it adds. |

`<name>` follows the rules for keys (§1.2). A project can declare several sources, of either kind.

**Rules.** `path` is relative (`model-path-absolute`); its folder must exist and be a directory (`model-source-path-missing`) inside the project's repository (`model-source-outside-repository`). With no repository, as in a copy made with `git archive`, `ascribe build` and the other commands read a source wherever `path` leads, but the editor reads one only inside a folder of the workspace it opened, and `ascribe mcp` only inside the folder it was started in: open the folder that contains the source. A source has `path` or `git`, never both, and `branch` only with `git` (`model-source-remote`).

### A source in another repository

`check` and `build` never fetch anything. A source with `git` is read from copies kept in the project:

- `ascribe.lock`, beside `ascribe.toml`, pins each such source to a commit, and records the hash of each file copied from it, and which files snippets name that aren't in the repository at that commit.
- The files the project's snippets use are copied, whole, into `sources/<name>/` beside `ascribe.toml`, at the paths they have in their repository. Only those files are copied, not the repository, and not everything `include` matches. `sources/` can't be inside the content root.

Both are written by [`ascribe sources fetch` and `ascribe sources update`](https://ascribed-dev.com/docs/examples/sources.md#ascribe-sources), and committed with the rest of the docs. `check` reports a copy that was changed by hand, a copy the lock doesn't list, a copy no snippet uses any more, and a snippet whose file hasn't been copied yet, or isn't in the repository at the pinned commit because it was moved or deleted there. The copies are published to everyone who can read the docs repository: for a private code repository and public docs, that's a decision to make knowingly.

---

## 21\. `[apis.<name>]`

OpenAPI specs that pages link into, by name: each one's file, and where its reference is published. A link to a declared spec with a [fragment](https://ascribed-dev.com/docs/glossary.md#fragment), `[Get a user](../api/openapi.yaml#getUser)`, is a link to the operation whose `operationId` is the fragment, percent-decoded (SPEC §7.11); it's checked against the spec, and written as the operation's address in the reference.

```toml
[apis.public]
spec = "api/openapi.yaml"
reference = { renderer = "redoc", at = "/api/" }

[apis.partner]
spec = "../services/partner/openapi.json"
reference = "/partner-api/#/operations/{operationId}"
```

| Key | Type | Default | Description |
| --- | --- | --- | --- |
| `spec` | string (path) | **required** | The spec's file, YAML or JSON, relative to the project root. It may be outside the project's folder, inside the git repository the project is in, when it's in one. |
| `reference` | table or string | **required** | Where the published reference is: `{ renderer = "redoc", at = "/api/" }` for Redoc's page, or an address pattern, an operation's address with `{operationId}` and `{tag}`, for another renderer. |

`spec` is read as YAML, or as JSON when its name ends in `.json`, the same way for Swagger 2.0 and OpenAPI 3.0 to 3.2: each operation of `paths`, with its method, path, `operationId`, `summary`, first tag, and `deprecated`. Nothing else is read, and nothing is validated. A path item that's a `$ref` to another file isn't followed. A spec outside the project's folder is read for its operations, and a link to it with no fragment is still a link outside the project (`link-spec-outside-project`).

`reference` is a table for Redoc:

| Key | Type | Default | Description |
| --- | --- | --- | --- |
| `renderer` | string | **required** | The renderer that publishes the reference: `"redoc"`. |
| `at` | string | **required** | The address of Redoc's page, relative to `[consumer] base-path`, or absolute when the reference is published elsewhere. |

Redoc's address of an operation is `<at>#operation/<operationId>`, which Redoc 2 and 3 both open. Any other renderer's is an address pattern: a string with `{operationId}`, and `{tag}` for the operation's first tag when the renderer's address has it, each filled in percent-encoded. Swagger UI's is `"/api/#/{tag}/{operationId}"`, and Stoplight Elements' with its hash router `"/api/#/operations/{operationId}"`. Either address is joined to `[consumer] base-path`, unless it's absolute (`https://…` or `//…`), for a reference published on another site. It's the site's base path in every line of a versioned build: an API's reference isn't a line's.

How to publish a reference and link to it is in [Link to your API reference](https://ascribed-dev.com/docs/openapi.md).

**Rules.** `spec` is a path from the project root, relative (`model-path-absolute`), inside the git repository the project is in, when it's in one (`model-api-outside-repository`). A file that isn't there, that can't be read, or that isn't YAML or JSON is an error at `spec` (`api-spec-unreadable`), and one with no operations is advice (`api-spec-empty`). `reference` is a table with `renderer` and `at`, or an address pattern with `{operationId}` and no placeholder but `{operationId}` and `{tag}` (`model-api-reference`). A link to an operation the spec doesn't have is an error at the link, with the closest ids as its fixes (`link-operation-missing`). An operation no link names, unless the spec marks it `deprecated`, is advice at `spec` (`api-operation-unreferenced`): see [Find the operations no guide links to](https://ascribed-dev.com/docs/openapi/coverage.md). No other key is allowed (`model-unknown-key`).
