+
{renderedChildren}
{!generatedPageHeader && titleDecorationsFallback}
@@ -1184,6 +1191,7 @@ export function DocsPageClient({
)}
+ {devToolsEnabled &&
}
>
);
}
diff --git a/packages/fumadocs/src/greentree/index.ts b/packages/fumadocs/src/greentree/index.ts
index c47fb641d..dca5bbc23 100644
--- a/packages/fumadocs/src/greentree/index.ts
+++ b/packages/fumadocs/src/greentree/index.ts
@@ -37,7 +37,6 @@ const GreenTreeUIDefaults = {
Callout: { variant: "soft", icon: true },
CodeBlock: { showCopyButton: true },
HoverLink: { linkLabel: "Open page", showIndicator: false },
- Tabs: { style: "default" },
},
};
diff --git a/packages/fumadocs/src/hardline/index.ts b/packages/fumadocs/src/hardline/index.ts
index fb51a7f78..7d8ec9897 100644
--- a/packages/fumadocs/src/hardline/index.ts
+++ b/packages/fumadocs/src/hardline/index.ts
@@ -41,7 +41,6 @@ const HardlineUIDefaults = {
Callout: { variant: "outline", icon: true },
CodeBlock: { showCopyButton: true },
HoverLink: { linkLabel: "Open page", showIndicator: true },
- Tabs: { style: "underline" as const },
},
};
diff --git a/packages/fumadocs/src/index.ts b/packages/fumadocs/src/index.ts
index 600082185..38ce01b91 100644
--- a/packages/fumadocs/src/index.ts
+++ b/packages/fumadocs/src/index.ts
@@ -89,6 +89,7 @@ export { DocsLayout } from "fumadocs-ui/layouts/docs";
export { DocsPageClient } from "./docs-page-client.js";
export { DocsClientHooks } from "./docs-client-hooks.js";
export { DocsFeedback } from "./docs-feedback.js";
+export { DocsDevTools } from "./devtools.js";
// ─── Page action buttons (Copy Markdown, Open in LLM) ─────────────────
export { PageActions } from "./page-actions.js";
@@ -109,6 +110,7 @@ export type {
TypographyConfig,
DocsNav,
DocsMetadata,
+ DevToolsConfig,
OGConfig,
PageFrontmatter,
PageAgentAppliesTo,
diff --git a/packages/fumadocs/src/ledger/index.ts b/packages/fumadocs/src/ledger/index.ts
index 49c6d7632..19eb5659d 100644
--- a/packages/fumadocs/src/ledger/index.ts
+++ b/packages/fumadocs/src/ledger/index.ts
@@ -55,7 +55,6 @@ const LedgerUIDefaults = {
Callout: { variant: "soft", icon: true },
CodeBlock: { showCopyButton: true },
HoverLink: { linkLabel: "Open page", showIndicator: false },
- Tabs: { style: "default" },
},
};
diff --git a/packages/fumadocs/src/shadcn/index.test.ts b/packages/fumadocs/src/shadcn/index.test.ts
index f480f4165..46d877233 100644
--- a/packages/fumadocs/src/shadcn/index.test.ts
+++ b/packages/fumadocs/src/shadcn/index.test.ts
@@ -1,4 +1,6 @@
import { describe, expect, it } from "vitest";
+import { hardline } from "../hardline/index.js";
+import { threadline } from "../threadline/index.js";
import { shadcn } from "./index.js";
describe("shadcn theme", () => {
@@ -10,4 +12,10 @@ describe("shadcn theme", () => {
darkTheme: "vesper",
});
});
+
+ it("does not forward theme variants through React's reserved style prop", () => {
+ for (const theme of [hardline(), shadcn(), threadline()]) {
+ expect(theme.ui?.components?.Tabs).toBeUndefined();
+ }
+ });
});
diff --git a/packages/fumadocs/src/shadcn/index.ts b/packages/fumadocs/src/shadcn/index.ts
index 6554518ab..f556de8e9 100644
--- a/packages/fumadocs/src/shadcn/index.ts
+++ b/packages/fumadocs/src/shadcn/index.ts
@@ -61,7 +61,6 @@ const ShadcnUIDefaults = {
Callout: { variant: "soft", icon: true },
CodeBlock: { showCopyButton: true },
HoverLink: { linkLabel: "Open page", showIndicator: false },
- Tabs: { style: "underline" as const },
},
};
diff --git a/packages/fumadocs/src/shiny/index.ts b/packages/fumadocs/src/shiny/index.ts
index fece64aa0..76714366a 100644
--- a/packages/fumadocs/src/shiny/index.ts
+++ b/packages/fumadocs/src/shiny/index.ts
@@ -37,7 +37,6 @@ const ShinyUIDefaults = {
Callout: { variant: "soft", icon: true },
CodeBlock: { showCopyButton: true },
HoverLink: { linkLabel: "Open page", showIndicator: false },
- Tabs: { style: "default" },
},
};
diff --git a/packages/fumadocs/src/threadline/index.ts b/packages/fumadocs/src/threadline/index.ts
index 766a368a6..af1780f76 100644
--- a/packages/fumadocs/src/threadline/index.ts
+++ b/packages/fumadocs/src/threadline/index.ts
@@ -64,7 +64,6 @@ const ThreadlineUIDefaults = {
copiedIcon: "check",
openIcon: "arrowUpRight",
},
- Tabs: { style: "default" },
},
};
diff --git a/packages/fumadocs/tsdown.config.ts b/packages/fumadocs/tsdown.config.ts
index b42c7b4a5..52fc168ec 100644
--- a/packages/fumadocs/tsdown.config.ts
+++ b/packages/fumadocs/tsdown.config.ts
@@ -13,6 +13,7 @@ export default defineConfig({
"src/code-block-copy-wrapper.tsx",
"src/docs-ai-features.tsx",
"src/docs-command-search.tsx",
+ "src/devtools.tsx",
"src/docs-layout.tsx",
"src/docs-page-client.tsx",
"src/mdx-img.tsx",
diff --git a/skills/farming-labs/configuration/references/core-options.md b/skills/farming-labs/configuration/references/core-options.md
index c61de6a03..6eb93bb36 100644
--- a/skills/farming-labs/configuration/references/core-options.md
+++ b/skills/farming-labs/configuration/references/core-options.md
@@ -36,6 +36,7 @@ export, and reader-facing UI configuration.
| `agent` | unset | Compaction, evaluations, published skills, and A2A |
| `review` | `true` | Review scoring, CI workflow, and severities |
| `pageActions` | unset | Copy Markdown and Open in LLM actions |
+| `devTools` | `false` | Local visual MDX editor with apply and preview actions |
| `ai` | unset | Ask AI configuration |
| `search` | `true` | Simple, Typesense, Algolia, MCP, or custom search |
| `cloud` | unset | Hosted preview/publish defaults |
@@ -166,6 +167,22 @@ export default defineDocs({
## Reader-facing options
+### DevTools
+
+```ts
+devTools: true,
+
+// or
+devTools: {
+ enabled: true,
+},
+```
+
+The built-in DevTools editor is local-development only. It loads and writes the current MDX page
+through `/api/docs?devtools=page`, supports block and source editing, and can publish a preview
+through `/api/docs?devtools=publish` when `FARMING_CLOUD_API_KEY` or `FARMING_API_KEY` is available.
+It is hidden for `staticExport: true`, and its API rejects production or non-local requests.
+
### Reading time
```ts
diff --git a/website/app/docs/configuration/page.mdx b/website/app/docs/configuration/page.mdx
index b852dc06e..a7d070470 100644
--- a/website/app/docs/configuration/page.mdx
+++ b/website/app/docs/configuration/page.mdx
@@ -168,6 +168,7 @@ All configuration lives in a single `docs.config.ts` file.
| `review` | `boolean \| DocsReviewConfig` | `true` | Docs Review CI workflow generation, scoring, and rule severity |
| `readingTime` | `boolean \| ReadingTimeConfig` | `false` | Opt-in estimated read-time label with optional per-page overrides |
| `pageActions` | `PageActionsConfig` | — | Copy Markdown, Open in LLM buttons |
+| `devTools` | `boolean \| DevToolsConfig` | `false` | Local visual MDX editor with Apply Changes and Publish Preview actions |
| `ai` | `AIConfig` | — | RAG-powered AI chat |
| `search` | `boolean \| DocsSearchConfig` | `true` | Built-in simple search, Typesense, Algolia, or a custom adapter |
| `cloud` | `DocsCloudConfig` | — | Docs Cloud API key env, deploy, and publish defaults mirrored into `docs.json` |
@@ -594,6 +595,28 @@ export default defineDocs({
Use this when you deploy to a static host and don’t run a server. Search and AI require a server; with `staticExport: true` they are hidden so the site works without one.
+## DevTools
+
+Set `devTools: true` while developing locally to render the built-in visual MDX editor. It adds a
+floating DevTools button on docs pages, loads the current page source from the docs API, replaces the
+page body with an inline editing canvas, lets you edit/reorder MDX blocks, and writes the result back
+to the source file when you click Apply Changes.
+
+```ts title="docs.config.ts"
+export default defineDocs({
+ entry: "docs",
+ devTools: true,
+ theme: fumadocs(),
+});
+```
+
+DevTools are local-development only. The docs API refuses DevTools requests unless the feature is
+enabled and the request is local or the app is running outside production. With `staticExport: true`,
+the floating editor is hidden because there is no server route to write files.
+
+Publish Preview uses the same local DevTools toolbar and forwards to Farming Cloud with
+`FARMING_CLOUD_API_KEY` or `FARMING_API_KEY`.
+
## Search
Search is enabled by default. If you do nothing, the docs API uses the built-in simple adapter with
diff --git a/website/app/docs/reference/page.mdx b/website/app/docs/reference/page.mdx
index f03c659c8..99716c1f0 100644
--- a/website/app/docs/reference/page.mdx
+++ b/website/app/docs/reference/page.mdx
@@ -141,6 +141,7 @@ Top-level configuration object passed to `defineDocs()`.
| `review` | `boolean \| DocsReviewConfig` | `true` | Docs Review scoring, rule severity, and GitHub Actions workflow generation |
| `readingTime` | `boolean \| ReadingTimeConfig` | `false` | Opt-in estimated reading-time label with per-page overrides |
| `pageActions` | `PageActionsConfig` | — | "Copy Markdown" and "Open in LLM" buttons |
+| `devTools` | `boolean \| DevToolsConfig` | `false` | Local visual MDX editor with Apply Changes and Publish Preview actions |
| `ai` | `AIConfig` | — | RAG-powered AI chat |
| `search` | `boolean \| DocsSearchConfig` | `true` | Built-in simple search, Typesense, Algolia, or a custom adapter |
| `mcp` | `boolean \| DocsMcpConfig` | enabled | Built-in MCP server over stdio, `/mcp`, and `/.well-known/mcp` |
@@ -410,6 +411,34 @@ In both cases the adapter-owned MDX transform is prepended before any plugins yo
---
+## `devTools` and `DevToolsConfig`
+
+Local visual MDX editor for docs authors.
+
+| Option | Type | Default | Description |
+| --------- | --------- | ------- | ---------------------------------------------- |
+| `enabled` | `boolean` | `true` | Set `false` when using object form to opt out. |
+
+```ts title="docs.config.ts"
+devTools: true,
+
+// or
+devTools: {
+ enabled: true,
+},
+```
+
+When enabled, docs pages render a floating DevTools button in local development. Opening it replaces
+the page body with an inline MDX editing canvas, so authors can edit the current page as blocks or
+raw source, apply changes back to the page file through `/api/docs?devtools=page`, and publish
+previews through `/api/docs?devtools=publish` when `FARMING_CLOUD_API_KEY` or `FARMING_API_KEY` is
+available.
+
+DevTools are hidden when `staticExport: true` and API requests are rejected unless the feature is
+enabled and the request is local or the app is running outside production.
+
+---
+
## `telemetry` and `DocsTelemetryConfig`
Farming Labs maintainer telemetry for production adoption and coarse agent-optimized feature usage.