Why I Built @farming-labs/docs for the AI Era
108 reads.
This is the reasoning behind docs.farming-labs.dev: why I made it, why it fits this AI moment, and why I wanted docs to work for humans, IDEs, agents, MCP clients, and search systems without becoming another rigid docs generator.
There are already a lot of documentation tools.
So when I started building docs.farming-labs.dev, the goal was not to make "yet another docs site." The goal was to build a docs framework that feels small, practical, and easy to adapt to real products.
The bigger idea is that docs are no longer only a website. They are also product context. They are what a teammate reads, what an implementation agent fetches, what search indexes, what an IDE assistant uses to make changes safely, and what a support workflow can point people toward.
Why I Built It
Most docs tools push you into one of two extremes:
- polished, but too rigid
- flexible, but full of wiring and boilerplate
I wanted something in the middle: MDX-based, good-looking by default, but still simple enough to understand quickly. Docs should not feel like a second app you have to maintain just to publish a page.
That is why the project keeps the real setup surface centered around one config file and supports multiple frameworks instead of trapping you inside one stack. The docs should be easy to start, easy to theme, easy to index, and easy for agents to consume directly.
Why It Fits The AI Era
Today docs are not only read by humans. They are also read by AI tools, agents, copilots, search systems, and retrieval pipelines.
That changes the design goal.
In this AI era, boilerplate is not just ugly, it is expensive. Every extra wrapper or config layer becomes more context for a model to read before it can reach the actual documentation.
So one of the main ideas behind docs.farming-labs.dev is simple:
keep the framework surface small so humans and AI can understand the project faster.
That is why the project leans on:
- one
docs.config.tsas the main control surface - minimal generated files
- built-in
llms.txtsupport - page-level markdown routes for machine-readable docs
- built-in MCP server support
- hidden
Agentblocks and page-localagent.mdoverrides - built-in AI chat instead of bolted-on integrations
- agent feedback endpoints so automated workflows can report useful context back
Getting Started And Working With It
Getting started should feel boring:
npx @farming-labs/docs init
The CLI detects the framework, lets you choose a theme, scaffolds the minimal files, installs dependencies, and gets the dev server running. If you are starting fresh, it can scaffold a new project too.
It can also help with the parts that normally make docs annoying later: i18n folders, generated API reference setup, framework route files, theme CSS, and the minimal config needed to keep everything readable.
The day-to-day workflow stays close to content:
- write Markdown or MDX
- keep docs in a
docsdirectory - control the site from
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', url: '/docs' },
metadata: {
titleTemplate: '%s - Docs',
description: 'My documentation site',
},
})
That is the kind of ergonomics I wanted: small enough to read in one glance, but strong enough to run a real docs site.
For agent workflows, the same package can also run the built-in MCP server locally:
npx @farming-labs/docs mcp
That means a local assistant or IDE agent can query the docs through tools like list_pages, get_navigation, search_docs, and read_page instead of scraping the rendered website.
Why Customization Matters
I did not want "easy to use" to mean "hard to customize."
The project is designed so the important parts are open:
- themes, colors, typography
- sidebar behavior and components
- page actions
- AI chat
llms.txt- OG images
- search providers
- generated API reference
- changelog pages
- human and agent feedback
Creating a theme is intentionally simple:
import { createTheme } from '@farming-labs/docs'
export const myTheme = createTheme({
name: 'my-theme',
ui: {
colors: {
primary: '#e11d48',
background: '#09090b',
muted: '#71717a',
border: '#27272a',
},
},
})
And if you want to start from an existing preset instead of from zero:
import { extendTheme } from '@farming-labs/docs'
import { fumadocs } from '@farming-labs/theme'
export const myTheme = extendTheme(fumadocs(), {
name: 'my-fumadocs-variant',
ui: {
colors: { primary: '#22c55e', background: '#0c0c0c' },
sidebar: { style: 'bordered' },
},
})
That part matters because good themes should be reusable. A team can publish a theme as an npm package, reuse it across projects, and effectively build its own theme registry or shared preset system instead of copying styles from app to app.
That sharing model was important to me. A good docs theme should not be trapped inside one repo. It should be something you can install, version, improve, and roll out across multiple products the same way you would handle any other shared design system package.
The built-in themes also give teams somewhere useful to start. You can use presets like fumadocs, darksharp, pixel-border, colorful, greentree, darkbold, shiny, concrete, command-grid, or hardline, then extend only the pieces you care about. The goal is not to make every docs site look the same. The goal is to make custom docs cheaper to build and easier to share.
What Changed Since The First Version
The project has grown into more than a docs renderer.
There is generated API reference support from framework route handlers or a hosted OpenAPI JSON file. There are built-in changelog pages for Next.js, so product updates can live in the same docs system. There are search adapters for simple built-in search, Typesense, Algolia, MCP-backed search, and custom indexing. There are built-in MDX components like Callout, Tabs, HoverLink, and hidden Agent blocks.
There are also page actions and feedback surfaces that make docs more useful outside the page itself. Users can copy markdown, open docs in an LLM, leave human feedback, and agents can submit structured feedback through machine-readable endpoints.
That is the part I care about: docs should not be a static brochure. They should be a working interface between the product, the reader, the team, and the tools around them.
AI, Agentic Features, And OG Support
The AI features are there because they belong there.
AI chat can be enabled with a very small config surface:
ai: {
enabled: true,
model: "gpt-4o-mini",
}
But it goes beyond a single model call. The chat can live inside search or as a floating UI, can use one model or multiple selectable models, and can route different models through different OpenAI-compatible providers.
Around that, there are other AI-friendly features too:
llms.txtandllms-full.txtoutput- page actions like "Copy Markdown" and "Open in..."
- token-efficient config that agents can read quickly
- machine-readable
.mdroutes like/docs/quickstart.md Accept: text/markdownsupport on normal docs URLs- hidden
Agentblocks for machine-only instructions agent.mdfiles when a page needs a focused agent-specific version- an agent spec route at
/api/docs/agent/spec - agent feedback schema and submit routes
- built-in MCP support through
/api/docs/mcpandnpx @farming-labs/docs mcp - installable Agent Skills for setup, CLI usage, theme creation, Ask AI, page actions, and configuration
That combination matters more than any one feature by itself. I wanted the docs to work well for people reading normally, for people sharing pages into AI tools, and for systems that need a structured way to consume the content.
The important detail is that the agentic layer is not just "add chat to the docs." It is a whole set of surfaces:
- humans get polished pages
- search gets normalized chunks
- LLMs get
llms.txt - agents get markdown routes,
Agentblocks,agent.md, MCP tools, and an agent spec - teams get feedback endpoints so automation can report what worked or failed
That makes the docs easier to use in Cursor, Copilot-style workflows, local MCP clients, internal support tools, and retrieval systems without forcing every team to invent the same glue code again.
And docs also need strong OG image support. Shared docs links should look good, not broken or generic.
That is why the framework supports both:
- dynamic OG images through an endpoint like
/api/og - static per-page OG images from frontmatter when a page needs a custom image
That mix matters. Most docs sites need a clean default OG system for the whole site, but they also need the option to override important pages with a better static image.
For me, that is one of those details that makes docs feel more complete. A docs page is not only something people read on-site. It is something they paste into Slack, X, Discord, and issue threads. Better OG support makes the docs feel more intentional everywhere else too.
Why Multi-Framework Support Still Matters
I also did not want this to only make sense for one ecosystem.
Teams already have strong preferences around Next.js, TanStack Start, SvelteKit, Astro, and Nuxt. Good docs infrastructure should meet them where they already are instead of asking them to switch frameworks just to get a better docs experience.
So part of the idea here was to keep the authoring model and config model consistent, while adapting the integration details to each framework.
Final Thought
I created docs.farming-labs.dev because I think documentation is becoming more central, not less.
In the AI era, docs are part of onboarding, search, retrieval, and product experience. So I wanted a docs framework that stays simple, looks polished, feels customizable, and works well for both humans and AI.
If that sounds like the workflow you want, the easiest way to start is still:
npx @farming-labs/docs init