# Voxx A zero-friction CMS for you and your agents. --- # Introduction Source: https://voxx.prudentbird.com/docs Date: 1970-01-01T00:00:00.000Z Voxx is a zero-friction, file-based CMS. You point it at a folder of markdown and it ships a **blog**, a **docs site**, or a **changelog** — no database, no admin UI, no lock-in. Every page is a plain `.md` file with a little YAML frontmatter, so humans and agents can read and write your content with the same tools they use for code. This page — and every page in this section — is rendered by Voxx from a markdown file in the [repository](https://github.com/prudentbird/voxx). The sidebar, the "On this page" widget, the prev/next pager, the sitemap, and the `llms.txt` behind this site all come from the engine described here. ## Why files Prose wants to be prose — headings, paragraphs, the occasional list — not rows in a database. Keeping each page as one file means you can: - grep, diff, branch, and review content exactly like code - edit anywhere, in any editor, offline - let an agent discover, read, and write pages directly — no API tokens, no custom integration A folder of files will outlive every CMS. ## One engine, three surfaces Voxx renders three kinds of content, all through the same pipeline: | Surface | Shape | Convention | | --------- | ------------------ | ------------------------------------------------- | | Blog | Flat, newest-first | `2026-06-11-hello.md` date-stamps a post | | Docs | Ordered tree | Folders become sections; `01-` prefixes pin order | | Changelog | Versioned timeline | `1.4.0.md` becomes a release with a stable anchor | Need more than one on the same site? Mount them side by side with [collections](/docs/reference/collections). ## What you get out of the box - GitHub-flavored markdown with [Shiki](https://shiki.style) syntax highlighting (light **and** dark) - An "On this page" table of contents built from your headings - Open Graph, Twitter cards, type-aware JSON-LD, and canonical URLs - `sitemap.xml`, RSS, and `llms.txt`, each toggled per surface - Styles that [inherit your design tokens](/docs/reference/theming) — shadcn variables just work ## How the pieces fit - **[`@prudentbird/voxx-core`](/docs/reference/core-api)** is the portable engine: plain async functions in, structured data out. It has no opinion about your framework. - **The [`voxx` CLI](/docs/reference/cli)** scaffolds a surface into your Next.js app — real, editable files you own — or renders a self-contained static site for any other stack. Ready? Head to [Getting started](/docs/getting-started). --- # Getting started Source: https://voxx.prudentbird.com/docs/getting-started Date: 1970-01-01T00:00:00.000Z Every Voxx setup starts the same way — pick a surface, run one command: ```bash npx @prudentbird/voxx init # a blog npx @prudentbird/voxx init docs # a docs site npx @prudentbird/voxx init changelog # a release-notes page ``` `voxx init` looks at the directory you run it in and does the right thing: - **Next.js app detected** — it scaffolds routes under `app/` (or `src/app/`), writes a `voxx.json` and sample content, and wraps your `next.config` with [`withVoxx`](#rendering-modes) when it can do so safely. The generated components live in a `_voxx/` folder inside the mounted route — they're plain files you own and restyle. - **No Next.js** — it asks whether you want a static site (rendered with `voxx build`) or a fresh app via `create-next-app`, then scaffolds into your choice. Then install the engine the scaffolded files import: ```bash npm i @prudentbird/voxx-core ``` Set `site.url` in `voxx.json`, start your dev server, and open the mount path (`/blog`, `/docs`, or `/changelog`). That's the whole loop: write markdown, refresh, publish on deploy. ## Common flags Every preset accepts the same flags: | Flag | Default | What it does | | --------------- | ------------- | ---------------------------------------- | | `--base /notes` | `/` | Mount path — scaffolded routes follow it | | `--dir content` | `content` | Where your markdown lives | | `--app src/app` | auto-detected | The Next.js app directory | | `--force` | off | Overwrite files that already exist | ## Rendering modes Voxx adapts to the host app instead of reconfiguring it. The default data layer memoizes filesystem reads for the life of each deploy, so pages prerender and content reads cost nothing at request time. No whole-app rendering switch comes with it, and existing routes keep behaving exactly as they did. `withVoxx` wires only the serverless plumbing every Voxx app needs. It keeps `@prudentbird/voxx-core` external and traces `voxx.json` plus your content directories into the serverless bundle so runtime reads resolve. It never sets `cacheComponents`, so how the rest of your app renders stays your call: ```ts import type { NextConfig } from "next"; import { withVoxx } from "@prudentbird/voxx-core/next"; const nextConfig: NextConfig = {}; export default withVoxx(nextConfig); ``` Apps that already enable Next's Cache Components get a matching data layer built on the `"use cache"` directive, pinned to the `max` lifetime so it refreshes only on rebuild. `voxx init` detects `cacheComponents: true` in your `next.config` and scaffolds that variant automatically. Pass `--cache-components` or `--no-cache-components` to choose the variant yourself. On Next 16+, `voxx init` wraps your config when it has a recognizable shape. Otherwise it prints the snippet to add yourself. ## Pick your surface Each surface has its own one-page guide: - [Start a blog](/docs/getting-started/blog) - [Start a docs site](/docs/getting-started/docs) - [Start a changelog](/docs/getting-started/changelog) - [Static sites](/docs/getting-started/static-sites) — any stack, no framework --- # Start a blog Source: https://voxx.prudentbird.com/docs/getting-started/blog Date: 1970-01-01T00:00:00.000Z From the root of your Next.js app: ```bash npx @prudentbird/voxx init npm i @prudentbird/voxx-core ``` This writes: ``` voxx.json # config (autocompleted via JSON schema) content/2026-01-15-hello-world.md # a sample post (date prefix orders files; the URL uses the slug) app/blog/page.tsx # the /blog index — lists all posts app/blog/[slug]/page.tsx # one post (+ metadata + static params) app/blog/layout.tsx # imports the Voxx stylesheet app/blog/_voxx/* # data layer + components, yours to edit app/sitemap.ts # sitemap.xml app/robots.ts # robots.txt app/blog/rss.xml/route.ts # /blog/rss.xml app/llms.txt/route.ts # /llms.txt app/llms-full.txt/route.ts # /llms-full.txt ``` Set `site.url` in `voxx.json`, run your dev server, and open `/blog`. ## Write a post Drop a `.md` file in your content folder, or let the CLI do it: ```bash npx @prudentbird/voxx new "Why files win" ``` That creates `content/2026-06-11-why-files-win.md` with frontmatter filled in. The date prefix keeps posts sorted by creation date on disk and doubles as the publish date when frontmatter doesn't say otherwise. Prefer flat names? Pass `--flat`. A post is just this: ```markdown --- title: Why files win description: A short summary used for SEO and excerpts. date: 2026-06-11 tags: [craft, tooling] --- Prose wants to be prose — not rows in a database. Just write and commit. ``` `title` is the only required field — see the [frontmatter reference](/docs/writing/frontmatter) for everything else. ## What blogs get by default Blogs ship with every feature flag on: table of contents, RSS, sitemap, `llms.txt`, tags, and reading time. Turn any of them off in [`voxx.json`](/docs/reference/configuration): ```jsonc { "features": { "readingTime": false } } ``` Posts are sorted newest-first. Drafts (`draft: true`) stay out of the index, the feeds, and the sitemap until you flip them or build with drafts enabled. --- # Start a docs site Source: https://voxx.prudentbird.com/docs/getting-started/docs Date: 1970-01-01T00:00:00.000Z From the root of your Next.js app: ```bash npx @prudentbird/voxx init docs npm i @prudentbird/voxx-core ``` This writes: ``` voxx.json # config, with type: "docs" content/index.md # the docs landing page content/01-getting-started/ # a sample section index.md # the section's landing page 01-installation.md # an ordered page inside it app/docs/[[...slug]]/page.tsx # one route renders the whole tree app/docs/layout.tsx # the docs shell — sidebar, theme toggle app/docs/_voxx/* # nav, drawer, pager, TOC — yours to edit app/sitemap.ts # sitemap.xml app/llms.txt/route.ts # /llms.txt instrumentation.ts # dev content watcher (live reload) ``` Open `/docs` and you'll see the sidebar built from your folders, a prev/next pager that walks the tree in order, and an "On this page" widget built from your headings. The shell is self-contained — your site title at the top of the sidebar, a theme toggle pinned to the bottom, a drawer on mobile. See [Layouts](/docs/reference/layouts) for how it's arranged and how to keep your app's own navbar out of it. ## The conventions Three rules drive the whole thing: 1. **Folders become sections.** `content/guides/deploy.md` ships at `/docs/guides/deploy` and nests under a "Guides" node in the sidebar. 2. **`index.md` lands a section.** It gives the section node its title and URL; without one the section is a label in the sidebar. A root `index.md` is the docs landing page itself. 3. **Numeric prefixes pin order without touching URLs.** `01-install.md` ships at `/docs/install`; the `01-` only decides where it sorts. The same works on folders: `02-writing/` → `/docs/writing`. The full details — ordering precedence, slugs, nesting — live in [Organizing docs](/docs/writing/organizing-docs). ## Add a page ```bash npx @prudentbird/voxx new "Deploying" --section guides --order 3 ``` creates `content/guides/03-deploying.md`. Or just create the file — the CLI is a convenience, never a requirement. ## Live reload Editing a `.md` file updates the page in `next dev` without a manual refresh. Voxx reads content off the filesystem rather than importing it, so Next's HMR does not see those edits on its own. The default static data layer reads fresh content in development, so edits show up on the next request with nothing extra to run. Cache Components mode holds content in the cache across requests, so the scaffolded `instrumentation.ts` starts a dev-only watcher (shipped in `@prudentbird/voxx-core`) that bumps `_voxx/content-version.ts` whenever content or `voxx.json` changes: ```ts export async function register() { if (process.env.NEXT_RUNTIME !== "nodejs") return; const { registerContentWatcher } = await import("@prudentbird/voxx-core"); await registerContentWatcher(); } ``` The cached `data.ts` threads that version into its `"use cache"` calls, so a bump both refreshes the open page and busts the content cache. It runs in development only; production builds are untouched. Delete `instrumentation.ts` to opt out. ## What docs get by default Docs sites default to: table of contents, sitemap, and `llms.txt` **on**; RSS, tags, and reading time **off** — those are blog concerns. Any flag can be overridden in [`voxx.json`](/docs/reference/configuration). This very site is the output of these conventions — the sidebar to your left is a folder listing. --- # Start a changelog Source: https://voxx.prudentbird.com/docs/getting-started/changelog Date: 1970-01-01T00:00:00.000Z From the root of your Next.js app: ```bash npx @prudentbird/voxx init changelog npm i @prudentbird/voxx-core ``` This writes: ``` voxx.json # config, with type: "changelog" content/0.1.0.md # a sample release app/changelog/page.tsx # the timeline — all releases, one page app/changelog/layout.tsx # imports the Voxx stylesheet app/changelog/_voxx/* # the release list, yours to edit app/changelog/rss.xml/route.ts # /changelog/rss.xml — a release feed app/llms.txt/route.ts # /llms.txt app/llms-full.txt/route.ts # /llms-full.txt ``` Open `/changelog` for a single page of releases, newest first, each with a stable anchor link you can share (`/changelog#1-4-0`). ## Cut a release ```bash npx @prudentbird/voxx new "1.4.0" ``` creates `content/1.4.0.md`, pre-dated today: ```markdown --- title: v1.4.0 version: "1.4.0" date: 2026-06-11 --- ### Added - Collections: mount a blog, docs, and changelog on one site. ``` The version comes from the filename (`1.4.0.md`, `v2.0.0-beta.1.md` both work) or from `version:` in frontmatter — frontmatter wins. The body is ordinary markdown; headings like `### Added` / `### Fixed` are a convention, not a requirement. ## What changelogs get by default Changelogs default to: RSS and `llms.txt` **on** (release feeds are useful); table of contents, sitemap, tags, and reading time **off** — one timeline page doesn't need them. Override anything in [`voxx.json`](/docs/reference/configuration). --- # Static sites Source: https://voxx.prudentbird.com/docs/getting-started/static-sites Date: 1970-01-01T00:00:00.000Z Voxx doesn't require Next.js — or any framework. `voxx build` renders your whole collection to plain HTML and CSS: ```bash npx @prudentbird/voxx init # choose "static site" when asked npx @prudentbird/voxx build # -> dist/ ``` The output depends on your content type: - **Blog** — an index page plus one page per post - **Docs** — every page with the sidebar, pager, and TOC baked in; if there's no root `index.md`, Voxx emits a landing page so the base path isn't a 404 - **Changelog** — the release timeline on a single page Alongside the pages you get `rss.xml`, `sitemap.xml`, `robots.txt`, `llms.txt`, and `llms-full.txt`, following the same [feature flags](/docs/reference/configuration#features) as everything else, plus the Voxx stylesheet under `dist/_voxx/`. Images and other non-markdown files in your content folder are copied through, and relative references like `![diagram](./diagram.png)` are resolved to where they land. Multi-collection configs build every collection in one pass. ```bash npx @prudentbird/voxx build --out public # somewhere other than ./dist npx @prudentbird/voxx build --drafts # include draft pages ``` Preview locally with the built-in dev server — it rebuilds on change and includes drafts by default: ```bash npx @prudentbird/voxx dev # http://localhost:4321 ``` Or serve the built folder with anything that can serve files: ```bash npx serve dist ``` ## Bring your own framework The static builder and the Next.js scaffolding are both thin layers over [`@prudentbird/voxx-core`](/docs/reference/core-api), whose public API is plain async functions: ```ts import { getPosts, buildSeo, renderRss } from "@prudentbird/voxx-core"; const posts = await getPosts(); // reads voxx.json, returns Post[] ``` If you're on Astro, Remix, SvelteKit, or a hand-rolled build script, call the engine directly — every `Post` carries rendered HTML, a TOC, SEO-ready fields, and its final URL. --- # Writing content Source: https://voxx.prudentbird.com/docs/writing Date: 1970-01-01T00:00:00.000Z Everything Voxx publishes is a markdown file: YAML frontmatter on top, prose below. There's no editor to learn and no required workflow — create files by hand, with `voxx new`, or let an agent write them. ```markdown --- title: Hello, world description: An optional summary used for SEO and excerpts. --- ## Why files win Prose wants to be prose. Just write and commit. ``` ## What the renderer gives you Voxx renders GitHub-flavored markdown — tables, task lists, strikethrough, autolinks — and adds: - **Syntax highlighting** via Shiki, with paired light/dark themes - **Heading anchors** — every heading gets an id and a self-link, so deep links work with JavaScript disabled - **A table of contents** collected from your `h2`/`h3` headings, which powers the "On this page" widget - **Excerpts and reading time**, derived from the body unless frontmatter says otherwise Raw HTML passes through untouched, so `
`, `