AI-native, agent-optimized docs with Ask AI, MCP, llms.txt, search adapters, and zero boilerplate.
Keep your docs source simple, then layer in Ask AI, MCP delivery, llms.txt, and index-backed search without leaving the same runtime.
# Human + agent ready
Write Markdown and MDX that stays clean for humans while remaining structured enough for AI tools and agents to read, cite, and update confidently.
# Retrieval layer
Mix built-in Ask AI with search adapters for simple, Typesense, Algolia, MCP, or custom retrieval so you can keep the indexing flow that fits your stack.
# Agent optimized
Ship docs to IDEs, agents, and humans from the same source with MCP, llms.txt, API reference, changelogs, and a docs runtime that stays open and portable.
Run a public readiness check for llms.txt, markdown routes, OpenAPI discovery, MCP, sitemap, robots, structure, access, and cache hygiene, then compare your docs on the leaderboard.
Easily scaffold your docs with the CLI. It auto-detects your framework and scaffolds everything.
Setup beautiful documentation in seconds
Add the core packages to your Next.js project.
pnpm add @farming-labs/docs @farming-labs/theme @farming-labs/nextOne file. Theme, metadata, components, icons — everything.
import { defineDocs } from "@farming-labs/docs";
import { pixelBorder } from "@farming-labs/theme/pixel-border";
export default defineDocs({
entry: "docs",
theme: pixelBorder(),
metadata: {
titleTemplate: "%s – My Docs",
},
});Wrap your config with withDocs(). Handles MDX, routing, and search.
import { withDocs } from "@farming-labs/next/config";
export default withDocs({});Wrap your app with RootProvider for search, theme switching, and AI.
import { RootProvider } from "@farming-labs/theme";
import "./global.css";
export default function RootLayout({ children }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<RootProvider>{children}</RootProvider>
</body>
</html>
);
}In app/global.css, import your theme's CSS so docs styling applies (e.g. @import "@farming-labs/theme/default/css"; — use the path that matches your theme).
Create MDX files under app/docs/. Frontmatter for metadata. That's it.
---
title: "Getting Started"
description: "Set up in 5 minutes"
icon: "rocket"
---
# Getting Started
Write your content in **MDX** with
frontmatter for metadata.
```ts title="auth.ts"
export const auth = betterAuth({
database: { provider: "postgresql" },
});
```See the full installation walkthrough for all generated files and options.
Add the core packages to your SvelteKit project.
pnpm add @farming-labs/docs @farming-labs/svelte @farming-labs/svelte-themeOne config file. Theme, metadata, navigation — everything.
import { defineDocs } from "@farming-labs/docs";
import { fumadocs } from "@farming-labs/svelte-theme";
export default defineDocs({
entry: "docs",
contentDir: "docs",
theme: fumadocs(),
metadata: {
titleTemplate: "%s – My Docs",
},
});Create the server helper. Handles loading, search, and AI.
import { createDocsServer } from "@farming-labs/svelte/server";
import config from "./docs.config";
export const { load, GET, POST } = createDocsServer(config);Create Markdown files under docs/. That's it.
---
title: "Getting Started"
description: "Set up in 5 minutes"
icon: "rocket"
---
# Getting Started
Write your content in **Markdown** with
frontmatter for metadata.
```ts title="auth.ts"
export const auth = betterAuth({
database: { provider: "postgresql" },
});
```Three small files for layout, server loader, and page.
<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>Add the core packages to your Astro project.
pnpm add @farming-labs/docs @farming-labs/astro @farming-labs/astro-themeOne config file. Theme, metadata, navigation — everything.
import { defineDocs } from "@farming-labs/docs";
import { fumadocs } from "@farming-labs/astro-theme";
export default defineDocs({
entry: "docs",
contentDir: "docs",
theme: fumadocs(),
metadata: {
titleTemplate: "%s – My Docs",
},
});Create the server helper. Handles loading, search, and AI.
import { createDocsServer } from "@farming-labs/astro/server";
import config from "./docs.config";
export const { load, GET, POST } = createDocsServer(config);Create Markdown files under docs/. That's it.
---
title: "Getting Started"
description: "Set up in 5 minutes"
icon: "rocket"
---
# Getting Started
Write your content in **Markdown** with
frontmatter for metadata.
```ts title="auth.ts"
export const auth = betterAuth({
database: { provider: "postgresql" },
});
```Index page, catch-all route, and API endpoint.
---
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>Add the core packages to your Nuxt project.
pnpm add @farming-labs/docs @farming-labs/nuxt @farming-labs/nuxt-themeOne config file. Theme, metadata, navigation — everything.
import { defineDocs } from "@farming-labs/docs";
import { fumadocs } from "@farming-labs/nuxt-theme/fumadocs";
export default defineDocs({
entry: "docs",
contentDir: "docs",
theme: fumadocs(),
metadata: {
titleTemplate: "%s – My Docs",
},
});Import the theme CSS and configure Nitro server assets.
export default defineNuxtConfig({
css: ["@farming-labs/nuxt-theme/fumadocs/css"],
nitro: {
serverAssets: [
{ baseName: "docs", dir: "../docs" },
],
},
});One handler for docs loading, search, and AI.
import { defineDocsHandler } from "@farming-labs/nuxt/server";
import config from "../../docs.config";
export default defineDocsHandler(config, useStorage);Create Markdown files under docs/. That's it.
---
title: "Getting Started"
description: "Set up in 5 minutes"
icon: "rocket"
---
# Getting Started
Write your content in **Markdown** with
frontmatter for metadata.
```ts title="auth.ts"
export const auth = betterAuth({
database: { provider: "postgresql" },
});
```A single Vue page that handles all doc routes.
<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>Pick a preset or build your own with createTheme(). Override any styles from config.
Clean, neutral palette with standard border radius
@import "@farming-labs/theme/default/css";All-black, sharp corners, no rounded edges
@import "@farming-labs/theme/darksharp/css";Inspired by better-auth.com — refined dark UI
@import "@farming-labs/theme/pixel-border/css";Faithful clone of the fumadocs default neutral theme
@import "@farming-labs/theme/colorful/css";Clerk docs-inspired — clean, polished purple accents
@import "@farming-labs/theme/shiny/css";Stripe Docs-inspired product docs shell with navy code panels
@import "@farming-labs/theme/ledger/css";Pure monochrome design — clean, bold, minimal
@import "@farming-labs/theme/darkbold/css";Mintlify-inspired — emerald green, Inter font, modern
@import "@farming-labs/theme/greentree/css";Original hard-edge preset with square corners and strong borders
@import "@farming-labs/theme/hardline/css";Louder brutalist variant with offset shadows and poster-style contrast
@import "@farming-labs/theme/concrete/css";Mono-first paper-grid preset inspired by the better-cmdk landing page
@import "@farming-labs/theme/command-grid/css";theme: pixelBorder({
ui: {
colors: {
primary: "oklch(0.72 0.19 149)", // green
accent: "hsl(220 80% 60%)", // blue
},
},
}),import { defineDocs } from "@farming-labs/docs";
import { pixelBorder } from "@farming-labs/theme/pixel-border";
import { Rocket, BookOpen, Code } from "lucide-react";
export default defineDocs({
entry: "docs",
theme: pixelBorder({
ui: {
colors: { primary: "oklch(0.72 0.19 149)" },
typography: {
font: {
h1: { size: "2.25rem", weight: 700 },
body: { size: "0.975rem", lineHeight: "1.8" },
},
},
},
}),
nav: {
title: <div style={{ display: "flex", gap: 8 }}>
<Rocket size={14} /> My Docs
</div>,
},
icons: {
rocket: <Rocket size={16} />,
book: <BookOpen size={16} />,
code: <Code size={16} />,
},
sidebar: {
banner: (
<div>
<h2>Welcome to the docs</h2>
<p>This is a banner</p>
</div>
),
flat: false,
collapsible: true,
footer: (
<div>
<p>This is a footer</p>
</div>
),
},
components: { MyCustomCallout },
breadcrumb: { enabled: true },
themeToggle: { enabled: false, default: "dark" },
ai: {
enabled: true,
mode: "floating",
floatingStyle: "full-modal",
apiKey: process.env.OPENAI_API_KEY,
maxResults: 5,
aiLabel: "DocsBot",
suggestedQuestions: [
"How do I get started?",
"What themes are available?",
"How do I create a custom component?",
"How do I configure the sidebar?",
],
model: {
models: [
{ id: "gpt-4o-mini", label: "GPT-4o mini (fast)" },
{ id: "gpt-4o", label: "GPT-4o (quality)" },
],
defaultModel: "gpt-4o-mini",
},
},
pageActions: {
copyMarkdown: { enabled: true },
openDocs: {
enabled: true,
providers: [
{ name: "ChatGPT", urlTemplate: "https://chatgpt.com/?q={url}" },
],
},
},
metadata: {
titleTemplate: "%s – Docs",
description: "My documentation site",
},
});