Skip to main content

Configuration

Content Root

Tell NookDocs which folder in your repo holds your docs files.

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, ignored

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

  • LICENSE / LICENSE.md, CHANGELOG.md

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

Was this page helpful?

Last updated August 7, 2026