Agent-readable docs index: /llms.txt. Download /docs.zip to grep all markdown files locally.

Local Imports

You can import .tsx, .ts, .jsx, .js, .mdx, or .md files directly in your MDX pages. This lets you use custom React components and shared Markdown snippets alongside the built-in MDX components.

Basic usage

import { PricingTable } from '/components/pricing-table' # Pricing <PricingTable />

Import resolution

Prefer relative imports (./ or ../) over absolute imports. They are simpler, work consistently regardless of pagesDir, and match standard JavaScript conventions.
Relative paths resolve from the MDX file's directory:
import { Badge } from '../components/badge' import Guide from './snippets/guide.md'

Absolute imports (starting with /)

/ means the project root. Holocron probes the pages directory first, then the project root:
import { Chart } from '/components/chart'
If your pagesDir is ./pages, this looks for:
  1. ./pages/components/chart.tsx (pages dir first)
  2. ./components/chart.tsx (project root fallback)
Absolute imports can be ambiguous when pagesDir is set. Prefer relative imports instead.

Importing a README that renders on GitHub too

A popular pattern is importing a repo README.md as the docs index so the same file renders on both GitHub and the Holocron site. The README links to other docs, and those links must work in both places.
The rule is simple: always link to the real target file with a correct relative path, ending in .md or .mdx. Do not reason about slugs, pagesDir, or where / ends up. Write the link the way you would for GitHub — a relative path to the actual file on disk — and Holocron does the rest.
When it inlines the imported file, Holocron recomputes every relative link to be correct relative to the importing page, then strips the .md/.mdx extension. So a link to a real file lands on that file's page automatically.
Because Holocron recomputes the path relative to the importing page, the same relative href works whether the README sits at the repo root and the page lives deep under pagesDir, or vice versa.

Rules

  1. Link to the real file. The target must be an actual .md/.mdx file on disk at the relative path you write. That is what GitHub opens and what Holocron rewrites. Missing file means a GitHub 404 and a Holocron warning.
  2. Always use a relative path (./ or ../), never absolute. The README renders from different base directories on GitHub and Holocron, so an absolute /docs/x or a guessed path breaks in one of them.
  3. Keep the .md/.mdx extension. GitHub needs it to open the file; Holocron strips it so the link resolves to the rendered page.
  4. The target file must be rendered by a page in the site. If the file you link to is itself a page (or is imported by one) and that page is in docs.json, the link resolves. Otherwise the site 404s — add the page and put it in navigation.
README.md [pricing](./docs/pricing.md) ◄── correct relative path to a real file │ ├───────────────────────► GitHub opens ./docs/pricing.md │ ▼ imported into the index page Holocron recomputes the path ──► strips .md ──► lands on the page rendering pricing │ ▼ /docs/pricing ◄── resolves as long as a page renders that file and it is in docs.json

How it works

Import detection is MDX-driven, not folder-based. There are no magic snippets/ or components/ directories. Any local file can be imported from any location.
At build time, Holocron:
  1. Parses each MDX file to extract import statements
  2. Resolves the imports against the filesystem
  3. Generates a virtual module map so the imports work at render time
At dev time, adding or removing JS/TS importable files triggers HMR automatically. Markdown imports are resolved too, but edits to an MDX page are the most reliable way to refresh newly added Markdown snippets.

Supported extensions

The following extensions are tried in order: .tsx, .ts, .jsx, .js, .mdx, .md. You do not need to include the extension in the import path.

Example: shared snippets

A common pattern is a snippets/ directory for reusable content:
my-docs/ ├── snippets/ │ └── install-command.tsx ├── getting-started.mdx └── docs.json
// snippets/install-command.tsx export function InstallCommand() { return ( <div> <div>npm install @holocron.so/vite</div> <div>pnpm add @holocron.so/vite</div> </div> ) }
import { InstallCommand } from '/snippets/install-command' # Getting Started <InstallCommand />