# Installation
URL: /docs/installation
LLM index: /llms.txt
Description: Get up and running in minutes

# Installation

You are an agent helping a user install @farming-labs/docs into an existing app.

Prefer the CLI path first unless the user explicitly wants manual setup.
Keep the framework-specific package names exact.
If the user already told you their framework, do not switch stacks.
When reading `/docs/installation.md` or the MCP page output, preserve the tabbed command variants and
the distinction between existing-project setup and fresh-template setup.
If more repo and product context would help, suggest installing the skills bundle with
`npx skills add farming-labs/docs`.
Once agent skills are available, prefer the `getting-started` and `cli` skills for install, init,
upgrade, and theme setup questions.

## Option A: CLI (Recommended)

**Starting from scratch?** Use **`--template`** with **`--name <project>`** to bootstrap a new docs project (Next.js, TanStack Start, Nuxt, SvelteKit, or Astro). No prompts — the CLI creates the project folder and runs install. See the `--template` section below.

**Adding docs to an existing app?** Run the init command inside your Next.js, TanStack Start, SvelteKit, Astro, or Nuxt project:

<Tabs items={["npm", "pnpm", "yarn", "bun"]}>
  <Tab value="npm">
    ```bash title="terminal"
    npx @farming-labs/docs init
    ```
  </Tab>
  <Tab value="pnpm">
    ```bash title="terminal"
    pnpm dlx @farming-labs/docs init
    ```
  </Tab>
  <Tab value="yarn">
    ```bash title="terminal"
    yarn dlx @farming-labs/docs init
    ```
  </Tab>
  <Tab value="bun">
    ```bash title="terminal"
    bunx @farming-labs/docs init
    ```
  </Tab>
</Tabs>

The CLI will first ask: **Are you adding docs to an existing project or starting fresh?** Choose **Existing project** to add docs to the current directory. It will then:

1. Detect your framework (Next.js, TanStack Start, SvelteKit, Astro, or Nuxt), or ask you to pick one
2. Ask you to pick a theme (including **Create your own theme**, which prompts for a theme name and scaffolds `themes/<name>.ts` and `themes/<name>.css`)
3. Ask about path aliases and which global CSS file to use (defaults are offered; press **Enter** to accept)
4. Ask for the docs entry path (default: `docs` — press **Enter** to accept)
5. Optionally scaffold i18n by selecting locales, adding custom locale codes, and choosing a default locale
   TanStack Start currently skips the built-in i18n scaffold so the generated routes stay minimal and working
6. Generate config, layout, CSS, and sample pages
7. Install dependencies and optionally start the dev server

Prompts that show a placeholder (e.g. entry path, theme name) use that value as the default — you can press **Enter** to skip typing. See [CLI — Init flow](/docs/cli#init-flow-without-template) for the full sequence.

If you enable i18n, the CLI creates locale folders like `docs/en` and `docs/fr`, writes the `i18n` block to `docs.config`, and scaffolds the framework-specific files needed for routes like `/docs?lang=en`.

To **upgrade** all docs packages to the latest later, run from your project root: `npx @farming-labs/docs upgrade` (framework is auto-detected). See [CLI — Upgrade](/docs/cli#upgrade) for options.

**Starting from scratch or want a full example?** Use **`--template`** with **`--name <project>`** to bootstrap a ready-to-run docs app. The CLI creates the project folder, bootstraps it with the chosen framework, and runs install:

<Tabs items={["npm", "pnpm", "yarn", "bun"]}>
  <Tab value="npm">
    ```bash title="terminal"
    npx @farming-labs/docs init --template next --name my-docs     # Next.js
    npx @farming-labs/docs init --template tanstack-start --name my-docs # TanStack Start
    npx @farming-labs/docs init --template nuxt --name my-docs     # Nuxt
    npx @farming-labs/docs init --template sveltekit --name my-docs # SvelteKit
    npx @farming-labs/docs init --template astro --name my-docs    # Astro
    ```
  </Tab>
  <Tab value="pnpm">
    ```bash title="terminal"
    pnpm dlx @farming-labs/docs init --template next --name my-docs     # Next.js
    pnpm dlx @farming-labs/docs init --template tanstack-start --name my-docs # TanStack Start
    pnpm dlx @farming-labs/docs init --template nuxt --name my-docs     # Nuxt
    pnpm dlx @farming-labs/docs init --template sveltekit --name my-docs # SvelteKit
    pnpm dlx @farming-labs/docs init --template astro --name my-docs    # Astro
    ```
  </Tab>
  <Tab value="yarn">
    ```bash title="terminal"
    yarn dlx @farming-labs/docs init --template next --name my-docs     # Next.js
    yarn dlx @farming-labs/docs init --template tanstack-start --name my-docs # TanStack Start
    yarn dlx @farming-labs/docs init --template nuxt --name my-docs     # Nuxt
    yarn dlx @farming-labs/docs init --template sveltekit --name my-docs # SvelteKit
    yarn dlx @farming-labs/docs init --template astro --name my-docs    # Astro
    ```
  </Tab>
  <Tab value="bun">
    ```bash title="terminal"
    bunx @farming-labs/docs init --template next --name my-docs     # Next.js
    bunx @farming-labs/docs init --template tanstack-start --name my-docs # TanStack Start
    bunx @farming-labs/docs init --template nuxt --name my-docs     # Nuxt
    bunx @farming-labs/docs init --template sveltekit --name my-docs # SvelteKit
    bunx @farming-labs/docs init --template astro --name my-docs    # Astro
    ```
  </Tab>
</Tabs>

Replace `my-docs` with your project name. Then run `cd my-docs` and start the dev server (`npm run dev`, `pnpm run dev`, `yarn dev`, or `bun run dev`).

## Option B: Manual Setup

<Callout type="info" title="Theme CSS in global styles">
  For each framework below, add your **theme's CSS** to your global stylesheet (e.g. `app/global.css`, `src/app.css`, or `nuxt.config`). The import path must match the theme you use in `docs.config` — e.g. `default`, `greentree`, `darksharp`. Without it, docs pages will lack the correct styling.
</Callout>

<Tabs items={["Next.js", "TanStack Start", "SvelteKit", "Astro", "Nuxt"]}>
  <Tab value="Next.js">
    ### 1. Install packages

    <Tabs items={["npm", "pnpm", "yarn", "bun"]}>
      <Tab value="npm">
        ```bash title="terminal"
        npm install @farming-labs/docs @farming-labs/theme @farming-labs/next
        ```
      </Tab>
      <Tab value="pnpm">
        ```bash title="terminal"
        pnpm add @farming-labs/docs @farming-labs/theme @farming-labs/next
        ```
      </Tab>
      <Tab value="yarn">
        ```bash title="terminal"
        yarn add @farming-labs/docs @farming-labs/theme @farming-labs/next
        ```
      </Tab>
      <Tab value="bun">
        ```bash title="terminal"
        bun add @farming-labs/docs @farming-labs/theme @farming-labs/next
        ```
      </Tab>
    </Tabs>

    > **Monorepo note**: If you are developing `@farming-labs/docs` and a TanStack Start app in the same workspace, keep `@farming-labs/docs`, `@farming-labs/theme`, and `@farming-labs/tanstack-start` linked locally (for example `workspace:*`). This avoids Node 22 / Vercel trying to load raw adapter TypeScript from `node_modules`.

    ### 2. Create `docs.config.tsx`

    ```tsx title="docs.config.tsx"
    import { defineDocs } from "@farming-labs/docs";
    import { fumadocs } from "@farming-labs/theme";

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

    ### 3. Create `next.config.ts`

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

    ### 4. Set up `RootProvider` in `app/layout.tsx`

    Wrap your app with `RootProvider` from `@farming-labs/theme`. This enables search, theme switching, and AI chat across all pages.

    ```tsx title="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>
      );
    }
    ```

    > `RootProvider` automatically configures the search API endpoint (`/api/docs`) and handles theme persistence. The `suppressHydrationWarning` on `<html>` prevents React warnings from the theme class injection.

    ### 5. Import theme CSS in `app/global.css`

    Add your theme's CSS to your global stylesheet so docs styling applies. Use the import that matches the theme in your config (e.g. `default` below; for `greentree` use `@farming-labs/theme/greentree/css`).

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

    ### 6. Write your first doc

    Create an MDX file under `app/docs/`:

    ```text
    app/docs/
      page.mdx              # /docs
      getting-started/
        page.mdx            # /docs/getting-started
    ```

    Each page uses frontmatter for metadata:

    ```mdx title="app/docs/getting-started/page.mdx"
    ---
    title: "Getting Started"
    description: "Your first doc page"
    icon: "rocket"
    ---

    # Getting Started

    Your content here.
    ```

    That's it — the docs layout (`app/docs/layout.tsx`) is auto-generated by `withDocs()`. The framework handles routing, MDX compilation, and metadata from your config.

    > See [CLI](/docs/cli) for all generated files including the full `app/layout.tsx` and `app/docs/layout.tsx`, or check [Configuration](/docs/configuration) for all available options.

  </Tab>
  <Tab value="TanStack Start">
    ### 1. Install packages

    <Tabs items={["npm", "pnpm", "yarn", "bun"]}>
      <Tab value="npm">
        ```bash title="terminal"
        npm install @farming-labs/docs @farming-labs/theme @farming-labs/tanstack-start
        ```
      </Tab>
      <Tab value="pnpm">
        ```bash title="terminal"
        pnpm add @farming-labs/docs @farming-labs/theme @farming-labs/tanstack-start
        ```
      </Tab>
      <Tab value="yarn">
        ```bash title="terminal"
        yarn add @farming-labs/docs @farming-labs/theme @farming-labs/tanstack-start
        ```
      </Tab>
      <Tab value="bun">
        ```bash title="terminal"
        bun add @farming-labs/docs @farming-labs/theme @farming-labs/tanstack-start
        ```
      </Tab>
    </Tabs>

    > **Monorepo note**: If you are developing `@farming-labs/docs` and a TanStack Start app in the same workspace, keep `@farming-labs/docs`, `@farming-labs/theme`, and `@farming-labs/tanstack-start` linked locally (for example `workspace:*`). This avoids Node 22 / Vercel trying to load raw adapter TypeScript from `node_modules`.

    ### 2. Create `docs.config.tsx`

    ```tsx title="docs.config.tsx"
    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",
      },
      metadata: {
        titleTemplate: "%s – Docs",
        description: "My documentation site",
      },
    });
    ```

    ### 3. Update `vite.config.ts`

    ```ts title="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()],
    });
    ```

    ### 4. Create `src/lib/docs.server.ts`

    ```ts title="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(),
    });
    ```

    ### 5. Create `src/lib/docs.functions.ts`

    ```ts title="src/lib/docs.functions.ts"
    import { createServerFn } from "@tanstack/react-start";
    import { docsServer } from "./docs.server";

    export const loadDocPage = createServerFn({ method: "GET" })
      .inputValidator((data: { pathname: string; locale?: string }) => data)
      .handler(async ({ data }) => docsServer.load(data));
    ```

    ### 6. Wrap the app with `RootProvider`

    ```tsx title="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 }],
        meta: [
          { charSet: "utf-8" },
          { name: "viewport", content: "width=device-width, initial-scale=1" },
          { title: "TanStack Start Docs" },
        ],
      }),
      component: RootComponent,
    });

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

    ### 7. Render docs routes

    ```tsx title="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()} />,
    });
    ```

    ```tsx title="src/routes/docs.$.tsx"
    import { createFileRoute, notFound } 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: async ({ location }) => {
        try {
          return await loadDocPage({ data: { pathname: location.pathname } });
        } catch (error) {
          if (
            error &&
            typeof error === "object" &&
            "status" in error &&
            (error as { status?: unknown }).status === 404
          ) {
            throw notFound();
          }
          throw error;
        }
      },
      component: () => <TanstackDocsPage config={docsConfig} data={Route.useLoaderData()} />,
    });
    ```

    ### 8. Import the theme CSS in `src/styles/app.css`

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

    ### 9. Add the docs API route

    ```ts title="src/routes/api.docs.ts"
    import { createFileRoute } from "@tanstack/react-router";
    import { docsServer } from "@/lib/docs.server";

    export const Route = createFileRoute("/api/docs")({
      server: {
        handlers: {
          GET: async ({ request }) => docsServer.GET({ request }),
          POST: async ({ request }) => docsServer.POST({ request }),
        },
      },
    });
    ```

    That is the full manual setup. The built-in `TanstackDocsPage` renderer handles MDX page modules for you, so there is no extra `docs-page.tsx` or `doc-modules.ts` file to maintain.
  </Tab>
  <Tab value="SvelteKit">
    ### 1. Install packages

    <Tabs items={["npm", "pnpm", "yarn", "bun"]}>
      <Tab value="npm">
        ```bash title="terminal"
        npm install @farming-labs/docs @farming-labs/svelte @farming-labs/svelte-theme
        ```
      </Tab>
      <Tab value="pnpm">
        ```bash title="terminal"
        pnpm add @farming-labs/docs @farming-labs/svelte @farming-labs/svelte-theme
        ```
      </Tab>
      <Tab value="yarn">
        ```bash title="terminal"
        yarn add @farming-labs/docs @farming-labs/svelte @farming-labs/svelte-theme
        ```
      </Tab>
      <Tab value="bun">
        ```bash title="terminal"
        bun add @farming-labs/docs @farming-labs/svelte @farming-labs/svelte-theme
        ```
      </Tab>
    </Tabs>

    ### 2. Create `src/lib/docs.config.ts`

    ```ts title="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",
      },
      metadata: {
        titleTemplate: "%s – Docs",
        description: "My documentation site",
      },
    });
    ```

    ### 3. Create `src/lib/docs.server.ts`

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

    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,
    });
    ```

    ### 4. Create route files

    **`src/routes/docs/+layout.svelte`**:

    ```svelte title="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`**:

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

    **`src/routes/docs/[...slug]/+page.svelte`**:

    ```svelte title="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`** (for search and AI):

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

    > **Production note**: The `docs.server.ts` file 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.

    ### 5. Import theme CSS in `src/app.css`

    Add your theme's CSS to your global stylesheet so docs styling applies. Use the import that matches the theme in your config (e.g. `fumadocs` below; for `greentree` use `@farming-labs/svelte-theme/greentree/css`).

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

    ### 6. Write your first doc

    Create Markdown files under `docs/`:

    ```text
    docs/
      page.md               # /docs
      getting-started/
        page.md             # /docs/getting-started
    ```

    Each page uses frontmatter for metadata:

    ```md title="docs/getting-started/page.md"
    ---
    title: "Getting Started"
    description: "Your first doc page"
    icon: "rocket"
    ---

    # Getting Started

    Your content here.
    ```

  </Tab>
  <Tab value="Astro">
    ### 1. Install packages

    <Tabs items={["npm", "pnpm", "yarn", "bun"]}>
      <Tab value="npm">
        ```bash title="terminal"
        npm install @farming-labs/docs @farming-labs/astro @farming-labs/astro-theme
        ```
      </Tab>
      <Tab value="pnpm">
        ```bash title="terminal"
        pnpm add @farming-labs/docs @farming-labs/astro @farming-labs/astro-theme
        ```
      </Tab>
      <Tab value="yarn">
        ```bash title="terminal"
        yarn add @farming-labs/docs @farming-labs/astro @farming-labs/astro-theme
        ```
      </Tab>
      <Tab value="bun">
        ```bash title="terminal"
        bun add @farming-labs/docs @farming-labs/astro @farming-labs/astro-theme
        ```
      </Tab>
    </Tabs>

    ### 2. Create `src/lib/docs.config.ts`

    ```ts title="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" },
      metadata: { titleTemplate: "%s – My Docs" },
    });
    ```

    ### 3. Create `src/lib/docs.server.ts`

    ```ts title="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,
    });
    ```

    ### 4. Create page routes

    Import your theme's CSS in each docs page (or in a global CSS file and import that). The example below uses `@farming-labs/astro-theme/css` (default); for other themes use e.g. `@farming-labs/astro-theme/greentree/css`.

    **`src/pages/docs/index.astro`** and **`src/pages/docs/[...slug].astro`**:

    ```astro title="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>
    ```

    ### 5. Create API route

    **`src/pages/api/docs.ts`**:

    ```ts title="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 });
    ```

    ### 6. Astro config

    Enable SSR in `astro.config.mjs`:

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

    ### 7. Write your first doc

    Create Markdown files under `docs/`:

    ```text
    docs/
      page.md               # /docs
      getting-started/
        page.md             # /docs/getting-started
    ```

    Each page uses frontmatter for metadata:

    ```md title="docs/getting-started/page.md"
    ---
    title: "Getting Started"
    description: "Your first doc page"
    icon: "rocket"
    ---

    # Getting Started

    Your content here.
    ```

  </Tab>
  <Tab value="Nuxt">
    ### 1. Install packages

    <Tabs items={["npm", "pnpm", "yarn", "bun"]}>
      <Tab value="npm">
        ```bash title="terminal"
        npm install @farming-labs/docs @farming-labs/nuxt @farming-labs/nuxt-theme
        ```
      </Tab>
      <Tab value="pnpm">
        ```bash title="terminal"
        pnpm add @farming-labs/docs @farming-labs/nuxt @farming-labs/nuxt-theme
        ```
      </Tab>
      <Tab value="yarn">
        ```bash title="terminal"
        yarn add @farming-labs/docs @farming-labs/nuxt @farming-labs/nuxt-theme
        ```
      </Tab>
      <Tab value="bun">
        ```bash title="terminal"
        bun add @farming-labs/docs @farming-labs/nuxt @farming-labs/nuxt-theme
        ```
      </Tab>
    </Tabs>

    ### 2. Create `docs.config.ts`

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

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

    ### 3. Configure `nuxt.config.ts`

    Add your theme's CSS via the `css` array so docs styling applies. Use the path that matches the theme in your config (e.g. `fumadocs` below; for `greentree` use `@farming-labs/nuxt-theme/greentree/css`).

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

    ### 4. Create `server/api/docs.ts`

    ```ts title="server/api/docs.ts"
    import { defineDocsHandler } from "@farming-labs/nuxt/server";
    import config from "../../docs.config";

    export default defineDocsHandler(config, useStorage);
    ```

    ### 5. Create `pages/docs/[...slug].vue`

    ```vue title="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, error } = await useFetch("/api/docs", {
      query: { pathname },
      watch: [pathname],
    });

    if (error.value) {
      throw createError({ statusCode: 404, statusMessage: "Page not found" });
    }
    </script>

    <template>
      <div v-if="data" class="fd-docs-wrapper">
        <DocsLayout :tree="data.tree" :config="config">
          <DocsContent :data="data" :config="config" />
        </DocsLayout>
      </div>
    </template>
    ```

    > Nuxt uses Nitro's server assets to load markdown files at runtime. The `serverAssets` config in `nuxt.config.ts` tells Nitro where your docs directory is.

    ### 6. Write your first doc

    Create Markdown files under `docs/`:

    ```text
    docs/
      page.md               # /docs
      getting-started/
        page.md             # /docs/getting-started
    ```

    Each page uses frontmatter for metadata:

    ```md title="docs/getting-started/page.md"
    ---
    title: "Getting Started"
    description: "Your first doc page"
    icon: "rocket"
    ---

    # Getting Started

    Your content here.
    ```

  </Tab>
</Tabs>