Why this exists
By default NookDocs syncs every .md and .mdx file at your docs base directory (where nookdocs.config.json lives — the repo root for a single repo, or a subfolder for a monorepo). Repo-meta files — README.md, CONTRIBUTING.md, AGENTS.md, LICENSE, CHANGELOG.md, SECURITY.md, CODE_OF_CONDUCT.md — are auto-excluded, and a .nookignore file (gitignore-style, relative to the base) lets you exclude more.
This stops random markdown files in your repo from accidentally becoming public docs pages and cluttering your search results.
Default behavior (flat)
{
"name": "My Docs",
"navigation": [...]
}With no contentRoot set, your content lives flat directly at the docs base — no docs/ subfolder. If your repo looks like this:
my-repo/
├── nookdocs.config.json
├── README.md ← auto-excluded
├── introduction.mdx → /introduction
├── api/
│ └── auth.mdx → /api/auth
└── src/
└── README.md ← outside the base, ignoredThe two .mdx files at the base end up on your docs site; README.md is auto-excluded.
Custom content root (optional override)
Prefer to nest your content in a subfolder under the base? Set contentRoot explicitly:
{
"name": "My Docs",
"contentRoot": "docs/",
"navigation": [...]
}Now docs/intro.mdx becomes /intro, and an intro.mdx left at the base is ignored.
The contentRoot value must end with a trailing slash. "docs" is rejected by the validator — use "docs/".
Common patterns
Flat (default)
No contentRoot. Content .mdx sits directly at the docs base — works for most repos. No config needed.
Nested in a subfolder
Set "contentRoot": "docs/" to keep content under a docs/ folder beneath the base.
Content folder
Coming from a static site generator? Try "contentRoot": "content/".
Monorepo
The docs base itself is the monorepo subfolder — set when you connect the repo (and editable later in Settings → Git → Monorepo). contentRoot then nests further under that base if you want.
contentRoot is relative to the docs base, so the two add up. If your base
is already docs and you also set "contentRoot": "docs/", we look for
docs/docs/ — and if that folder doesn't exist, nothing syncs. With a base
set, leave contentRoot out unless your content really is nested one level
deeper.
What gets excluded
Repo-meta files are auto-excluded even when they sit at the docs base:
README.md,CONTRIBUTING.md,AGENTS.mdLICENSE/LICENSE.md,CHANGELOG.mdSECURITY.md,CODE_OF_CONDUCT.md
A .nookignore file at the docs base (gitignore-style patterns, relative to the base) excludes anything else you don't want published. And of course, anything outside the docs base (or outside contentRoot, if set) is never synced.
Troubleshooting
"My README is showing up as a page"
It shouldn't — README.md is auto-excluded. If some other stray markdown is appearing, add it to .nookignore at the docs base. After the next push, the page will be removed automatically because it's no longer in the filtered file list.
"I want to exclude some files"
Add gitignore-style patterns to a .nookignore file at the docs base. Repo-meta files (README/CONTRIBUTING/AGENTS/LICENSE/CHANGELOG/SECURITY/CODE_OF_CONDUCT) are excluded for you already.
"Where is the file path → URL mapping documented?"
The docs base (and contentRoot, if set) is stripped, the .mdx extension is removed, and index becomes /. See the Navigation guide for the full URL mapping rules.