Home /

docs

CLI

The @farming-labs/docs CLI has a few main jobs:

If you only need the common commands, start here. The framework-specific output and generated file lists are further down this page.

Quick Start

From scratch

Use init --template when you want a brand new project directory with docs already set up.

terminal
npx @farming-labs/docs init --template next --name my-docs
npx @farming-labs/docs init --template tanstack-start --name my-docs
npx @farming-labs/docs init --template nuxt --name my-docs
npx @farming-labs/docs init --template sveltekit --name my-docs
npx @farming-labs/docs init --template astro --name my-docs
terminal
pnpm dlx @farming-labs/docs init --template next --name my-docs
pnpm dlx @farming-labs/docs init --template tanstack-start --name my-docs
pnpm dlx @farming-labs/docs init --template nuxt --name my-docs
pnpm dlx @farming-labs/docs init --template sveltekit --name my-docs
pnpm dlx @farming-labs/docs init --template astro --name my-docs
terminal
yarn dlx @farming-labs/docs init --template next --name my-docs
yarn dlx @farming-labs/docs init --template tanstack-start --name my-docs
yarn dlx @farming-labs/docs init --template nuxt --name my-docs
yarn dlx @farming-labs/docs init --template sveltekit --name my-docs
yarn dlx @farming-labs/docs init --template astro --name my-docs
terminal
bunx @farming-labs/docs init --template next --name my-docs
bunx @farming-labs/docs init --template tanstack-start --name my-docs
bunx @farming-labs/docs init --template nuxt --name my-docs
bunx @farming-labs/docs init --template sveltekit --name my-docs
bunx @farming-labs/docs init --template astro --name my-docs

This creates a new folder, clones the example template, installs dependencies, and leaves you with a ready-to-run docs app.

Existing project

Use plain init inside an app you already have.

terminal
npx @farming-labs/docs init
terminal
pnpm dlx @farming-labs/docs init
terminal
yarn dlx @farming-labs/docs init
terminal
bunx @farming-labs/docs init

Run that from your app root. The CLI will:

  1. detect your framework from package.json or ask you to choose
  2. ask for a theme
  3. ask where docs should live, usually docs
  4. ask about aliases, global CSS, and optional i18n when supported
  5. generate the docs files and install the correct @farming-labs/* packages

Upgrade an existing docs project

Use upgrade when docs are already installed and you just want newer package versions.

terminal
npx @farming-labs/docs upgrade
terminal
pnpm dlx @farming-labs/docs upgrade
terminal
yarn dlx @farming-labs/docs upgrade
terminal
bunx @farming-labs/docs upgrade

By default, the CLI detects your framework and package manager from the current project. If detection is ambiguous, pass --framework.

Run the built-in MCP server locally

Use mcp when you want to expose the current docs project to a local MCP client over stdio.

terminal
pnpx @farming-labs/docs mcp

If your config lives outside the project root default:

terminal
pnpm exec docs mcp --config src/lib/docs.config.ts

To test the HTTP MCP route in this repo instead of stdio, start the Next example:

terminal
pnpm --dir examples/next dev

Then point your MCP client or inspector at:

~
http://127.0.0.1:3000/mcp
http://127.0.0.1:3000/.well-known/mcp

Sync an external search index

Use search sync when you want to pre-index docs into a hosted search backend instead of waiting for the first request to trigger sync.

terminal
pnpm dlx @farming-labs/docs search sync --typesense

The command reads .env and .env.local from the current project, scans the docs content based on entry / contentDir, and uploads search documents to the selected provider.

Typesense example:

terminal
pnpm dlx @farming-labs/docs search sync --typesense

Required env:

terminal
TYPESENSE_URL=https://your-cluster.a1.typesense.net
TYPESENSE_API_KEY=your-admin-capable-key

Optional:

terminal
TYPESENSE_COLLECTION=docs
TYPESENSE_MODE=hybrid
TYPESENSE_OLLAMA_MODEL=embeddinggemma
TYPESENSE_OLLAMA_BASE_URL=http://127.0.0.1:11434

Algolia example:

terminal
pnpm dlx @farming-labs/docs search sync --algolia

Required env:

terminal
ALGOLIA_APP_ID=your-app-id
ALGOLIA_ADMIN_API_KEY=your-admin-key
ALGOLIA_SEARCH_API_KEY=your-search-key

Generate sitemaps

Use sitemap generate when you want static sitemap.xml and sitemap.md files, or when a server-rendered deployment needs a generated manifest with reliable lastmod dates.

terminal
pnpm exec docs sitemap generate

By default the command writes:

SvelteKit writes the public files under static/ instead of public/. Use --config when your config lives outside the project root:

terminal
pnpm exec docs sitemap generate --config src/lib/docs.config.ts

Useful flags:

FlagDescription
--config <path>Use a custom docs config path.
--manifest-onlyWrite only .farming-labs/sitemap-manifest.json. Useful for server-rendered apps that serve sitemap routes through the runtime.
--publicExplicitly write public sitemap files. This is already the default unless --manifest-only is set.
--checkFail if the generated manifest or public sitemap files are stale.

The generator resolves lastmod from each page source file's last git commit date, then falls back to filesystem modified time. See Sitemaps for route config, static export setup, and output examples.

Generate robots.txt

Use robots generate when you want a static robots.txt file that explicitly allows docs, markdown, llms.txt, sitemap, AGENTS.md, skill, MCP, and agent discovery routes.

terminal
pnpm exec docs robots generate

By default the command resolves the framework public directory and writes:

If the target file already exists, the command keeps it untouched. Use --append to add or update the generated @farming-labs/docs block inside an existing policy, or --force to replace the file:

terminal
pnpm exec docs robots generate --append
pnpm exec docs robots generate --force
pnpm exec docs robots generate --path public/robots.txt --append

Useful flags:

FlagDescription
--path <path>Write to a specific robots.txt path. Positional paths work too.
--appendAdd or update the generated block inside an existing robots.txt.
--forceReplace the target robots.txt with the generated policy.
--checkFail if the generated output would change.
--config <path>Use a custom docs config path.

Configure defaults with robots in docs.config.ts, then run the command during release prep or static export builds when you want the policy committed.

Compact page-level agent docs

For commands, config, and how generated agent.md files affect .md routes, docs API markdown output, and MCP, see Agent compact below.

Agent compact

Use agent compact when you want shorter page-level machine docs without hand-writing every agent.md.

What it does:

Common forms:

terminal
pnpm exec docs agent compact installation configuration
pnpm exec docs agent compact /docs/installation
pnpm exec docs agent compact /docs/installation.md
pnpm exec docs agent compact https://docs.example.com/docs/installation
pnpm exec docs agent compact . --dry-run
pnpm exec docs agent compact --page installation --page configuration
pnpm exec docs agent compact --all
pnpm exec docs agent compact --changed
pnpm exec docs agent compact --stale
pnpm exec docs agent compact --stale --include-missing

Selection notes:

Recommended config defaults:

docs.config.ts
export default defineDocs({
  entry: "docs",
  agent: {
    compact: {
      apiKeyEnv: "TOKEN_COMPANY_API_KEY",
      model: "bear-1.2",
      aggressiveness: 0.3,
      protectJson: true,
    },
  },
});

If you prefer to reference the env var directly in docs.config.tsx, that works too:

docs.config.tsx
export default defineDocs({
  entry: "docs",
  agent: {
    compact: {
      apiKey: process.env.TOKEN_COMPANY_API_KEY,
    },
  },
});

The command loads .env and .env.local from the current project before it resolves the key, so the default TOKEN_COMPANY_API_KEY env var works without exporting it manually.

Per-page budget overrides live in frontmatter:

app/docs/installation/page.mdx
---
title: "Installation"
description: "Install the framework"
agent:
  tokenBudget: 777
---

That agent.tokenBudget value becomes the compact output target for just that page. It overrides global agent.compact.maxOutputTokens defaults and CLI --max-output-tokens values for the same page. If the page already has a sibling agent.md, the command compacts that file. If it does not, the command compacts the generated machine-readable page output first and then writes the resulting agent.md.

If a global minOutputTokens would be higher than the page budget, the CLI clamps it down to the same page budget before calling the compression API.

Generated agent.md files include hidden provenance metadata so the CLI can tell the difference between:

docs doctor --agent reports those states, and docs agent compact --stale only refreshes the generated files that are actually stale. Handwritten agent.md files still count as explicit machine context; the doctor reports them as unknown freshness instead of treating them as stale.

Useful checks:

terminal
pnpm exec docs agent compact installation --dry-run
pnpm exec docs agent compact --changed
pnpm exec docs agent compact installation
curl "http://127.0.0.1:3000/docs/installation.md"

See Configuration for agent.compact, and Token Efficiency for when you should use compaction instead of writing agent.md by hand.

Agents Generate

Generate committed AGENTS.md files for coding agents and static exports:

terminal
pnpm exec docs agents generate
pnpm exec docs agents generate --check
pnpm exec docs agents generate --force
pnpm exec docs agents generate --path AGENTS.md

By default the command writes a managed root AGENTS.md plus public copies at /AGENTS.md, /.well-known/AGENTS.md, /AGENT.md, and /.well-known/AGENT.md (static/ instead of public/ for SvelteKit). If a hand-written root AGENTS.md or AGENT.md already exists, the command keeps it and uses that content for missing static aliases unless --force is passed.

Doctor

Use docs doctor --agent when you want a quick health check for the machine-facing side of the docs site.

Use docs doctor --site when you want a reader-facing audit of navigation, descriptions, structure, trust signals, feedback, and reading-time cues.

This command does not generate files. It inspects the current project and scores how ready the docs are for agents, IDEs, and GEO-style crawlers.

What it checks:

Common forms:

terminal
pnpm exec docs doctor
pnpm exec docs doctor --agent
pnpm exec docs doctor --site
pnpm exec docs doctor --agent --json
pnpm exec docs doctor agent
pnpm exec docs doctor site
pnpm exec docs doctor --agent --config docs.config.tsx
pnpm exec docs doctor --agent --url https://docs.example.com
pnpm exec docs doctor --agent --url https://docs.example.com --json

Expected output:

@farming-labs/docs doctor — agent

Score: 100% (Agent-optimized)
Framework: nextjs • Entry: docs • Content: app/docs
Explicit agent-friendly pages: 37/37 pages (100%)

PASS Docs API route (10/10)
  Found docs API route at app/api/docs/route.ts.
PASS Agent discovery spec (5/5)
  Expected discovery endpoints are available through /.well-known/agent.json, /.well-known/agent, and /api/docs?agent=spec.
PASS Robots agent policy (5/5)
  public/robots.txt advertises agent-readable routes and common AI crawler policy.
PASS Page metadata (5/5)
  37/37 pages include descriptions and 8/37 pages include related links (100% described, 22% related).
PASS Explicit page optimization (10/10)
  37/37 pages define explicit machine-only context (2 agent.md, 35 Agent blocks, 100% of pages).
PASS Agent compaction freshness (5/5)
  0 fresh, 0 stale, 0 modified, 2 unknown, 0 token-budget missing, and 35 other missing pages across compactable docs pages. agent.compact defaults are configured.

Sample abbreviated for brevity. Full runs can also include a Next steps section with the most useful follow-up improvements.

Reader-facing runs use the same overall shape, but print doctor — site and score:

When you need structured output instead of terminal text, add --json:

terminal
pnpm exec docs doctor --agent --json
pnpm exec docs doctor --site --json

Sample shape:

~
{
  "mode": "agent",
  "score": 87,
  "maxScore": 100,
  "grade": "Agent-ready",
  "framework": "nextjs",
  "entry": "docs",
  "contentDir": "app/docs",
  "coverage": {
    "explicitPages": 10,
    "totalPages": 41,
    "explicitCoverage": 24
  },
  "checks": [
    {
      "id": "api-route",
      "title": "Docs API route",
      "status": "pass",
      "score": 10,
      "maxScore": 10
    }
  ],
  "recommendations": [
    "Add page-level Agent blocks or agent.md files for workflows where the rendered docs need machine-only hints."
  ]
}

The JSON report itself is written to stdout. Separate loader notices, such as config fallback warnings, are outside the JSON payload.

Hosted agent checks

Add --url when you want the doctor to verify a deployed docs site in addition to the local project files:

terminal
pnpm exec docs doctor --agent --url https://docs.example.com

Without --url, the command only inspects the repository: config, content, route files, metadata, generated sitemap state, and local agent-readiness signals. With --url, it also sends real requests to the hosted site and adds hosted checks to the report.

The hosted pass probes:

For MCP, the doctor performs a Streamable HTTP initialize request, reuses mcp-session-id when the server returns one, sends tools/list, and expects the built-in docs tools:

Hosted checks add extra weighted checks, but the top-level score stays normalized to 100%. The JSON report also includes the normalized url field and hosted check IDs such as hosted-agent-discovery, hosted-llms, hosted-sitemap, hosted-robots, hosted-skill, hosted-markdown, hosted-markdown-canonical, hosted-structured-data, hosted-markdown-alternate, and hosted-mcp.

Use this form after deploying, in preview-deployment CI, or any time a site looks healthy locally but an agent cannot discover the public routes. A hosted failure usually means the deployment is missing a rewrite, middleware forwarder, or public route, not that the MDX page content itself is wrong.

How to read it:

When to use it:

How essential it is:

Init

init without --template

When you run init without --template, the CLI asks whether you're working with an existing project or starting from scratch.

ChoiceBest forWhat happens
Existing projectYou already have a Next.js, TanStack Start, Nuxt, SvelteKit, or Astro appThe CLI adds docs to the current app
Fresh projectYou want a new docs starterThe CLI creates a new folder from the selected example template

From scratch

If you select Fresh project, the CLI asks for:

  1. Framework — Next.js, TanStack Start, Nuxt, SvelteKit, or Astro
  2. Project name — default is my-docs
  3. Package manager — used for install and the suggested dev command

You can skip those prompts entirely with --template and --name.

terminal
npx @farming-labs/docs init --template next --name my-docs
terminal
pnpm dlx @farming-labs/docs init --template next --name my-docs
terminal
yarn dlx @farming-labs/docs init --template next --name my-docs
terminal
bunx @farming-labs/docs init --template next --name my-docs

Replace next with tanstack-start, nuxt, sveltekit, or astro.

Existing project

If you select Existing project, the CLI stays in the current folder and wires docs into the app you already have.

  1. Framework — Auto-detected from package.json, or you pick one if detection fails.
  2. Theme — One of the built-in themes or Create your own theme (you’ll be asked for a theme name; it creates themes/<name>.ts and themes/<name>.css).
  3. Path aliases — Whether to use @/, $lib/, or ~/ for imports (framework-dependent).
  4. Entry path — Where docs live (e.g. docs). Press Enter to use the default.
  5. Optional API reference — Whether to scaffold API reference support. If you enable it, the CLI pre-fills the detected API route root (usually api) and lets you edit it before writing apiReference.routeRoot.
  6. Optional i18n — Whether to scaffold internationalized docs, which locales to generate, any extra locale codes to add, and which locale should be the default.
  7. Global CSS — Which file to use (auto-detected if there’s only one, otherwise you pick or type the path; Enter uses the default).
  8. The CLI generates config, layout, and sample pages, then detects the package manager from a lockfile when possible. If no lockfile is found, it asks which package manager you want to use before installing dependencies, and can then start the dev server.

Typical flow:

terminal
cd my-app
npx @farming-labs/docs init
terminal
cd my-app
pnpm dlx @farming-labs/docs init
terminal
cd my-app
yarn dlx @farming-labs/docs init
terminal
cd my-app
bunx @farming-labs/docs init

Prompts that show a placeholder (e.g. entry path docs, project name my-docs, theme name my-theme) use that value as the default — you can press Enter to accept it instead of typing.

Existing-project flags

Use these to skip the matching prompts during init:

FlagDescription
--theme <name>Skip the theme prompt
--entry <path>Skip the docs entry prompt
--api-referenceEnable API reference scaffold during init
--no-api-referenceExplicitly skip API reference scaffold
--api-route-root <path>Set the detected API route root written to apiReference.routeRoot

Example:

terminal
npx @farming-labs/docs init --theme greentree --entry docs --api-reference --api-route-root internal-api

--api-route-root is optional. If you omit it, the CLI tries to detect a sensible default from the framework’s route conventions and shows that value as the default in the prompt.

When API reference is enabled through init:

Optional i18n scaffold

If you enable i18n during init, the CLI will:

  1. Let you multi-select common locales such as en, fr, es, de, pt, ja, ko, zh, ar, hi, and ru
  2. Let you add custom locale codes such as pt-BR
  3. Ask which locale should be the default

The generated project gets:

Upgrade

Upgrade all @farming-labs/* docs packages to the latest version, beta channel, or an exact version. Run from your project root; the CLI auto-detects your framework from package.json and upgrades the right packages for Next.js, TanStack Start, Nuxt, SvelteKit, and Astro.

The CLI also detects your package manager from the lockfile in the current directory (pnpm-lock.yaml, yarn.lock, bun.lock, bun.lockb, or package-lock.json). If no lockfile is found, it asks which package manager you want to use instead of defaulting to npm.

terminal
npx @farming-labs/docs upgrade
terminal
pnpm dlx @farming-labs/docs upgrade
terminal
yarn dlx @farming-labs/docs upgrade
terminal
bunx @farming-labs/docs upgrade
FrameworkPackages upgraded
Next.js@farming-labs/docs, @farming-labs/theme, @farming-labs/next
TanStack Start@farming-labs/docs, @farming-labs/theme, @farming-labs/tanstack-start
Nuxt@farming-labs/docs, @farming-labs/nuxt, @farming-labs/nuxt-theme
SvelteKit@farming-labs/docs, @farming-labs/svelte, @farming-labs/svelte-theme
Astro@farming-labs/docs, @farming-labs/astro, @farming-labs/astro-theme

To specify the framework explicitly (e.g. in a monorepo or when auto-detect fails), use --framework:

terminal
npx @farming-labs/docs upgrade --framework tanstack-start
# or
npx @farming-labs/docs upgrade tanstack-start
terminal
pnpm dlx @farming-labs/docs upgrade --framework tanstack-start
# or
pnpm dlx @farming-labs/docs upgrade tanstack-start
terminal
yarn dlx @farming-labs/docs upgrade --framework tanstack-start
# or
yarn dlx @farming-labs/docs upgrade tanstack-start
terminal
bunx @farming-labs/docs upgrade --framework tanstack-start
# or
bunx @farming-labs/docs upgrade tanstack-start

Valid values: next, tanstack-start, nuxt, sveltekit, astro.

Use --latest (default) to install the latest stable release, --beta to install beta versions, or --version <version> to install a specific release:

terminal
npx @farming-labs/docs upgrade              # latest stable (default)
npx @farming-labs/docs upgrade --latest     # same
npx @farming-labs/docs upgrade --beta       # beta versions
npx @farming-labs/docs upgrade --version 0.1.104
terminal
pnpm dlx @farming-labs/docs upgrade              # latest stable (default)
pnpm dlx @farming-labs/docs upgrade --latest     # same
pnpm dlx @farming-labs/docs upgrade --beta       # beta versions
pnpm dlx @farming-labs/docs upgrade --version 0.1.104
terminal
yarn dlx @farming-labs/docs upgrade              # latest stable (default)
yarn dlx @farming-labs/docs upgrade --latest     # same
yarn dlx @farming-labs/docs upgrade --beta       # beta versions
yarn dlx @farming-labs/docs upgrade --version 0.1.104
terminal
bunx @farming-labs/docs upgrade              # latest stable (default)
bunx @farming-labs/docs upgrade --latest     # same
bunx @farming-labs/docs upgrade --beta       # beta versions
bunx @farming-labs/docs upgrade --version 0.1.104

If you prefer the shorter command form, the CLI also accepts upgrade@beta and upgrade@latest. For example, pnpx @farming-labs/docs upgrade@beta behaves like pnpx @farming-labs/docs upgrade --beta.

Downgrade

Use downgrade when you need to move the docs packages back to a lower published version. The CLI auto-detects your framework and package manager the same way upgrade does.

Without --version, it installs the published version immediately below your current installed @farming-labs/docs version:

terminal
npx @farming-labs/docs downgrade
terminal
pnpm dlx @farming-labs/docs downgrade
terminal
yarn dlx @farming-labs/docs downgrade
terminal
bunx @farming-labs/docs downgrade

Pass --version to choose an exact lower version:

terminal
npx @farming-labs/docs downgrade --version 0.1.103

If the requested version is newer than the current installed version, the command stops and points you to upgrade --version <version> instead.

MCP

Run the built-in docs MCP server over stdio from the current project.

terminal
npx @farming-labs/docs mcp

The command reads docs.config.ts[x] from the current project root by default and reuses the docs graph from your configured entry and contentDir.

Use --config when the config lives somewhere else:

terminal
pnpm exec docs mcp --config src/lib/docs.config.ts

The current built-in MCP surface includes:

For the HTTP endpoint version, see MCP Server.

Supported Frameworks

FrameworkDetectioninitupgradedowngrade
Next.jsnext in dependenciesSupportedSupportedSupported
TanStack Start@tanstack/react-start in dependenciesSupportedSupportedSupported
SvelteKit@sveltejs/kit in dependenciesSupportedSupportedSupported
Astroastro in dependenciesSupportedSupportedSupported
Nuxtnuxt in dependenciesSupportedSupportedSupported

Available Themes

The init CLI offers several built-in themes plus an option to create your own:

ThemeDescription
fumadocsClean, neutral docs theme (default)
darksharpAll-black, sharp corners, no rounded edges
pixel-borderRefined dark UI inspired by better-auth.com
colorfulFumadocs-style neutral theme with description support
greentreeEmerald green accent, Inter font, Mintlify-inspired
ledgerStripe Docs-inspired product docs shell with navy code panels
command-gridMono-first paper-grid preset inspired by the better-cmdk landing page
concreteBrutalist poster-style theme with offset shadows
hardlineHard-edge theme with square corners and bold borders
darkboldPure monochrome, Geist typography, clean minimalism
shinyGlossy, modern look with subtle shimmer effects
Create your own themeScaffolds themes/<name>.ts and themes/<name>.css; you’re prompted for the theme name (default my-theme). See Creating your own theme.

What it does (Existing project)

When you choose Existing project, the CLI does the following (framework-specific files vary):

  1. Detects Next.js via next in your package.json (or asks you to pick a framework)
  2. Asks for a theme — built-in themes or Create your own theme (then prompts for theme name; press Enter for default my-theme)
  3. Asks for the entry path — Default is docs (press Enter to accept)
  4. Asks about path aliases — Use @/ alias or relative paths for imports
  5. Optionally scaffolds i18n — Generates locale folders like app/docs/en and app/docs/fr, plus locale-aware wrapper pages
  6. Generates files:
    • docs.config.ts — Full config with your selected theme
    • next.config.ts — Wraps your existing config with withDocs()
    • app/global.css — Imports Tailwind and theme CSS
    • app/layout.tsx — Root layout with RootProvider
    • app/docs/layout.tsx — Docs layout
    • app/docs/page.mdx — Sample documentation page when i18n is disabled
    • app/docs/installation/page.mdx — Sample installation guide when i18n is disabled
    • app/docs/quickstart/page.mdx — Sample quickstart guide when i18n is disabled
  7. Installs dependencies@farming-labs/docs, @farming-labs/theme, @farming-labs/next
  8. Starts the dev server — Opens your docs at http://localhost:3000/docs
  1. Detects TanStack Start via @tanstack/react-start in your package.json (or asks you to pick a framework)
  2. Asks for a theme — built-in themes or Create your own theme (then prompts for theme name; press Enter for default my-theme)
  3. Asks about path aliases — Use @/ alias or relative paths for imports
  4. Asks for the entry path — Default is docs (press Enter to accept)
  5. Skips the built-in i18n scaffold so the generated TanStack routes stay minimal and working
  6. Generates files:
    • docs.config.ts — Full config with your selected theme
    • src/lib/docs.server.ts — TanStack docs server
    • src/lib/docs.functions.ts — Server function wrapper for page loading
    • src/routes/{entry}/index.tsx — Docs index route
    • src/routes/{entry}/$.tsx — Catch-all docs route
    • src/routes/api/docs.ts — Search and AI API route
    • src/routes/$.ts — Public llms.txt, sitemap, .well-known, .md, and MCP aliases
    • src/styles/app.css — Imports Tailwind and theme CSS
    • docs/page.mdx — Sample documentation page
    • docs/installation/page.mdx — Sample installation guide
    • docs/quickstart/page.mdx — Sample quickstart guide
  7. Updates existing app files when needed — Injects RootProvider into src/routes/__root.tsx and adds docsMdx() / Tailwind plugins to vite.config.ts
  8. Installs dependencies@farming-labs/docs, @farming-labs/theme, @farming-labs/tanstack-start
  9. Starts the dev server — Opens your docs at http://localhost:5173/docs

In this repo's examples and in other monorepos, keep those @farming-labs/* dependencies linked locally while testing unpublished changes. CI and Vercel on Node 22 should consume the built adapter entrypoints, not raw src/*.ts files from node_modules.

  1. Detects SvelteKit via @sveltejs/kit in your package.json (or asks you to pick a framework)
  2. Asks for a theme — built-in themes or Create your own theme (then prompts for theme name; press Enter for default)
  3. Asks for the entry path — Default is docs (press Enter to accept)
  4. Asks about path aliases — Use $lib/ alias or relative paths for imports
  5. Optionally scaffolds i18n — Generates locale folders like docs/en and docs/fr plus a docs root page for /docs?lang=...
  6. Generates files (does not touch svelte.config.js):
    • src/lib/docs.config.ts — Full config with your selected theme
    • src/lib/docs.server.ts — Server-side docs loader with import.meta.glob for production builds
    • src/routes/docs/+layout.svelte — Docs layout component
    • src/routes/docs/+layout.server.js — Layout data loader
    • src/routes/docs/[...slug]/+page.svelte — Dynamic page component
    • src/routes/docs/+page.svelte — Generated when i18n is enabled
    • src/routes/api/docs/+server.ts — Search and AI API route
    • src/hooks.server.ts — Public llms.txt, sitemap, .well-known, .md, and MCP aliases
    • src/app.css — Theme CSS import
    • docs/page.md — Sample documentation page
    • docs/installation/page.md — Sample installation guide
    • docs/quickstart/page.md — Sample quickstart guide
  7. Installs dependencies@farming-labs/docs, @farming-labs/svelte, @farming-labs/svelte-theme
  8. Starts the dev server — Opens your docs at http://localhost:5173/docs

Production note: The generated docs.server.ts uses import.meta.glob to bundle your markdown files at build time. This is required for serverless deployments (Vercel, Netlify, etc.) where the filesystem is not available at runtime.

  1. Detects Astro via astro in your package.json (or asks you to pick a framework)
  2. Asks for a theme — built-in themes or Create your own theme (then prompts for theme name; press Enter for default)
  3. Asks for the entry path — Default is docs (press Enter to accept)
  4. Optionally scaffolds i18n — Generates locale folders like docs/en and docs/fr
  5. Generates files:
    • src/lib/docs.config.ts — Full config with your selected theme
    • src/lib/docs.server.ts — Server-side docs loader with import.meta.glob for production builds
    • src/pages/{entry}/index.astro — Docs index page
    • src/pages/{entry}/[...slug].astro — Dynamic page component
    • src/pages/api/{entry}.ts — API route for search and AI
    • src/middleware.ts — Public llms.txt, sitemap, .well-known, .md, and MCP aliases
    • astro.config.mjs — Astro config with SSR enabled
    • docs/page.md — Sample documentation page
    • docs/installation/page.md — Sample installation guide
    • docs/quickstart/page.md — Sample quickstart guide
  6. Installs dependencies@farming-labs/docs, @farming-labs/astro, @farming-labs/astro-theme
  7. Starts the dev server — Opens your docs at http://localhost:4321/docs

Production note: The generated docs.server.ts uses import.meta.glob to bundle your markdown files at build time. This is required for serverless deployments (Vercel, Netlify, etc.) where the filesystem is not available at runtime.

  1. Detects Nuxt via nuxt in your package.json (or asks you to pick a framework)
  2. Asks for a theme — built-in themes or Create your own theme (then prompts for theme name; press Enter for default)
  3. Asks for the entry path — Default is docs (press Enter to accept)
  4. Optionally scaffolds i18n — Generates locale folders like docs/en and docs/fr
  5. Generates files:
    • docs.config.ts — Full config with your selected theme
    • nuxt.config.ts — Nuxt config with theme CSS and server assets
    • server/api/docs.ts — docs data, search, AI, and page loading
    • server/middleware/docs-public.ts — public llms.txt, sitemap, .well-known, .md, and MCP aliases
    • pages/docs/[[...slug]].vue — Catch-all page component that handles the docs index and nested docs routes
    • docs/page.md — Sample documentation page
    • docs/installation/page.md — Sample installation guide
    • docs/quickstart/page.md — Sample quickstart guide
  6. Installs dependencies@farming-labs/docs, @farming-labs/nuxt, @farming-labs/nuxt-theme
  7. Starts the dev server — Opens your docs at http://localhost:3000/docs

Example Output

next-js-project-structure.txt
$ npx @farming-labs/docs init

  ┌ @farming-labs/docs

  ◆ Are you adding docs to an existing project or starting fresh?
  │ ● Existing project — Add docs to the current app in this directory
  │ ○ Fresh project — Bootstrap a new app from a template

  ◆ Detected framework: Next.js

  ◆ Which theme would you like to use?
  │ ● fumadocs (default)
  │ ○ darksharp
  │ ○ pixel-border
  │ ○ colorful
  │ ○ greentree
  │ ○ concrete
  │ ○ command-grid
  │ ○ hardline
  │ ○ darkbold
  │ ○ shiny
  │ ○ Create your own theme

  ◆ Where should your docs live?
  │ docs  (press Enter for default)

  ◆ Scaffold i18n support?
  │ ● Yes
  │ ○ No

  ◆ Which locales should we scaffold?
  │ ◻ en
  │ ◼ fr
  │ ◼ de

  ◆ Any additional locale codes? (comma-separated, optional)
  │ pt-BR

  ◆ Which locale should be the default?
  │ ● fr
  │ ○ de
  │ ○ pt-BR

  ◆ Use path aliases for imports?
  │ ● Yes (@/ alias)
  │ ○ No (relative paths)

  ◇ Generated docs.config.ts
  ◇ Generated next.config.ts
  ◇ Generated app/global.css
  ◇ Generated app/components/locale-doc-page.tsx
  ◇ Generated app/docs/page.mdx
  ◇ Generated app/docs/installation/page.mdx
  ◇ Generated app/docs/quickstart/page.mdx
  ◇ Generated app/docs/fr/page.mdx
  ◇ Generated app/docs/fr/installation/page.mdx
  ◇ Generated app/docs/fr/quickstart/page.mdx
  ◇ Generated app/docs/de/page.mdx
  ◇ Generated app/docs/de/installation/page.mdx
  ◇ Generated app/docs/de/quickstart/page.mdx
  ◇ Generated app/docs/pt-BR/page.mdx
  ◇ Generated app/docs/pt-BR/installation/page.mdx
  ◇ Generated app/docs/pt-BR/quickstart/page.mdx

  ◇ Installing dependencies...
  ◇ Starting dev server...

  └ Done! Open http://localhost:3000/docs
tanstack-start-project-structure.txt
$ npx @farming-labs/docs init

  ┌ @farming-labs/docs

  ◆ Are you adding docs to an existing project or starting fresh?
  │ ● Existing project
  │ ○ Fresh project

  ◆ Detected framework: TanStack Start

  ◆ Which theme would you like to use?
  │ ● fumadocs (default)
  │ ○ darksharp
  │ ○ pixel-border
  │ ○ colorful
  │ ○ greentree
  │ ○ concrete
  │ ○ command-grid
  │ ○ hardline
  │ ○ darkbold
  │ ○ shiny
  │ ○ Create your own theme

  ◆ Use path aliases for imports?
  │ ● Yes (@/ alias)
  │ ○ No (relative paths)

  ◆ Where should your docs live?
  │ docs  (press Enter for default)

  ℹ Skipping i18n scaffold for TanStack Start. Configure localized routes manually if needed.

  ◇ Generated docs.config.ts
  ◇ Generated src/lib/docs.server.ts
  ◇ Generated src/lib/docs.functions.ts
  ◇ Generated src/routes/docs/index.tsx
  ◇ Generated src/routes/docs/$.tsx
  ◇ Generated src/routes/api/docs.ts
  ◇ Updated src/routes/__root.tsx
  ◇ Updated vite.config.ts
  ◇ Updated src/styles/app.css

  ◇ Installing dependencies...
  ◇ Starting dev server...

  └ Done! Open http://localhost:5173/docs
sveltekit-project-structure.txt
$ npx @farming-labs/docs init

  ┌ @farming-labs/docs

  ◆ Are you adding docs to an existing project or starting fresh?
  │ ● Existing project
  │ ○ Fresh project

  ◆ Detected framework: SvelteKit

  ◆ Which theme would you like to use?
  │ ● fumadocs (default)
  │ ○ darksharp
  │ ○ pixel-border
  │ ○ colorful
  │ ○ darkbold
  │ ○ shiny
  │ ○ greentree
  │ ○ concrete
  │ ○ command-grid
  │ ○ hardline

  ◆ Entry path for docs:
  │ docs

  ◆ Scaffold i18n support?
  │ ● Yes
  │ ○ No

  ◆ Which locales should we scaffold?
  │ ◼ en
  │ ◼ fr
  │ ◻ de

  ◆ Any additional locale codes? (comma-separated, optional)

  ◆ Which locale should be the default?
  │ ● en
  │ ○ fr

  ◆ Use path aliases for imports?
  │ ● Yes ($lib/ alias)
  │ ○ No (relative paths)

  ◇ Generated src/lib/docs.config.ts
  ◇ Generated src/lib/docs.server.ts
  ◇ Generated src/routes/docs/+layout.svelte
  ◇ Generated src/routes/docs/+layout.server.js
  ◇ Generated src/routes/docs/[...slug]/+page.svelte
  ◇ Generated src/routes/api/docs/+server.ts
  ◇ Generated src/hooks.server.ts
  ◇ Generated docs/page.md
  ◇ Generated docs/installation/page.md
  ◇ Generated docs/quickstart/page.md
  ◇ Generated docs/en/page.md
  ◇ Generated docs/en/installation/page.md
  ◇ Generated docs/en/quickstart/page.md
  ◇ Generated docs/fr/page.md
  ◇ Generated docs/fr/installation/page.md
  ◇ Generated docs/fr/quickstart/page.md

  ◇ Installing dependencies...
  ◇ Starting dev server...

  └ Done! Open http://localhost:5173/docs
astro-project-structure.txt
$ npx @farming-labs/docs init

  ┌ @farming-labs/docs

  ◆ Are you adding docs to an existing project or starting fresh?
  │ ● Existing project
  │ ○ Fresh project

  ◆ Detected framework: Astro

  ◆ Which theme would you like to use?
  │ ● fumadocs (default)
  │ ○ darksharp
  │ ○ pixel-border
  │ ○ colorful
  │ ○ darkbold
  │ ○ shiny
  │ ○ greentree
  │ ○ concrete
  │ ○ command-grid
  │ ○ hardline

  ◆ Entry path for docs:
  │ docs

  ◆ Scaffold i18n support?
  │ ● Yes
  │ ○ No

  ◆ Which locales should we scaffold?
  │ ◼ en
  │ ◼ ja
  │ ◻ fr

  ◆ Any additional locale codes? (comma-separated, optional)
  │ zh-CN

  ◆ Which locale should be the default?
  │ ● en
  │ ○ ja
  │ ○ zh-CN

  ◇ Generated src/lib/docs.config.ts
  ◇ Generated src/lib/docs.server.ts
  ◇ Generated src/pages/docs/index.astro
  ◇ Generated src/pages/docs/[...slug].astro
  ◇ Generated src/pages/api/docs.ts
  ◇ Generated src/middleware.ts
  ◇ Generated astro.config.mjs
  ◇ Generated docs/page.md
  ◇ Generated docs/installation/page.md
  ◇ Generated docs/quickstart/page.md
  ◇ Generated docs/en/page.md
  ◇ Generated docs/en/installation/page.md
  ◇ Generated docs/en/quickstart/page.md
  ◇ Generated docs/ja/page.md
  ◇ Generated docs/ja/installation/page.md
  ◇ Generated docs/ja/quickstart/page.md
  ◇ Generated docs/zh-CN/page.md
  ◇ Generated docs/zh-CN/installation/page.md
  ◇ Generated docs/zh-CN/quickstart/page.md

  ◇ Installing dependencies...
  ◇ Starting dev server...

  └ Done! Open http://localhost:4321/docs
nuxt-project-structure.txt
$ npx @farming-labs/docs init

  ┌ @farming-labs/docs

  ◆ Are you adding docs to an existing project or starting fresh?
  │ ● Existing project
  │ ○ Fresh project

  ◆ Detected framework: Nuxt

  ◆ Which theme would you like to use?
  │ ● fumadocs (default)
  │ ○ darksharp
  │ ○ pixel-border
  │ ○ colorful
  │ ○ darkbold
  │ ○ shiny
  │ ○ greentree
  │ ○ concrete
  │ ○ command-grid
  │ ○ hardline

  ◆ Entry path for docs:
  │ docs

  ◆ Scaffold i18n support?
  │ ● Yes
  │ ○ No

  ◆ Which locales should we scaffold?
  │ ◼ en
  │ ◼ es
  │ ◻ fr

  ◆ Any additional locale codes? (comma-separated, optional)

  ◆ Which locale should be the default?
  │ ● en
  │ ○ es

  ◇ Generated docs.config.ts
  ◇ Generated nuxt.config.ts
  ◇ Generated server/api/docs.ts
  ◇ Generated server/middleware/docs-public.ts
  ◇ Generated pages/docs/[...slug].vue
  ◇ Generated docs/page.md
  ◇ Generated docs/installation/page.md
  ◇ Generated docs/quickstart/page.md
  ◇ Generated docs/en/page.md
  ◇ Generated docs/en/installation/page.md
  ◇ Generated docs/en/quickstart/page.md
  ◇ Generated docs/es/page.md
  ◇ Generated docs/es/installation/page.md
  ◇ Generated docs/es/quickstart/page.md

  ◇ Installing dependencies...
  ◇ Starting dev server...

  └ Done! Open http://localhost:3000/docs

Flags

FlagDescription
--template <name>Bootstrap a project: next, tanstack-start, nuxt, sveltekit, or astro. Use with --name.
--name <project>Project folder name when using --template; prompt if omitted (e.g. my-docs)
--theme <name>Skip theme prompt: fumadocs, darksharp, pixel-border, colorful, darkbold, shiny, ledger, greentree, concrete, command-grid, hardline
--entry <path>Skip entry path prompt (e.g. --entry docs)

Starting from scratch? Use --template with --name <project>. The CLI bootstraps a project with the given name, installs dependencies, and then you run cd <project> && pnpm run dev to start.

Manual Code

Here is every file the CLI generates, ready to copy-paste if you prefer manual setup.

Theme CSS in global styles

For each framework, add your theme's CSS to the global stylesheet (or config) shown below. The import must match the theme you use in docs.config (e.g. default, greentree, darksharp). Without it, docs pages will lack the correct styling.

Rename to docs.config.ts when using JSX

If your config includes JSX or React nodes, rename docs.config.ts to docs.config.ts. This applies when you add things like a custom nav.title, React icons, or React-based components directly in the config file.

docs.config.ts

docs.config.ts
import { defineDocs } from "@farming-labs/docs";
import { fumadocs } from "@farming-labs/theme";

export default defineDocs({
  entry: "docs",
  theme: fumadocs(),
  nav: { title: "My Docs" },
  breadcrumb: { enabled: true },
  metadata: {
    titleTemplate: "%s – Docs",
    description: "My documentation site",
  },
});

next.config.ts

next.config.ts
import { withDocs } from "@farming-labs/next/config";
export default withDocs({});

app/global.css — add your theme's CSS here so docs styling applies.

app/global.css
@import "tailwindcss";
@import "@farming-labs/theme/default/css";

app/layout.tsx

app/layout.tsx
import { RootProvider } from "@farming-labs/theme";
import "./global.css";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <RootProvider>{children}</RootProvider>
      </body>
    </html>
  );
}

app/docs/layout.tsx

app/docs/layout.tsx
import { createDocsLayout } from "@farming-labs/theme";
import config from "@/docs.config";

const { DocsLayout } = createDocsLayout(config);

export default function Layout({
  children,
}: {
  children: React.ReactNode;
}) {
  return <DocsLayout>{children}</DocsLayout>;
}

app/docs/page.mdx (sample page)

app/docs/page.mdx
---
title: "Introduction"
description: "Welcome to the docs"
icon: "book"
---

# Welcome

This is your documentation home page.

If you chose darksharp or pixel-border, the CSS import line will differ:

  • Darksharp: @import "@farming-labs/theme/darksharp/css";
  • Pixel Border: @import "@farming-labs/theme/pixel-border/css";

docs.config.ts

docs.config.ts
import { defineDocs } from "@farming-labs/docs";
import { fumadocs } from "@farming-labs/theme";

export default defineDocs({
  entry: "docs",
  contentDir: "docs",
  theme: fumadocs(),
  nav: {
    title: "My Docs",
    url: "/docs",
  },
  breadcrumb: { enabled: true },
  metadata: {
    titleTemplate: "%s – Docs",
    description: "My documentation site",
  },
});

vite.config.ts

vite.config.ts
import { defineConfig } from "vite";
import tailwindcss from "@tailwindcss/vite";
import tsconfigPaths from "vite-tsconfig-paths";
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import { docsMdx } from "@farming-labs/tanstack-start/vite";

export default defineConfig({
  plugins: [tailwindcss(), docsMdx(), tsconfigPaths({ ignoreConfigErrors: true }), tanstackStart()],
});

src/styles/app.css — add your theme's CSS here so docs styling applies.

src/styles/app.css
@import "tailwindcss";
@import "@farming-labs/theme/default/css";

src/routes/__root.tsx

src/routes/__root.tsx
import appCss from "@/styles/app.css?url";
import { createRootRoute, HeadContent, Outlet, Scripts } from "@tanstack/react-router";
import { RootProvider } from "@farming-labs/theme/tanstack";

export const Route = createRootRoute({
  head: () => ({
    links: [{ rel: "stylesheet", href: appCss }],
  }),
  component: RootComponent,
});

function RootComponent() {
  return (
    <html lang="en" suppressHydrationWarning>
      <head>
        <HeadContent />
      </head>
      <body>
        <RootProvider>
          <Outlet />
        </RootProvider>
        <Scripts />
      </body>
    </html>
  );
}

src/lib/docs.server.ts

src/lib/docs.server.ts
import { createDocsServer } from "@farming-labs/tanstack-start/server";
import docsConfig from "../../docs.config";

export const docsServer = createDocsServer({
  ...docsConfig,
  rootDir: process.cwd(),
});

src/routes/docs/index.tsx

src/routes/docs/index.tsx
import { createFileRoute } from "@tanstack/react-router";
import { TanstackDocsPage } from "@farming-labs/tanstack-start/react";
import { loadDocPage } from "@/lib/docs.functions";
import docsConfig from "../../../docs.config";

export const Route = createFileRoute("/docs/")({
  loader: () => loadDocPage({ data: { pathname: "/docs" } }),
  component: () => <TanstackDocsPage config={docsConfig} data={Route.useLoaderData()} />,
});

TanStack Start uses the same @farming-labs/theme theme package as Next.js. Keep the theme name in docs.config.ts and src/styles/app.css aligned.

src/lib/docs.config.ts

src/lib/docs.config.ts
import { defineDocs } from "@farming-labs/docs";
import { fumadocs } from "@farming-labs/svelte-theme";

export default defineDocs({
  entry: "docs",
  contentDir: "docs",
  theme: fumadocs(),
  nav: {
    title: "My Docs",
    url: "/docs",
  },
  breadcrumb: { enabled: true },
  metadata: {
    titleTemplate: "%s – Docs",
    description: "My documentation site",
  },
});

src/lib/docs.server.ts

src/lib/docs.server.ts
import { createDocsServer } from "@farming-labs/svelte/server";
import config from "./docs.config";

// preloading for production
const contentFiles = import.meta.glob(
  ["/docs/**/*.{md,mdx,svx}", "/AGENTS.md", "/AGENT.md", "/skill.md", "/.farming-labs/sitemap-manifest.json"],
  {
    query: "?raw",
    import: "default",
    eager: true,
  },
) as Record<string, string>;

export const { load, GET, POST } = createDocsServer({
  ...config,
  _preloadedContent: contentFiles,
});

src/routes/docs/+layout.svelte

src/routes/docs/+layout.svelte
<script>
  import { DocsLayout } from "@farming-labs/svelte-theme";
  import config from "../../lib/docs.config";

  let { data, children } = $props();
</script>

<DocsLayout tree={data.tree} {config}>
  {@render children()}
</DocsLayout>

src/routes/docs/+layout.server.js

src/routes/docs/+layout.server.js
export { load } from "../../lib/docs.server";

src/routes/docs/[...slug]/+page.svelte

src/routes/docs/[...slug]/+page.svelte
<script>
  import { DocsContent } from "@farming-labs/svelte-theme";
  import config from "../../../lib/docs.config";

  let { data } = $props();
</script>

<DocsContent {data} {config} />

src/routes/api/docs/+server.js (search & AI)

src/routes/api/docs/+server.js
export { GET, POST } from "../../../lib/docs.server";

src/app.css — add your theme's CSS here so docs styling applies.

src/app.css
@import "@farming-labs/svelte-theme/fumadocs/css";

docs/page.md (sample page)

docs/page.md
---
title: "Introduction"
description: "Welcome to the docs"
icon: "book"
---

# Welcome

This is your documentation home page.

If you chose darksharp or pixel-border, swap the theme factory and CSS:

  • Darksharp: import { darksharp } from "@farming-labs/svelte-theme" + @import "@farming-labs/svelte-theme/darksharp/css";
  • Pixel Border: import { pixelBorder } from "@farming-labs/svelte-theme" + @import "@farming-labs/svelte-theme/pixel-border/css";

src/lib/docs.config.ts

src/lib/docs.config.ts
import { defineDocs } from "@farming-labs/docs";
import { fumadocs } from "@farming-labs/astro-theme";

export default defineDocs({
  entry: "docs",
  contentDir: "docs",
  theme: fumadocs(),
  nav: {
    title: "My Docs",
    url: "/docs",
  },
  breadcrumb: { enabled: true },
  metadata: {
    titleTemplate: "%s – Docs",
    description: "My documentation site",
  },
});

src/lib/docs.server.ts

src/lib/docs.server.ts
import { createDocsServer } from "@farming-labs/astro/server";
import config from "./docs.config";

const contentFiles = import.meta.glob(
  ["/docs/**/*.{md,mdx}", "/AGENTS.md", "/AGENT.md", "/skill.md", "/.farming-labs/sitemap-manifest.json"],
  {
    query: "?raw",
    import: "default",
    eager: true,
  },
) as Record<string, string>;

export const { load, GET, POST } = createDocsServer({
  ...config,
  _preloadedContent: contentFiles,
});

src/pages/docs/index.astro and src/pages/docs/[...slug].astro — import your theme's CSS in each (e.g. @farming-labs/astro-theme/css for default; use greentree/css etc. for other themes).

src/pages/docs/[...slug].astro
---
import DocsLayout from "@farming-labs/astro-theme/src/components/DocsLayout.astro";
import DocsContent from "@farming-labs/astro-theme/src/components/DocsContent.astro";
import config from "../../lib/docs.config";
import { load } from "../../lib/docs.server";
import "@farming-labs/astro-theme/css";

const data = await load(Astro.url.pathname);
---

<html lang="en">
  <head><title>{data.title} – Docs</title></head>
  <body>
    <DocsLayout tree={data.tree} config={config}>
      <DocsContent data={data} config={config} />
    </DocsLayout>
  </body>
</html>

src/pages/api/docs.ts (search & AI)

src/pages/api/docs.ts
import type { APIRoute } from "astro";
import { GET as docsGET, POST as docsPOST } from "../../lib/docs.server";

export const GET: APIRoute = async ({ request }) => docsGET({ request });
export const POST: APIRoute = async ({ request }) => docsPOST({ request });

astro.config.mjs

astro.config.mjs
import { defineConfig } from "astro/config";
export default defineConfig({ output: "server" });

docs/page.md (sample page)

docs/page.md
---
title: "Introduction"
description: "Welcome to the docs"
icon: "book"
---

# Welcome

This is your documentation home page.

If you chose darksharp or pixel-border, swap the theme factory and CSS:

  • Darksharp: import { darksharp } from "@farming-labs/astro-theme" + @farming-labs/astro-theme/darksharp/css
  • Pixel Border: import { pixelBorder } from "@farming-labs/astro-theme" + @farming-labs/astro-theme/pixel-border/css

docs.config.ts

docs.config.ts
import { defineDocs } from "@farming-labs/docs";
import { fumadocs } from "@farming-labs/nuxt-theme/fumadocs";

export default defineDocs({
  entry: "docs",
  contentDir: "docs",
  theme: fumadocs(),
  nav: {
    title: "My Docs",
    url: "/docs",
  },
  breadcrumb: { enabled: true },
  metadata: {
    titleTemplate: "%s – Docs",
    description: "My documentation site",
  },
});

nuxt.config.ts — add your theme's CSS in the css array so docs styling applies.

nuxt.config.ts
export default defineNuxtConfig({
  css: ["@farming-labs/nuxt-theme/fumadocs/css"],
  nitro: {
    serverAssets: [{ baseName: "docs", dir: "../docs" }],
  },
});

server/api/docs.ts (search, AI, and page loading) and server/middleware/docs-public.ts (public agent/GEO aliases)

pages/docs/[...slug].vue

pages/docs/[...slug].vue
<script setup lang="ts">
import { DocsLayout, DocsContent } from "@farming-labs/nuxt-theme";
import config from "~/docs.config";
const route = useRoute();
const pathname = computed(() => route.path);
const { data } = await useFetch("/api/docs", {
  query: { pathname }, watch: [pathname],
});
</script>
<template>
  <DocsLayout :tree="data.tree" :config="config">
    <DocsContent :data="data" :config="config" />
  </DocsLayout>
</template>

docs/page.md (sample page)

docs/page.md
---
title: "Introduction"
description: "Welcome to the docs"
icon: "book"
---

# Welcome

This is your documentation home page.

If you chose darksharp or pixel-border, swap the theme factory and CSS:

  • Darksharp: import { darksharp } from "@farming-labs/nuxt-theme" + @farming-labs/nuxt-theme/darksharp/css
  • Pixel Border: import { pixelBorder } from "@farming-labs/nuxt-theme" + @farming-labs/nuxt-theme/pixel-border/css

Project Structure

After running init, your project will look like this:

my-app/
├── docs.config.ts        # Docs configuration
├── next.config.ts        # Next.js config with withDocs()
├── app/
│   ├── global.css        # Theme CSS import
│   ├── layout.tsx        # Root layout
│   └── docs/
│       ├── layout.tsx    # Docs layout
│       ├── page.mdx      # /docs
│       ├── installation/
│       │   └── page.mdx  # /docs/installation
│       └── quickstart/
│           └── page.mdx  # /docs/quickstart
└── package.json
tanstack-start-project-structure.txt
my-app/
├── docs.config.ts             # Docs configuration
├── docs/                      # Markdown content
│   ├── page.mdx               # /docs
│   ├── installation/
│   │   └── page.mdx           # /docs/installation
│   └── quickstart/
│       └── page.mdx           # /docs/quickstart
├── src/
│   ├── lib/
│   │   ├── docs.functions.ts  # Server function wrapper
│   │   └── docs.server.ts     # Docs server
│   ├── routes/
│   │   ├── __root.tsx         # Root layout with RootProvider
│   │   ├── $.ts               # Public docs aliases
│   │   ├── api/
│   │   │   └── docs.ts        # Search & AI API route
│   │   └── docs/
│   │       ├── $.tsx          # Dynamic page
│   │       └── index.tsx      # /docs
│   └── styles/
│       └── app.css            # Theme CSS import
├── vite.config.ts             # docsMdx() + TanStack Start plugin
└── package.json
sveltekit-project-structure.txt
my-app/
├── docs/                     # Markdown content
│   ├── page.md               # /docs
│   ├── installation/
│   │   └── page.md           # /docs/installation
│   └── quickstart/
│       └── page.md           # /docs/quickstart
├── src/
│   ├── app.css               # Theme CSS import
│   ├── hooks.server.ts       # Public docs aliases
│   ├── lib/
│   │   ├── docs.config.ts    # Docs configuration
│   │   └── docs.server.ts    # Server loader + content bundling
│   └── routes/
│       ├── api/
│       │   └── docs/
│       │       └── +server.ts      # Search & AI API route
│       └── docs/
│           ├── +layout.svelte      # Docs layout
│           ├── +layout.server.js   # Layout data loader
│           └── [...slug]/
│               └── +page.svelte    # Dynamic page
└── package.json
astro-project-structure.txt
my-app/
├── astro.config.mjs          # Astro config with SSR
├── docs/                     # Markdown content
│   ├── page.md               # /docs
│   ├── installation/
│   │   └── page.md           # /docs/installation
│   └── quickstart/
│       └── page.md           # /docs/quickstart
├── src/
│   ├── lib/
│   │   ├── docs.config.ts    # Docs configuration
│   │   └── docs.server.ts    # Server loader + content bundling
│   ├── middleware.ts         # Public docs aliases
│   └── pages/
│       ├── api/
│       │   └── docs.ts       # Search & AI API route
│       └── docs/
│           ├── index.astro   # /docs
│           └── [...slug].astro  # /docs/*
└── package.json
nuxt-project-structure.txt
my-app/
├── docs.config.ts            # Docs configuration
├── nuxt.config.ts            # Nuxt config with theme CSS
├── docs/                     # Markdown content
│   ├── page.md               # /docs
│   ├── installation/
│   │   └── page.md           # /docs/installation
│   └── quickstart/
│       └── page.md           # /docs/quickstart
├── server/
│   ├── api/
│   │   └── docs.ts           # Search & AI API route
│   └── middleware/
│       └── docs-public.ts    # Public docs aliases
├── pages/
│   └── docs/
│       └── [...slug].vue     # Dynamic page
└── package.json