Manifest compile order
Each guide’s compile order comes from markdown links in its manifest file: index.md by default, or shards.md when configured under guides[].compile.manifest. Merlon Docs collects every link to a .md file in document order and stitches those shards in that sequence. A same-document #slug link also adds slug.md when that file exists in the guide directory. Those shards compile after the shards the manifest links by path. The rule skips #table-of-contents: the [Guide title](#table-of-contents) self-link that opens the manifests in this repository doesn’t add a shard.
Guide directories are human source only (index.md, shard files). Under outputDir, compile writes a per-guide {name}.md for each guide that has no compile.outputFile, the optional monolith and .caches/refs.json. A publish output goes where its compile.outputFile points, which can be outside outputDir. Path layout gives the rules.
Default behavior
Section titled “Default behavior”A minimal manifest is a table of contents — only section links, no stray .md links in preamble prose:
# Admin guide
- [Getting started](./chapter-1-getting-started.md)Compile order: chapter-1-getting-started.md first (and only). No extra config needed.
When manifests mix policy prose and section lists
Section titled “When manifests mix policy prose and section lists”Some guides use index.md as both policy prose (how authors should work) and section manifest (ordered shard list). A common pattern:
# Compound glossary
## Acronyms and new terms
When you introduce an acronym… spell out the term and link it — e.g.Content-Security-Policy ([CSP](04-security-sync.md#glossary-csp)).
## Sections
- [Product surfaces](01-product-surfaces.md)- [Tenancy](02-tenancy.md)- [Data model](03-data-model.md)- [Security and sync](04-security-sync.md)- [Review vocabulary](05-review-vocabulary.md)Without sectionsHeading
Section titled “Without sectionsHeading”Merlon Docs collects all .md links in file order:
| Order | Link | Author intent |
|---|---|---|
| 1 | 04-security-sync.md |
Example in policy prose — “link CSP like this” |
| 2 | 01-product-surfaces.md |
Section shard |
| 3 | 02-tenancy.md |
Section shard |
| … | … | … |
Compile stitches 04-security-sync.md first, then 01, 02, … — wrong order. The CSP link is documentation, not a directive to lead with that shard.
With sectionsHeading
Section titled “With sectionsHeading”Set guides[].compile.sectionsHeading to the ## heading that starts the real section list (without the # marks):
{ "name": "glossary", "path": "glossary", "compile": { "title": "Compound glossary", "sectionsHeading": "Sections", "outputFile": "glossary.md" }}Merlon Docs only considers links at or after ## Sections. Preamble example links are ignored for compile order. Order becomes 01 → 02 → 03 → 04 → 05.
04-security-sync.md still compiles because it appears under ## Sections, not because it is mentioned in the policy paragraph.
When you need sectionsHeading
Section titled “When you need sectionsHeading”| Situation | sectionsHeading |
|---|---|
Manifest is a TOC — every .md link is a section |
Omit |
shards.md lists cross-tree shards only (compiled review guides) |
Usually omit |
Preamble has inline .md links that are examples or cross-references, plus a separate ordered section list under a ## heading |
Set to that heading text |
sectionsHeading matches a ## line whose text equals it, ignoring case: "Sections" matches ## Sections and ## SECTIONS, not ## Section list. When no ## line matches, compile reads every link in the manifest, as it does without sectionsHeading.
Linked shards and the file-name fallback
Section titled “Linked shards and the file-name fallback”Compile also follows inline .md links inside the shards it stitches. A guide compiles its manifest’s shards plus every shard it finds by following links from shard to shard, a set the code calls linkedSectionFiles. Each link resolves from the directory that contains its shard, and the walk keeps a target that exists in the guide directory or under compile.scopeRoot. Those shards compile after the manifest’s shards, in the order the walk finds them. Guide link index says which shards in the set get an entry in the guide link index.
| Authoring form | Walk follows it |
|---|---|
Inline link [label](path.md) or [label](path.md#fragment) |
Yes |
Linked image [](path.md), or a label with balanced brackets such as [arr[0]](path.md) |
Yes |
Image  |
Yes |
Link after a backslash, \[label](path.md) |
No |
Reference-style link [label][ref] with [ref]: path.md |
No |
File path in backticks, such as `path.md` |
No |
The walk reads a label and a target as the link passes do. It reads each shard’s raw text, so it also follows an inline link written in a code span or a fenced code block. The walk skips a reference-style link and a path in backticks, so either one can refer to a shard that the guide doesn’t compile. No link pass rewrites either form, and the path stays as written in the compiled output.
That walk serves shards in guide subdirectories and under compile.scopeRoot. The manifest must link every top-level shard in the guide directory directly, because the orphan check reads only the manifest. A top-level shard that only another shard links still compiles, and merlon check reports it as an orphan.
When the manifest links no shards, compile takes the other top-level .md files in the guide directory in file-name order, leaving out any shards.md.
Orphan check scope
Section titled “Orphan check scope”The orphan check compares each guide directory in compileOrder with the shards its manifest links, read the way compile reads them, from compile.sectionsHeading on when that is set. It reports:
- a top-level
.mdfile in the guide directory that the manifest doesn’t link, other than the manifest andshards.md - a manifest link to a file that doesn’t exist
- a guide directory that doesn’t exist, or a manifest that is missing or can’t be read
The check doesn’t follow links from shard to shard, and it doesn’t read guide subdirectories or compile.scopeRoot. When the manifest links no shards, every top-level file compiles through the file-name fallback, and the check reports none of them for that guide. merlon check runs it first and stops on any issue, as Check gate stages says. Relationship to the orphan check says which unlinked shards neither the orphan check nor the coverage scan reports.
Workflow
Section titled “Workflow”- Edit shard files and
index.mdlink order as needed. - Run
merlon compile— there is no separate manifest sync step. - Run
merlon check— orphan validation uses the same manifest rules as compile.
Code: manifestTextForSections and sectionFiles in packages/merlon-docs-core/src/compile/section-manifest.ts.