--- name: using-docs-kit description: > Set up and author a documentation site with @lobehub/docs-kit (the `lobedocs` CLI, React Router + Vite static docs used by ui.lobehub.com). Covers consumer repo layout, docs.config.ts, package scripts, component doc pages (index.mdx frontmatter, `?demo` imports, , ), guide pages, home page, changelog, and the build-time validations that reject bad docs. Trigger on docs-kit, lobedocs, defineDocsConfig, docs.config.ts, migrate from dumi, write component docs, add a demo, , , index.mdx, 文档站, 写文档, 组件文档, 迁移 dumi. --- # Using @lobehub/docs-kit The consumer repo holds **only content + `docs.config.ts`**. The kit owns Vite and React Router config; do not add `vite.config.ts` or `react-router.config.ts` unless overriding (see [reference/config.md](reference/config.md)). lobe-ui itself is the reference consumer: `docs.config.ts`, `docs/`, `src/*/index.mdx`, `src/*/demos/`. ## 1. Repo layout ``` / ├── docs.config.ts # defineDocsConfig({...}) — required ├── package.json # lobedocs scripts ├── docs/ │ ├── index.mdx # "/" — required (frontmatter feeds SEO even with a custom homePage) │ ├── changelog.mdx # "/changelog" — optional; else root CHANGELOG.md is used │ └── home/home.tsx # optional custom landing page (config.homePage) ├── src/ │ └── Button/ │ ├── index.ts # barrel export — resolves props through it │ ├── Button.tsx │ ├── type.ts # props with JSDoc │ ├── index.mdx # -> /components/button │ └── demos/ │ ├── index.tsx # default-export component │ └── Variant.tsx ├── public/ # static assets served at "/" (favicons, og images) └── CHANGELOG.md ``` Hard rules the compiler enforces: - Only files named **`index.mdx`** under an `atomDirs` root become component pages (`index.md` and `README.md` are ignored). - Demo files must live under **`src/**/demos/**`** — standalone `/~demos/:id` routes and `isolated` demos are globbed from that path only. - Other `docs/**/*.mdx` files are **not** discovered unless listed in `publicDocs`. ## 2. Install and scripts ```bash pnpm add -D @lobehub/docs-kit @react-router/dev@8.2.0 react-router@8.2.0 vite@8.1.4 tsx pnpm add react react-dom # ^19 ``` ```json { "scripts": { "docs:dev": "lobedocs dev", "docs:build": "lobedocs build", "postinstall": "lobedocs typegen" } } ``` `lobedocs build` writes the static site to `dist/` (Pagefind search, sitemap, `/llms.txt`, `/skills.md` are generated automatically). Node >= 22.22. ## 3. Minimal `docs.config.ts` ```ts export default { atomDirs: [{ dir: 'src' }], title: 'Lobe Editor', description: 'One sentence describing the library.', siteUrl: 'https://editor.lobehub.com', alias: { '@': 'src', '@lobehub/editor': 'src' }, // let demos import the package from source themeConfig: { apiHeader: { packageName: '@lobehub/editor', // defaults to @lobehub/ui — always set it github: 'https://github.com/lobehub/lobe-editor', }, socialLinks: [ { href: 'https://github.com/lobehub/lobe-editor', icon: 'github', label: 'GitHub' }, ], }, }; ``` > The package's only stable JS entry is `@lobehub/docs-kit/react-router-config`; there is no > root export for `defineDocsConfig`. It is an identity function, so export a plain object. > (lobe-ui imports it from `./packages/docs-kit/src/config` only because it is the workspace.) **Restart `lobedocs dev` after editing `docs.config.ts`** — config is cached per process. All fields (multiple `atomDirs`, `subType`, `homePage`, `publicDocs`, `navItems`, giscus, analytics, `legacyRedirects`) are in [reference/config.md](reference/config.md). ## 4. Writing a component page (`src//index.mdx`) Template: ```mdx --- title: Button description: Button triggers an action. Supports variants, sizes, loading and icon slots. category: General order: -1 --- import Basic from './demos/index.tsx?demo'; import Variants from './demos/Variant.tsx?demo'; ## Introduction One or two paragraphs: what it is, when to use it, when to use something else. ## Basic Usage ## Variants Explain the dimension first, then show it. ## API Additionally, Button supports all props of antd's Button except `icon`. ``` ### Frontmatter | Field | Required | Effect | | ------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------- | | `title` | yes | H1, ``, sidebar label. If PascalCase, the header shows `import { Title } from '<packageName>'` — match the export name | | `description` | yes | Subtitle, meta/OG description, search, llms.txt. One or two plain sentences, no markdown | | `category` | yes (component) | Sidebar group inside the section. Reuse existing names; `General` sorts first | | `order` | no | Number, lower first within category; unset sorts last, then by title | | `status` | no | `stable` \| `beta` \| `experimental` \| `deprecated` | | `since` | no | Version string | | `route` | no | Override the URL; component pages must stay under `/components/` | Anything else (`group`, `nav`, `apiHeader`, dumi's `hero`) is ignored — remove it. URL is derived from the folder: `src/Button/index.mdx` → `/components/button`, `src/base-ui/Select/index.mdx` → `/components/base-ui/select` (each segment kebab-cased). ### Headings The page already renders `title` as the H1. Start body sections at `##`; a stray `#` is downgraded to H2. Every heading gets an anchor and appears in the outline and llms.txt, so use short, stable, noun-style headings (`## Variants`, `## Controlled`, `## API`). ### Demos ```mdx import Basic from './demos/index.tsx?demo'; <Demo of={Basic} title="Basic usage" description="Optional caption." layout="center" /> ``` | Prop | Default | Use | | ----------------------- | ----------- | --------------------------------------------------------------------------------------- | | `of` | — | Required. The `?demo` import (without `?demo` you get the raw component and it fails) | | `title` / `description` | — | Caption above the demo | | `layout` | `'default'` | `'bare'` no padding/frame (playgrounds, full-width); `'center'` centered small elements | | `isolated` | `false` | Render in an iframe — for fixed/portal/global-CSS demos that would leak into the page | | `editable` | `true` | Set `false` if the demo uses dynamic `import()`, workers, or odd local deps | | `height` | — | Frame height, e.g. for isolated demos | Demo file rules: - Exactly one `export default` component; import the library by its **package name** (`import { Button } from '@lobehub/editor'`) so the shown source is copy-pasteable — the `alias` maps it back to `src/`. - One idea per demo; name files after the idea (`Variant.tsx`, `Controlled.tsx`), `index.tsx` for the basic one. - Keep it self-contained: no fetching, no reliance on site state; mock data inline. - Interactive playgrounds (lobe-ui style) use `StoryBook` + `useControls` from `@lobehub/ui/storybook` with `layout="bare"`. ### API table ```mdx <Api name="Button" /> <!-- resolves via nearest index.ts barrel --> <Api name="ChatItem" from=".." /> <!-- module path relative to this index.mdx --> ``` Only static `name` and `from` are allowed (`data` is compiler-owned; `migrationKey` in old lobe-ui pages is inert). Props are extracted from TypeScript, so the quality of the table is the quality of your types: ```ts export interface ButtonProps { /** * Adds a frosted-glass background. * @default false */ glass?: boolean; /** @deprecated Use `variant="filled"` instead. */ filled?: boolean; } ``` - The JSDoc body is the description; supported tags: `@default`, `@deprecated`, `@since`. - `@default` must match the runtime destructuring default, or the build fails. - `any` / `unknown` props fail the build — type them. - Props starting with `_` are hidden; inherited React/HTML attributes collapse into a footnote. ### Other MDX content - Globals available without import: only `Demo` and `Api`. Import anything else explicitly (e.g. `import { Alert } from '@lobehub/ui'`). - GFM is on (tables, task lists, strikethrough). No `:::` callout syntax. - Code fences are highlighted only — never executed. dumi's ` ```tsx | pure ` meta is harmless but meaningless; plain ` ```tsx ` is preferred for new pages. - `.md` files can be imported as components: `import Changelog from '../CHANGELOG.md'`. ## 5. Guides, home, changelog - **Guide pages**: add `docs/<path>.mdx` (frontmatter `title` + `description`) and list it in `publicDocs: ['docs/<path>.mdx']` → served at `/<path>`. Guides get no sidebar entry; link to them via `themeConfig.navItems`. - **Home**: `docs/index.mdx` needs frontmatter. Without `homePage`, the default home is built from `themeConfig.home` (hero, features, install). With `homePage: './docs/home/home.tsx'`, that module's default export renders instead and receives `{ description: string; getStartedPathname: string }`. - **Changelog**: either `docs/changelog.mdx` importing `../CHANGELOG.md`, or just a root `CHANGELOG.md` (no frontmatter needed). ## 6. Workflow for adding or migrating a page ``` - [ ] index.mdx exists at src/<Name>/index.mdx with title, description, category - [ ] every <Demo of={X}> has a matching `import X from './demos/….tsx?demo'` - [ ] demos default-export and import the package by name - [ ] <Api name> matches an exported component; props typed with JSDoc - [ ] dumi leftovers removed: <code src=…>, `group:`, `nav:`, `hero:`, `apiHeader:` frontmatter - [ ] `lobedocs dev`, open the page, check demos + API table render - [ ] `lobedocs build` passes (it runs all audits) ``` When the build fails, the error lists the offending file and rule; see [reference/validations.md](reference/validations.md) for every rule and the fix. ## Additional resources - [reference/config.md](reference/config.md) — every `docs.config.ts` field, multi-package `atomDirs`, sections/navigation, React Router overrides, tsconfig for typegen - [reference/validations.md](reference/validations.md) — what fails `lobedocs build` and why