mapcn-docs
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesemapcn-docs
mapcn-docs
Build beautiful, interactive documentation sites with live component previews and copy-paste code examples.
构建美观、交互式的文档站点,支持组件实时预览和可复制粘贴的代码示例。
Overview
概述
This skill implements a documentation system featuring:
- Live previews with tabbed preview/code views
- Syntax-highlighted code using Shiki with light/dark theme support
- Copy-to-clipboard functionality for all code examples
- Responsive sidebar navigation with mobile support
- Scroll-tracking TOC (Table of Contents)
- Accessible design using shadcn/ui components
本方案实现的文档系统具备以下特性:
- 实时预览:支持预览/代码标签页视图
- 语法高亮代码:使用Shiki实现,支持亮色/暗色主题
- 一键复制:所有代码示例均支持复制到剪贴板功能
- 响应式侧边栏:支持移动端的导航侧边栏
- 滚动跟踪目录(TOC)
- 无障碍设计:基于shadcn/ui组件实现
When to Use
适用场景
Use this skill when:
- Building a docs site for a component library or design system
- Creating API reference pages with interactive examples
- Need tabbed preview/code views like shadcn/ui docs
- Want copy-paste ready code examples with syntax highlighting
Do NOT use when:
- Simple static documentation (use MDX or plain markdown)
- No need for live component previews
- Not using Next.js App Router or React
Prerequisites:
- Next.js 13+ with App Router (directory)
app/ - Tailwind CSS configured
- shadcn/ui initialized ()
npx shadcn@latest init
推荐使用本方案的场景:
- 为组件库或设计系统构建文档站点
- 创建带有交互式示例的API参考页面
- 需要类似shadcn/ui文档的标签页式预览/代码视图
- 希望提供可直接复制粘贴的语法高亮代码示例
不推荐使用的场景:
- 简单的静态文档(建议使用MDX或纯Markdown)
- 不需要组件实时预览的场景
- 不使用Next.js App Router或React的项目
前置要求:
- 13+版本的Next.js,且启用App Router(目录)
app/ - 已配置Tailwind CSS
- 已初始化shadcn/ui(执行)
npx shadcn@latest init
Quick Start
快速开始
1. Directory Structure
1. 目录结构
src/app/docs/
├── layout.tsx # Root docs layout
├── page.tsx # Introduction page
├── _components/
│ ├── docs.tsx # Core UI components
│ ├── docs-sidebar.tsx # Navigation sidebar
│ ├── docs-toc.tsx # Table of contents
│ ├── component-preview.tsx # Server-side preview wrapper
│ ├── component-preview-client.tsx # Client-side preview tabs
│ ├── code-block.tsx # Code display
│ ├── copy-button.tsx # Clipboard utility
│ └── examples/ # Live example components
└── [route]/page.tsx # Documentation pagessrc/app/docs/
├── layout.tsx # 文档根布局
├── page.tsx # 介绍页
├── _components/
│ ├── docs.tsx # 核心UI组件
│ ├── docs-sidebar.tsx # 导航侧边栏
│ ├── docs-toc.tsx # 目录组件
│ ├── component-preview.tsx # 服务端预览包装器
│ ├── component-preview-client.tsx # 客户端预览标签页
│ ├── code-block.tsx # 代码展示组件
│ ├── copy-button.tsx # 剪贴板工具组件
│ └── examples/ # 实时示例组件目录
└── [route]/page.tsx # 文档页面2. Install Dependencies
2. 安装依赖
bash
npm install shiki
npx shadcn@latest add sidebar table card tabsbash
npm install shiki
npx shadcn@latest add sidebar table card tabs3. Create Core Components
3. 创建核心组件
See references/COMPONENTS.md for complete component implementations.
完整的组件实现请参考references/COMPONENTS.md。
Page Structure Pattern
页面结构模式
Every documentation page follows this structure:
tsx
import { Metadata } from "next";
import { DocsLayout, DocsSection, DocsPropTable } from "../_components/docs";
import { ComponentPreview } from "../_components/component-preview";
import { getExampleSource } from "@/lib/get-example-source";
import { MyExample } from "../_components/examples/my-example";
export const metadata: Metadata = { title: "Page Title" };
export default function PageName() {
const exampleSource = getExampleSource("my-example.tsx");
return (
<DocsLayout
title="Page Title"
description="Brief description of this page"
prev={{ title: "Previous", href: "/docs/previous" }}
next={{ title: "Next", href: "/docs/next" }}
toc={[
{ title: "Overview", slug: "overview" },
{ title: "Usage", slug: "usage" },
{ title: "API Reference", slug: "api-reference" },
]}
>
<DocsSection>
<p>Introduction paragraph.</p>
</DocsSection>
<DocsSection title="Overview">
<p>Section content here.</p>
</DocsSection>
<DocsSection title="Usage">
<ComponentPreview code={exampleSource}>
<MyExample />
</ComponentPreview>
</DocsSection>
<DocsSection title="API Reference">
<DocsPropTable
props={[
{
name: "propName",
type: "string",
default: "undefined",
description: "Description of the prop",
},
]}
/>
</DocsSection>
</DocsLayout>
);
}所有文档页面遵循以下结构:
tsx
import { Metadata } from "next";
import { DocsLayout, DocsSection, DocsPropTable } from "../_components/docs";
import { ComponentPreview } from "../_components/component-preview";
import { getExampleSource } from "@/lib/get-example-source";
import { MyExample } from "../_components/examples/my-example";
export const metadata: Metadata = { title: "页面标题" };
export default function PageName() {
const exampleSource = getExampleSource("my-example.tsx");
return (
<DocsLayout
title="页面标题"
description="本页面的简短描述"
prev={{ title: "上一页", href: "/docs/previous" }}
next={{ title: "下一页", href: "/docs/next" }}
toc={[
{ title: "概述", slug: "overview" },
{ title: "使用方法", slug: "usage" },
{ title: "API参考", slug: "api-reference" },
]}
>
<DocsSection>
<p>介绍段落。</p>
</DocsSection>
<DocsSection title="概述">
<p>本节内容。</p>
</DocsSection>
<DocsSection title="使用方法">
<ComponentPreview code={exampleSource}>
<MyExample />
</ComponentPreview>
</DocsSection>
<DocsSection title="API参考">
<DocsPropTable
props={[
{
name: "propName",
type: "string",
default: "undefined",
description: "该属性的描述",
},
]}
/>
</DocsSection>
</DocsLayout>
);
}Example Component Pattern
示例组件模式
Create example components in :
_components/examples/tsx
// Client-side example (with state)
"use client";
import { useState } from "react";
import { MyComponent } from "@/registry/my-component";
export function InteractiveExample() {
const [value, setValue] = useState("initial");
return (
<div className="h-[400px] w-full">
<MyComponent value={value} onChange={setValue} />
</div>
);
}tsx
// Server-side example (no state)
import { MyComponent } from "@/registry/my-component";
export function SimpleExample() {
return (
<div className="h-[400px] w-full">
<MyComponent />
</div>
);
}Key pattern: Always wrap examples in a fixed-height container () for consistent preview rendering.
h-[400px]在目录下创建示例组件:
_components/examples/tsx
// 客户端示例(带状态)
"use client";
import { useState } from "react";
import { MyComponent } from "@/registry/my-component";
export function InteractiveExample() {
const [value, setValue] = useState("initial");
return (
<div className="h-[400px] w-full">
<MyComponent value={value} onChange={setValue} />
</div>
);
}tsx
// 服务端示例(无状态)
import { MyComponent } from "@/registry/my-component";
export function SimpleExample() {
return (
<div className="h-[400px] w-full">
<MyComponent />
</div>
);
}关键模式:始终使用固定高度容器()包裹示例,以保证预览渲染的一致性。
h-[400px]Navigation Configuration
导航配置
Define navigation in :
docs-navigation.tstsx
import { BookOpen, Code, Settings } from "lucide-react";
export const docsNavigation = {
groups: [
{
title: "Getting Started",
items: [
{ title: "Introduction", href: "/docs", icon: BookOpen },
{ title: "Installation", href: "/docs/installation", icon: Code },
],
},
{
title: "Components",
items: [
{ title: "Button", href: "/docs/button", icon: Settings },
// Add more components...
],
},
],
};在中定义导航:
docs-navigation.tstsx
import { BookOpen, Code, Settings } from "lucide-react";
export const docsNavigation = {
groups: [
{
title: "快速开始",
items: [
{ title: "介绍", href: "/docs", icon: BookOpen },
{ title: "安装", href: "/docs/installation", icon: Code },
],
},
{
title: "组件",
items: [
{ title: "Button", href: "/docs/button", icon: Settings },
// 添加更多组件...
],
},
],
};Code Highlighting Setup
代码高亮设置
Create :
lib/highlight.tstsx
import { codeToHtml } from "shiki";
export async function highlightCode(code: string, lang = "tsx") {
return codeToHtml(code, {
lang,
themes: {
light: "github-light",
dark: "github-dark",
},
});
}Create :
lib/get-example-source.tstsx
import fs from "fs";
import path from "path";
export function getExampleSource(filename: string): string {
const filePath = path.join(
process.cwd(),
"src/app/docs/_components/examples",
filename
);
let content = fs.readFileSync(filePath, "utf-8");
// Transform import paths for user copy-paste
content = content.replace(
/@\/registry\//g,
"@/components/ui/"
);
return content;
}创建:
lib/highlight.tstsx
import { codeToHtml } from "shiki";
export async function highlightCode(code: string, lang = "tsx") {
return codeToHtml(code, {
lang,
themes: {
light: "github-light",
dark: "github-dark",
},
});
}创建:
lib/get-example-source.tstsx
import fs from "fs";
import path from "path";
export function getExampleSource(filename: string): string {
const filePath = path.join(
process.cwd(),
"src/app/docs/_components/examples",
filename
);
let content = fs.readFileSync(filePath, "utf-8");
// 转换导入路径,方便用户复制粘贴
content = content.replace(
/@\/registry\//g,
"@/components/ui/"
);
return content;
}UI Components
UI组件
The docs system uses these core components:
| Component | Purpose |
|---|---|
| Page wrapper with prev/next nav and TOC |
| Content section with auto-generated slug IDs |
| Page title and description |
| Highlighted callout boxes |
| Inline code styling |
| Styled links with external support |
| API reference tables |
| Live preview with code tab |
| Standalone code display |
本文档系统使用以下核心组件:
| 组件 | 用途 |
|---|---|
| 页面包装器,包含上一页/下一页导航和目录 |
| 内容区块,自动生成锚点ID |
| 页面标题和描述 |
| 高亮提示框 |
| 行内代码样式 |
| 带外部链接支持的样式化链接 |
| API参考表格 |
| 带代码标签页的实时预览组件 |
| 独立代码展示组件 |
Preview System Architecture
预览系统架构
┌─────────────────────────────────────────────┐
│ ComponentPreview (Server Component) │
│ - Receives code string │
│ - Calls highlightCode() with Shiki │
│ - Passes highlighted HTML to client │
└──────────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ ComponentPreviewClient (Client Component) │
│ - Renders tabs: Preview | Code │
│ - Preview tab: renders children │
│ - Code tab: shows highlighted code │
│ - Copy button for code │
└─────────────────────────────────────────────┘┌─────────────────────────────────────────────┐
│ ComponentPreview (Server Component) │
│ - 接收代码字符串 │
│ - 调用Shiki的highlightCode()方法 │
│ - 将高亮后的HTML传递给客户端 │
└──────────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ ComponentPreviewClient (Client Component) │
│ - 渲染标签页:预览 | 代码 │
│ - 预览标签页:渲染子组件 │
│ - 代码标签页:展示高亮后的代码 │
│ - 代码复制按钮 │
└─────────────────────────────────────────────┘Adding a New Documentation Page
添加新文档页面
- Create route directory:
src/app/docs/[page-name]/page.tsx - Create example component if needed:
_components/examples/[name]-example.tsx - Add to navigation in
docs-navigation.ts - Update prev/next links on adjacent pages
- 创建路由目录:
src/app/docs/[page-name]/page.tsx - 若需要,创建示例组件:
_components/examples/[name]-example.tsx - 在中添加导航项
docs-navigation.ts - 更新相邻页面的上一页/下一页链接
Best Practices
最佳实践
- Keep examples focused - One concept per example
- Use fixed heights - for consistent previews
h-[400px] - Transform imports - Change internal paths for user copy-paste
- Include API tables - Document all props with types and defaults
- Add TOC items - List all major sections for scroll tracking
- Mobile-first - Test sidebar collapse and responsive layouts
- 示例聚焦:每个示例只展示一个核心概念
- 使用固定高度:用保证预览一致性
h-[400px] - 转换导入路径:修改内部路径以便用户直接复制使用
- 包含API表格:记录所有属性的类型和默认值
- 添加目录项:列出所有主要章节以支持滚动跟踪
- 移动端优先:测试侧边栏折叠和响应式布局
Common Mistakes
常见错误
| Mistake | Fix |
|---|---|
Calling | Move to Server Component - Shiki requires server-side execution |
| Missing fixed height on examples | Add |
| Using internal import paths in examples | Use |
| Forgetting to update navigation | Always add new pages to |
| Not updating prev/next links | Check adjacent pages when adding/removing docs |
| 错误 | 修复方案 |
|---|---|
在客户端组件中调用 | 移至服务端组件 - Shiki需要在服务端执行 |
| 示例缺少固定高度 | 添加 |
| 示例中使用内部导入路径 | 使用 |
| 忘记更新导航配置 | 务必在 |
| 未更新上一页/下一页链接 | 添加或删除文档时检查相邻页面的链接 |
Troubleshooting
故障排除
| Problem | Solution |
|---|---|
| shadcn/ui not installed | Run |
| Shiki SSR errors | Ensure |
| Dark mode not working | Add |
| Preview height inconsistent | Always use fixed height ( |
| Copy button not working | Ensure HTTPS or localhost (clipboard API requirement) |
| 问题 | 解决方案 |
|---|---|
| shadcn/ui未安装 | 先执行 |
| Shiki SSR错误 | 确保 |
| 暗色主题不生效 | 在Shiki配置中添加 |
| 预览高度不一致 | 始终为示例添加固定高度( |
| 复制按钮无法工作 | 确保使用HTTPS或localhost(剪贴板API的要求) |
Prerequisites Check
前置要求检查
Before using this skill, verify:
- Next.js 13+ with App Router (directory)
app/ - Tailwind CSS configured
- utility from shadcn/ui (
cn())lib/utils.ts
If missing shadcn/ui:
bash
npx shadcn@latest init使用本方案前,请确认:
- 已安装13+版本的Next.js并启用App Router(目录)
app/ - 已配置Tailwind CSS
- 已具备shadcn/ui的工具函数(
cn())lib/utils.ts
若未安装shadcn/ui:
bash
npx shadcn@latest initFile Reference
文件参考
- references/COMPONENTS.md - Complete component implementations
- references/LAYOUT.md - Layout and sidebar setup
- scripts/create-doc-page.sh - Generate new doc pages
- references/COMPONENTS.md - 完整的组件实现
- references/LAYOUT.md - 布局和侧边栏设置
- scripts/create-doc-page.sh - 生成新文档页面的脚本