Docs from GitHub

Project layout

A docs project is a folder of Markdown in your repository, with a section.json wherever you want a section.

text
docs/
├── AGENTS.md         the folder's rules for agents. Never published.
├── site.json         header and footer links. Optional.
├── 01-welcome.md
├── getting-started/
│   ├── section.json
│   ├── 01-install.md      →  /~/<workspace>/<knowledge-base>/install
│   └── 02-first-steps.md  →  /~/<workspace>/<knowledge-base>/first-steps
├── billing/
│   ├── section.json
│   └── invoices.md
└── faqs/
    ├── 01-do-you-ship-internationally.md
    └── 02-how-do-i-cancel.md

Which workspace and knowledge base the folder publishes to is set in the workflow, not in the folder. site.json is presentation, and you edit it whenever your marketing site grows a page. See Site navigation.

AGENTS.md and README.md are never published, at any level. Put the folder's rules in AGENTS.md so the next person or agent keeps them.

Titles come from the first heading#

The first # heading in a file becomes the article title and is removed from the body — so it isn't rendered twice.

markdown
# How to cancel your subscription

Open Account → Subscription and choose Cancel.

That becomes an article titled "How to cancel your subscription" whose body starts at "Open Account".

Without an # heading, the filename becomes the title. Rely on the heading; it reads better and survives a rename.

Number your files to order them#

Files sort lexicographically, and that becomes article order. Numeric prefixes give you explicit control:

text
01-install.md
02-first-steps.md
03-troubleshooting.md

The prefix is only for sorting. It never appears in the title, and it never appears in the URL — 01-install.md publishes at /install. Renumbering a file to reorder it does not move its page.

Use 01, not 1. Ten files sorted as strings put 10- between 1- and 2-.

Prefixes are optional: an unprefixed file sorts alphabetically among its siblings, so a folder can mix both.

Choosing a URL#

The URL segment comes from the filename with the ordering prefix stripped. When you want something different, set slug: in frontmatter:

markdown
---
slug: install
---

# Install the widget on your site

That publishes at /install instead of /install-the-widget-on-your-site.

Unlike the derived slug — which is computed once, when the article is first created, so a published page never moves on its own — slug: is applied on every sync. It is how you deliberately rename a live page.

You need it in one other case: a four-digit prefix is left alone so 2026-pricing-change.md keeps its year, but three digits are treated as an ordinal, so 404-page.md would publish at /page. Set slug: 404-page to keep it.

If two files would land on the same URL — getting-started/01-overview.md and billing/02-overview.md both want /overview — the sync fails and names both files. Give one a slug:.

Sections#

Each directory can hold a section.json:

json
{
  "title": "Getting started",
  "position": 10
}

Markdown inherits the nearest section.json above it. A file with none is published as uncategorized.

Leave gaps in position — 10, 20, 30 — so you can insert a section later without renumbering the rest.

FAQs#

Markdown in the root faqs/ directory becomes FAQs instead of articles: the first # heading is the question, the rest is the answer. Only the faqs/ at the root of the folder counts; a faqs/ deeper down holds ordinary articles.

markdown
# Do you ship internationally?

Yes, to most countries. Shipping is calculated at checkout.

Filename order becomes FAQ order inside this knowledge base, written in the same transaction as the articles.

Conventions worth adopting#

One question per file, matching the article advice in the help center guide.

Filenames that match the title. 02-how-do-i-cancel.md for "How do I cancel?" makes the folder browsable without opening anything.

Reordering is safe. Files are matched to existing articles by path, but a file that moved is recognised by the URL it resolves to, so renumbering 01-install.md to 03-install.md updates the article in place — same page, same link. Renaming the part of the filename that becomes the URL is a different article; see How syncs work.

Pinning the folder with .askvoro#

You don't need one. Without it, the folder's identity comes from your repository and the folder's path, and the workflow says which workspace and knowledge base to publish to.

A .askvoro file at the root of the folder pins that identity explicitly:

json
{
  "workspaceId": "YOUR_WORKSPACE_ID",
  "knowledgeBase": "help",
  "sourceId": "src_a_stable_id"
}

It also takes a few optional keys:

KeyDefaultEffect
publishtruefalse publishes every article as a draft.
faqsfaqs/false turns the FAQ folder off; { "directory": "questions" } moves it.
sitesite.jsonfalse clears stored navigation; a path moves the file.

Never hand-edit sourceId. It is the folder's permanent identity, linked to the knowledge base itself, so renaming the knowledge base's slug in the dashboard can't retarget or duplicate your content. Changing it orphans every record the folder owns.