CLI
The @farming-labs/docs CLI has two main jobs:
init— create a new docs app or add docs to an existing appupgrade— bump the docs packages in an existing project
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.
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-docspnpm 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-docsyarn 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-docsbunx @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-docsThis 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.
npx @farming-labs/docs initpnpm dlx @farming-labs/docs inityarn dlx @farming-labs/docs initbunx @farming-labs/docs initRun that from your app root. The CLI will:
- detect your framework from
package.jsonor ask you to choose - ask for a theme
- ask where docs should live, usually
docs - ask about aliases, global CSS, and optional i18n when supported
- 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.
npx @farming-labs/docs upgradepnpm dlx @farming-labs/docs upgradeyarn dlx @farming-labs/docs upgradebunx @farming-labs/docs upgradeBy default, the CLI detects your framework and package manager from the current project. If detection is ambiguous, pass --framework.
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.
| Choice | Best for | What happens |
|---|---|---|
Existing project | You already have a Next.js, TanStack Start, Nuxt, SvelteKit, or Astro app | The CLI adds docs to the current app |
Fresh project | You want a new docs starter | The CLI creates a new folder from the selected example template |
From scratch
If you select Fresh project, the CLI asks for:
- Framework — Next.js, TanStack Start, Nuxt, SvelteKit, or Astro
- Project name — default is
my-docs - Package manager — used for install and the suggested dev command
You can skip those prompts entirely with --template and --name.
npx @farming-labs/docs init --template next --name my-docspnpm dlx @farming-labs/docs init --template next --name my-docsyarn dlx @farming-labs/docs init --template next --name my-docsbunx @farming-labs/docs init --template next --name my-docsReplace 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.
- Framework — Auto-detected from
package.json, or you pick one if detection fails. - Theme — One of the built-in themes or Create your own theme (you’ll be asked for a theme name; it creates
themes/<name>.tsandthemes/<name>.css). - Path aliases — Whether to use
@/,$lib/, or~/for imports (framework-dependent). - Entry path — Where docs live (e.g.
docs). Press Enter to use the default. - 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 writingapiReference.routeRoot. - Optional i18n — Whether to scaffold internationalized docs, which locales to generate, any extra locale codes to add, and which locale should be the default.
- Global CSS — Which file to use (auto-detected if there’s only one, otherwise you pick or type the path; Enter uses the default).
- 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:
cd my-app
npx @farming-labs/docs initcd my-app
pnpm dlx @farming-labs/docs initcd my-app
yarn dlx @farming-labs/docs initcd my-app
bunx @farming-labs/docs initPrompts 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:
| Flag | Description |
|---|---|
--theme <name> | Skip the theme prompt |
--entry <path> | Skip the docs entry prompt |
--api-reference | Enable API reference scaffold during init |
--no-api-reference | Explicitly skip API reference scaffold |
--api-route-root <path> | Set the detected API route root written to apiReference.routeRoot |
Example:
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:
- Next.js writes the
apiReferenceblock andapp/api-reference/[[...slug]]/route.ts(orsrc/app/...). - TanStack Start, SvelteKit, Astro, and Nuxt write the
apiReferenceblock and also scaffold the minimal/{path}handler files so the reference works immediately.
Optional i18n scaffold
If you enable i18n during init, the CLI will:
- Let you multi-select common locales such as
en,fr,es,de,pt,ja,ko,zh,ar,hi, andru - Let you add custom locale codes such as
pt-BR - Ask which locale should be the default
The generated project gets:
- An
i18nblock indocs.config.ts/src/lib/docs.config.ts - Locale content folders like
docs/en,docs/fr, anddocs/zh - Framework-specific starter files so routes like
/docs?lang=enand/docs?lang=frwork out of the box
Upgrade
Upgrade all @farming-labs/* docs packages to the latest 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.
npx @farming-labs/docs upgradepnpm dlx @farming-labs/docs upgradeyarn dlx @farming-labs/docs upgradebunx @farming-labs/docs upgrade| Framework | Packages upgraded to @latest |
|---|---|
| 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:
npx @farming-labs/docs upgrade --framework tanstack-start
# or
npx @farming-labs/docs upgrade tanstack-startpnpm dlx @farming-labs/docs upgrade --framework tanstack-start
# or
pnpm dlx @farming-labs/docs upgrade tanstack-startyarn dlx @farming-labs/docs upgrade --framework tanstack-start
# or
yarn dlx @farming-labs/docs upgrade tanstack-startbunx @farming-labs/docs upgrade --framework tanstack-start
# or
bunx @farming-labs/docs upgrade tanstack-startValid values: next, tanstack-start, nuxt, sveltekit, astro.
Use --latest (default) to install the latest stable release, or --beta to install beta versions:
npx @farming-labs/docs upgrade # latest stable (default)
npx @farming-labs/docs upgrade --latest # same
npx @farming-labs/docs upgrade --beta # beta versionspnpm dlx @farming-labs/docs upgrade # latest stable (default)
pnpm dlx @farming-labs/docs upgrade --latest # same
pnpm dlx @farming-labs/docs upgrade --beta # beta versionsyarn dlx @farming-labs/docs upgrade # latest stable (default)
yarn dlx @farming-labs/docs upgrade --latest # same
yarn dlx @farming-labs/docs upgrade --beta # beta versionsbunx @farming-labs/docs upgrade # latest stable (default)
bunx @farming-labs/docs upgrade --latest # same
bunx @farming-labs/docs upgrade --beta # beta versionsSupported Frameworks
| Framework | Detection | init | upgrade |
|---|---|---|---|
| Next.js | next in dependencies | Supported | Supported |
| TanStack Start | @tanstack/react-start in dependencies | Supported | Supported |
| SvelteKit | @sveltejs/kit in dependencies | Supported | Supported |
| Astro | astro in dependencies | Supported | Supported |
| Nuxt | nuxt in dependencies | Supported | Supported |
Available Themes
The init CLI offers several built-in themes plus an option to create your own:
| Theme | Description |
|---|---|
fumadocs | Clean, neutral docs theme (default) |
darksharp | All-black, sharp corners, no rounded edges |
pixel-border | Refined dark UI inspired by better-auth.com |
colorful | Fumadocs-style neutral theme with description support |
greentree | Emerald green accent, Inter font, Mintlify-inspired |
hardline | Hard-edge theme with square corners and bold borders |
concrete | Brutalist poster-style theme with offset shadows |
darkbold | Pure monochrome, Geist typography, clean minimalism |
shiny | Glossy, modern look with subtle shimmer effects |
| Create your own theme | Scaffolds 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):
- Detects Next.js via
nextin yourpackage.json(or asks you to pick a framework) - Asks for a theme — built-in themes or Create your own theme (then prompts for theme name; press Enter for default
my-theme) - Asks for the entry path — Default is
docs(press Enter to accept) - Asks about path aliases — Use
@/alias or relative paths for imports - Optionally scaffolds i18n — Generates locale folders like
app/docs/enandapp/docs/fr, plus locale-aware wrapper pages - Generates files:
docs.config.ts— Full config with your selected themenext.config.ts— Wraps your existing config withwithDocs()app/global.css— Imports Tailwind and theme CSSapp/layout.tsx— Root layout with RootProviderapp/docs/layout.tsx— Docs layoutapp/docs/page.mdx— Sample documentation page when i18n is disabledapp/docs/installation/page.mdx— Sample installation guide when i18n is disabledapp/docs/quickstart/page.mdx— Sample quickstart guide when i18n is disabled
- Installs dependencies —
@farming-labs/docs,@farming-labs/theme,@farming-labs/next - Starts the dev server — Opens your docs at
http://localhost:3000/docs
- Detects TanStack Start via
@tanstack/react-startin yourpackage.json(or asks you to pick a framework) - Asks for a theme — built-in themes or Create your own theme (then prompts for theme name; press Enter for default
my-theme) - Asks about path aliases — Use
@/alias or relative paths for imports - Asks for the entry path — Default is
docs(press Enter to accept) - Skips the built-in i18n scaffold so the generated TanStack routes stay minimal and working
- Generates files:
docs.config.ts— Full config with your selected themesrc/lib/docs.server.ts— TanStack docs serversrc/lib/docs.functions.ts— Server function wrapper for page loadingsrc/routes/{entry}/index.tsx— Docs index routesrc/routes/{entry}/$.tsx— Catch-all docs routesrc/routes/api/docs.ts— Search and AI API routesrc/styles/app.css— Imports Tailwind and theme CSSdocs/page.mdx— Sample documentation pagedocs/installation/page.mdx— Sample installation guidedocs/quickstart/page.mdx— Sample quickstart guide
- Updates existing app files when needed — Injects
RootProviderintosrc/routes/__root.tsxand addsdocsMdx()/ Tailwind plugins tovite.config.ts - Installs dependencies —
@farming-labs/docs,@farming-labs/theme,@farming-labs/tanstack-start - Starts the dev server — Opens your docs at
http://localhost:5173/docs
- Detects SvelteKit via
@sveltejs/kitin yourpackage.json(or asks you to pick a framework) - Asks for a theme — built-in themes or Create your own theme (then prompts for theme name; press Enter for default)
- Asks for the entry path — Default is
docs(press Enter to accept) - Asks about path aliases — Use
$lib/alias or relative paths for imports - Optionally scaffolds i18n — Generates locale folders like
docs/enanddocs/frplus a docs root page for/docs?lang=... - Generates files (does not touch
svelte.config.js):src/lib/docs.config.ts— Full config with your selected themesrc/lib/docs.server.ts— Server-side docs loader withimport.meta.globfor production buildssrc/routes/docs/+layout.svelte— Docs layout componentsrc/routes/docs/+layout.server.js— Layout data loadersrc/routes/docs/[...slug]/+page.svelte— Dynamic page componentsrc/routes/docs/+page.svelte— Generated when i18n is enabledsrc/app.css— Theme CSS importdocs/page.md— Sample documentation pagedocs/installation/page.md— Sample installation guidedocs/quickstart/page.md— Sample quickstart guide
- Installs dependencies —
@farming-labs/docs,@farming-labs/svelte,@farming-labs/svelte-theme - Starts the dev server — Opens your docs at
http://localhost:5173/docs
Production note: The generated
docs.server.tsusesimport.meta.globto bundle your markdown files at build time. This is required for serverless deployments (Vercel, Netlify, etc.) where the filesystem is not available at runtime.
- Detects Astro via
astroin yourpackage.json(or asks you to pick a framework) - Asks for a theme — built-in themes or Create your own theme (then prompts for theme name; press Enter for default)
- Asks for the entry path — Default is
docs(press Enter to accept) - Optionally scaffolds i18n — Generates locale folders like
docs/enanddocs/fr - Generates files:
src/lib/docs.config.ts— Full config with your selected themesrc/lib/docs.server.ts— Server-side docs loader withimport.meta.globfor production buildssrc/pages/{entry}/index.astro— Docs index pagesrc/pages/{entry}/[...slug].astro— Dynamic page componentsrc/pages/api/{entry}.ts— API route for search and AIastro.config.mjs— Astro config with SSR enableddocs/page.md— Sample documentation pagedocs/installation/page.md— Sample installation guidedocs/quickstart/page.md— Sample quickstart guide
- Installs dependencies —
@farming-labs/docs,@farming-labs/astro,@farming-labs/astro-theme - Starts the dev server — Opens your docs at
http://localhost:4321/docs
Production note: The generated
docs.server.tsusesimport.meta.globto bundle your markdown files at build time. This is required for serverless deployments (Vercel, Netlify, etc.) where the filesystem is not available at runtime.
- Detects Nuxt via
nuxtin yourpackage.json(or asks you to pick a framework) - Asks for a theme — built-in themes or Create your own theme (then prompts for theme name; press Enter for default)
- Asks for the entry path — Default is
docs(press Enter to accept) - Optionally scaffolds i18n — Generates locale folders like
docs/enanddocs/fr - Generates files:
docs.config.ts— Full config with your selected themenuxt.config.ts— Nuxt config with theme CSS and server assetsserver/api/docs.get.ts,server/api/docs.post.ts,server/api/docs/load.get.ts— docs data, search, AI, and page loadingpages/docs/[[...slug]].vue— Catch-all page component that handles the docs index and nested docs routesdocs/page.md— Sample documentation pagedocs/installation/page.md— Sample installation guidedocs/quickstart/page.md— Sample quickstart guide
- Installs dependencies —
@farming-labs/docs,@farming-labs/nuxt,@farming-labs/nuxt-theme - Starts the dev server — Opens your docs at
http://localhost:3000/docs
Example Output
$ 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
│ ○ hardline
│ ○ concrete
│ ○ 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$ 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
│ ○ hardline
│ ○ concrete
│ ○ 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$ 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
│ ○ greentree
│ ○ hardline
│ ○ concrete
│ ○ darkbold
│ ○ shiny
│
◆ 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 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$ 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
│ ○ greentree
│ ○ hardline
│ ○ concrete
│ ○ darkbold
│ ○ shiny
│
◆ 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 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$ 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
│ ○ greentree
│ ○ hardline
│ ○ concrete
│ ○ darkbold
│ ○ shiny
│
◆ 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.get.ts
◇ Generated server/api/docs.post.ts
◇ Generated server/api/docs/load.get.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/docsFlags
| Flag | Description |
|---|---|
--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, greentree, hardline, concrete |
--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
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
import { withDocs } from "@farming-labs/next/config";
export default withDocs({});app/global.css — add your theme's CSS here so docs styling applies.
@import "tailwindcss";
@import "@farming-labs/theme/default/css";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
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)
---
title: "Introduction"
description: "Welcome to the docs"
icon: "book"
---
# Welcome
This is your documentation home page.If you chose
darksharporpixel-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
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
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.
@import "tailwindcss";
@import "@farming-labs/theme/default/css";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
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
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/themetheme package as Next.js. Keep the theme name indocs.config.tsandsrc/styles/app.cssaligned.
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
import { createDocsServer } from "@farming-labs/svelte/server";
import config from "./docs.config";
// preloading for production
const contentFiles = import.meta.glob("/docs/**/*.{md,mdx,svx}", {
query: "?raw",
import: "default",
eager: true,
}) as Record<string, string>;
export const { load, GET, POST } = createDocsServer({
...config,
_preloadedContent: contentFiles,
});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
export { load } from "../../lib/docs.server";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)
export { GET, POST } from "../../../lib/docs.server";src/app.css — add your theme's CSS here so docs styling applies.
@import "@farming-labs/svelte-theme/fumadocs/css";docs/page.md (sample page)
---
title: "Introduction"
description: "Welcome to the docs"
icon: "book"
---
# Welcome
This is your documentation home page.If you chose
darksharporpixel-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
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
import { createDocsServer } from "@farming-labs/astro/server";
import config from "./docs.config";
const contentFiles = import.meta.glob("/docs/**/*.{md,mdx}", {
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).
---
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)
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
import { defineConfig } from "astro/config";
export default defineConfig({ output: "server" });docs/page.md (sample page)
---
title: "Introduction"
description: "Welcome to the docs"
icon: "book"
---
# Welcome
This is your documentation home page.If you chose
darksharporpixel-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
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.
export default defineNuxtConfig({
css: ["@farming-labs/nuxt-theme/fumadocs/css"],
nitro: {
serverAssets: [{ baseName: "docs", dir: "../docs" }],
},
});server/api/docs.get.ts, server/api/docs.post.ts, and server/api/docs/load.get.ts (search, AI, and page loading)
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)
---
title: "Introduction"
description: "Welcome to the docs"
icon: "book"
---
# Welcome
This is your documentation home page.If you chose
darksharporpixel-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.jsonmy-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
│ │ ├── 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.jsonmy-app/
├── docs/ # Markdown content
│ ├── page.md # /docs
│ ├── installation/
│ │ └── page.md # /docs/installation
│ └── quickstart/
│ └── page.md # /docs/quickstart
├── src/
│ ├── app.css # Theme CSS import
│ ├── lib/
│ │ ├── docs.config.ts # Docs configuration
│ │ └── docs.server.ts # Server loader + content bundling
│ └── routes/
│ └── docs/
│ ├── +layout.svelte # Docs layout
│ ├── +layout.server.js # Layout data loader
│ └── [...slug]/
│ └── +page.svelte # Dynamic page
└── package.jsonmy-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
│ └── pages/
│ ├── api/
│ │ └── docs.ts # Search & AI API route
│ └── docs/
│ ├── index.astro # /docs
│ └── [...slug].astro # /docs/*
└── package.jsonmy-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
├── pages/
│ └── docs/
│ └── [...slug].vue # Dynamic page
└── package.jsonHow is this guide?