MDX processing package for UI8Kit documentation. Provides React components and utilities for dev-time interactive previews and build-time static HTML generation.
- Dual-mode operation — Interactive dev mode with HMR, static HTML generation for production
- Docs-first routing — Filesystem structure defines routes (no config needed)
- React Context & Hooks —
usePageContent(),useToc(),useFrontmatter() - Documentation Components —
ComponentPreview,PropsTable,Callout,Steps - Generator Service —
MdxServicefor integration with@ui8kit/generator
bun add @ui8kit/mdx-react| Entry Point | Environment | Description |
|---|---|---|
@ui8kit/mdx-react |
Browser | React context, hooks, components |
@ui8kit/mdx-react/server |
Node.js | Scanner, generator (uses fs) |
@ui8kit/mdx-react/service |
Node.js | IService adapter for Orchestrator |
@ui8kit/mdx-react/vite |
Node.js | Vite plugin for dev mode |
// src/routes/DocsPage.tsx
import { PageContentProvider, usePageContent, useToc } from '@ui8kit/mdx-react'
// Load MDX files with Vite glob
const mdxModules = import.meta.glob('../docs/**/*.mdx')
function DocsPage() {
const { Content, frontmatter } = usePageContent()
const toc = useToc()
return (
<article>
<h1>{frontmatter.title}</h1>
<Content />
<TableOfContents items={toc} />
</article>
)
}// generator.config.ts
import { generate } from '@ui8kit/generator'
await generate({
mdx: {
enabled: true,
docsDir: './docs',
outputDir: './dist/html',
navOutput: './dist/docs-nav.json',
basePath: '/docs',
},
})import { MdxService } from '@ui8kit/mdx-react/service'
const service = new MdxService()
await service.initialize({
logger: console,
config: { html: { mode: 'tailwind' } },
})
const result = await service.execute({
docsDir: './docs',
outputDir: './dist/html',
basePath: '/docs',
navOutput: './dist/docs-nav.json',
})
console.log(`Generated ${result.pages} pages`)import { Orchestrator, MdxStage } from '@ui8kit/generator'
const orchestrator = new Orchestrator({ logger })
orchestrator.addStage(new MdxStage())
// MdxStage runs automatically when mdx.enabled=true
await orchestrator.generate(config)mdx: {
// Required
enabled: true,
docsDir: './docs', // MDX source folder
outputDir: './dist/html', // HTML output folder
// Optional
basePath: '/docs', // URL prefix for routes
navOutput: './dist/nav.json', // Navigation JSON path
// Components available in MDX
components: {
Button: '@/components/ui/Button',
Card: '@/components/Card',
},
// TypeScript props extraction
propsSource: './src/components',
// Table of Contents
toc: {
minLevel: 2, // Start from h2
maxLevel: 3, // Include up to h3
},
}| Mode | Output | Use Case |
|---|---|---|
tailwind |
class + data-class |
Development, Tailwind processing |
semantic |
class only (from data-class) |
Clean semantic HTML |
inline |
Semantic + inline <style> |
Email templates, portability |
Routes are derived from the filesystem structure:
docs/
├── index.mdx → /
├── getting-started.mdx → /getting-started
├── components/
│ ├── index.mdx → /components
│ ├── button.mdx → /components/button
│ └── card.mdx → /components/card
└── tutorials/
└── getting-started.mdx → /tutorials/getting-started
---
title: Button Component
description: Interactive button with variants
order: 1
---
# Button
Content here...| Field | Type | Description |
|---|---|---|
title |
string | Page title, used in <title> and navigation |
description |
string | SEO description, meta tag |
order |
number | Sort order in navigation (lower = first) |
const { Content, frontmatter, toc, excerpt } = usePageContent()const toc = useToc()
// [{ depth: 2, text: 'Usage', slug: 'usage' }, ...]const { title, description } = useFrontmatter()<ComponentPreview title="Primary Button">
<Button variant="primary">Click me</Button>
</ComponentPreview><PropsTable component="Button" /><Callout type="warning">
This feature is experimental.
</Callout><Steps>
1. Install the package
2. Import the component
3. Use in your code
</Steps>dist/html/
├── index.html
├── getting-started/
│ └── index.html
└── components/
├── index.html
├── button/
│ └── index.html
└── card/
└── index.html
{
"items": [
{ "title": "Home", "path": "/", "order": 0 },
{ "title": "Button", "path": "/components/button", "order": 1 }
],
"generated": "2026-01-22T12:00:00.000Z"
}Critical: Strict separation prevents Node.js APIs from being bundled for browser.
// ✅ Browser-safe (main entry)
import { usePageContent, useToc } from '@ui8kit/mdx-react'
// ✅ Node.js only (server entry)
import { scanDocsTree, generateDocsFromMdx } from '@ui8kit/mdx-react/server'
// ✅ IService for generator
import { MdxService } from '@ui8kit/mdx-react/service'
// ❌ Would fail in browser
import { scanDocsTree } from '@ui8kit/mdx-react' // Uses fs!// vite.config.ts
import mdx from '@mdx-js/rollup'
import remarkFrontmatter from 'remark-frontmatter'
import remarkMdxFrontmatter from 'remark-mdx-frontmatter'
export default {
plugins: [
mdx({
remarkPlugins: [remarkFrontmatter, remarkMdxFrontmatter],
}),
],
optimizeDeps: {
exclude: ['@ui8kit/mdx-react/server'], // Don't bundle server code
},
}MIT