Dumi is a static site generator specifically designed for React component library documentation. It provides developers with a powerful toolkit for creating beautiful, interactive documentation sites that showcase component APIs, usage examples, and live code demonstrations with automatic component prop extraction, live code editing capabilities, responsive themes, and multi-language support.
npm install dumiimport { defineConfig, IApi, type HastRoot, type UnifiedPlugin } from "dumi";For CommonJS:
const { defineConfig } = require("dumi");Additional imports:
import {
getProjectRoot,
unistUtilVisit,
type IDumiTechStack,
type IDumiTechStackRuntimeOpts
} from "dumi";Theme API imports:
import {
useAtomAssets,
useNavData,
useSidebarData,
useRouteMeta,
DumiDemo,
AtomRenderer
} from "dumi/theme";Create a basic dumi project:
// .dumirc.ts
import { defineConfig } from "dumi";
export default defineConfig({
themeConfig: {
name: "My Components",
logo: "/logo.png",
footer: "Copyright © 2023",
},
resolve: {
atomDirs: [{ type: "component", dir: "src" }],
docDirs: ["docs"],
},
});Use the CLI commands:
# Development
npx dumi dev
# Build for production
npx dumi build
# Setup project
npx dumi setupDumi is built around several key components:
Command-line interface providing development, build, and setup commands for dumi projects.
// Available CLI commands
dumi dev // Start development server
dumi build // Build for production
dumi setup // Initialize projectComprehensive configuration system for controlling documentation generation, theming, and build behavior.
function defineConfig(config: IDumiUserConfig): IDumiUserConfig;
interface IDumiUserConfig {
resolve?: {
docDirs?: (string | { type?: string; dir: string })[];
atomDirs?: { type: string; subType?: string; dir: string }[];
codeBlockMode?: 'active' | 'passive';
entryFile?: string;
forceKebabCaseRouting?: boolean;
};
themeConfig?: IThemeConfig;
apiParser?: {
unpkgHost?: string;
resolveFilter?: (args: {
id: string;
type: 'COMPONENT' | 'FUNCTION'
}) => boolean;
};
locales?: ILocale[];
extraRemarkPlugins?: (string | Function | [string | Function, object])[];
extraRehypePlugins?: (string | Function | [string | Function, object])[];
[key: string]: any;
}React hooks and components for building custom themes and accessing site data, navigation, and component metadata.
function useAtomAssets(): {
components: Record<string, AtomComponentAsset>;
};
function useNavData(): INavItems;
function useSidebarData(): ISidebarGroup[];
function useRouteMeta(): IRouteMeta;
function useLiveDemo(id: string, opts?: {
containerRef?: RefObject<HTMLElement>;
iframe?: boolean;
}): {
node: ReactNode;
loading: boolean;
error: Error | null;
setSource: (source: Record<string, string>) => Promise<void>;
};
interface DumiDemo {
(props: IPreviewerProps): JSX.Element;
}
interface AtomRenderer {
(props: { atom: string }): JSX.Element;
}Plugin architecture for extending dumi functionality with custom tech stacks, content tabs, and asset processing.
interface IApi {
registerTechStack: (fn: () => IDumiTechStack) => void;
addContentTab: (fn: () => IContentTab) => void;
modifyAssetsMetadata: IModify<AssetsPackage, null>;
modifyTheme: IModify<IThemeLoadResult, null>;
getAssetsMetadata?: () => Promise<AssetsPackage>;
}
abstract class IDumiTechStack {
abstract name: string;
abstract isSupported(node: Element, lang: string): boolean;
abstract transformCode(raw: string, opts: {
type: 'external' | 'code-block';
fileAbsPath: string;
}): string;
}File system utilities, caching, and build helpers for processing documentation files and managing project structure.
function getProjectRoot(cwd: string): string;
function getFileIdFromFsPath(fsPath: string): string;
function parseCodeFrontmatter(raw: string): {
code: string;
frontmatter: Record<string, any> | null;
};
function runLoaders(options: RunLoaderOption): Promise<RunLoaderResult>;
function getCache(ns: string): Cache;Core type definitions used throughout the dumi API:
interface ILocale {
id: string;
name: string;
base?: string;
suffix?: string;
}
interface IThemeConfig {
name?: string;
logo?: string | false;
nav?: IUserNavValue | NavWithMode<IUserNavValue>;
sidebar?: Record<string, ISidebarGroup[]>;
footer?: string | false;
showLineNum?: boolean;
prefersColor: {
default: 'light' | 'dark' | 'auto';
switch: boolean;
};
socialLinks?: {
[key in SocialTypes]?: string;
};
editLink?: boolean | string;
sourceLink?: boolean | string;
lastUpdated?: boolean;
}
interface AtomComponentAsset {
id: string;
title?: string;
description?: string;
props?: Record<string, any>;
methods?: Record<string, any>;
[key: string]: any;
}
interface IRouteMeta {
frontmatter: {
title: string;
description?: string;
keywords?: string[];
nav?: string | { title?: string; order?: number };
group?: string | { title?: string; order?: number };
order?: number;
hero?: {
title?: string;
description?: string;
background?: string;
actions?: { text: string; link: string }[];
};
features?: {
emoji?: string;
title?: string;
link?: string;
description?: string;
}[];
toc?: boolean | 'content' | 'menu';
demo?: { cols?: number; tocDepth?: number };
sidebar?: boolean;
};
toc: {
id: string;
depth: number;
title: string;
}[];
texts: {
type?: 'content';
value: string;
paraId: number;
tocIndex?: number;
}[];
}
interface IPreviewerProps {
title?: string;
description?: string;
filename?: string;
iframe?: boolean | number;
debug?: boolean;
defaultShowCode?: boolean;
demoUrl: string;
compact?: boolean;
transform?: boolean;
background?: string;
asset: ExampleBlockAsset;
children: ReactNode;
}
type SocialTypes =
| 'github'
| 'weibo'
| 'twitter'
| 'x'
| 'gitlab'
| 'facebook'
| 'zhihu'
| 'yuque'
| 'linkedin';
interface INavItem {
title: string;
link?: string;
order?: number;
activePath?: string;
}
interface ISidebarItem {
title: string;
link: string;
order?: number;
frontmatter?: IRouteMeta['frontmatter'];
}
interface ISidebarGroup {
title?: string;
children: ISidebarItem[];
}
interface IDemoCancelableFn {
(canvas: HTMLElement, component: any): (() => void) | Promise<() => void>;
}
interface IDemoCompileFn {
(code: string, opts: { filename: string }): Promise<string>;
}
interface RunLoaderOption {
resource?: string;
loaders?: any[];
context?: any;
readResource?: Function;
}
interface RunLoaderResult {
result: Buffer[];
resourceBuffer: Buffer;
cacheable: boolean;
fileDependencies: string[];
contextDependencies: string[];
}
/** HAST (Hypertext Abstract Syntax Tree) root node */
interface HastRoot {
type: 'root';
children: Array<any>;
data?: any;
}
/** Unified plugin function type */
type UnifiedPlugin = (options?: any) => any;
/** Unified transformer function type */
type UnifiedTransformer = (tree: any, file?: any) => any;
/** Plugin API interface for dumi plugins */
interface IApi {
config: IDumiConfig & { [key: string]: any };
userConfig: IDumiUserConfig;
service: {
themeData: IThemeLoadResult;
atomParser: any;
[key: string]: any;
};
registerTechStack: (fn: () => IDumiTechStack) => void;
addContentTab: (fn: () => IContentTab) => void;
modifyAssetsMetadata: (fn: (memo: AssetsPackage) => AssetsPackage) => void;
modifyTheme: (fn: (memo: IThemeLoadResult) => IThemeLoadResult) => void;
getAssetsMetadata?: () => Promise<AssetsPackage>;
}