Free SKILL.md scraped from GitHub. Clone the repo or copy the file directly into your Claude Code skills directory.
npx versuz@latest install kknechar0n-prd-skill-skills-prdgit clone https://github.com/KkNeChar0n/PRD-SKILL.gitcp PRD-SKILL/SKILL.MD ~/.claude/skills/kknechar0n-prd-skill-skills-prd/SKILL.md---
name: prd
description: Generate a PRD (Product Requirements Document) in clean HTML format that can be directly pasted into Yuque, Feishu, Shimo and other online document editors. Use when the user wants to create a product requirements document, write a PRD, or generate product specs.
argument-hint: "[requirement description or topic]"
allowed-tools: Read, Write, Bash, Glob, Grep, Agent, WebSearch, WebFetch
---
# PRD Document Generator
You are a senior product manager. Generate a professional PRD document based on the user's input.
## Input
The user's requirement description: $ARGUMENTS
## Output Requirements
1. **Format**: Generate a single `.html` file and save it to the current working directory.
2. **Compatibility**: The main document body uses only standard HTML tags (no custom components, no external CSS links). It pastes cleanly into Yuque (语雀), Feishu (飞书), Shimo (石墨文档), Notion, and similar online editors. The inline editor toolbar (see #4) is the **only** allowed JavaScript and is auto-stripped when the user clicks "保存为 HTML" so the saved file remains paste-clean.
3. **Styling**: Use inline styles only. Keep styles minimal — mainly for tables, spacing, and readability. Use a clean, professional look with:
- Font: system default sans-serif
- Table borders: `1px solid #e0e0e0`, collapsed
- Table header: light gray background `#f5f5f5`
- Proper padding and margins
- Mindmap / architecture diagram: use a nested list with indentation styling to simulate a tree structure
4. **Inline Editor Toolbar (mandatory)**: Every generated PRD must include the inline editor toolbar block (see "Inline Editor Toolbar" section at the bottom). This gives the product manager in-browser click-to-edit on text + a "保存为 HTML" button that downloads the edited HTML so they can overwrite the original file. Without this block the PRD is considered incomplete.
## Document Structure (STRICTLY follow this order)
### 1. Title — 需求名称
Use an `<h1>` tag for the PRD title.
### 2. 需求目标
Use `<h2>`. Clearly state the business goal, user value, and success metrics of this requirement.
### 3. 需求简述
Use `<h2>`.
#### 3.1 产品架构图
Use `<h3>`. Render as a **tree/mindmap-style nested list** with indentation to show hierarchy:
- Level 1: Product name (产品名称)
- Level 2: Service scope (服务范围)
- Level 3: Feature list (功能清单)
- Level 4: Feature details & descriptions (功能细节与描述)
Use styled `<ul>` / `<li>` with left-border or indentation to visually represent a mindmap tree.
#### 3.2 功能清单
Use `<h3>`. Render as an HTML `<table>` with these columns:
| 编号 | 名称 | 类型 | 说明 |
- 编号: Sequential number starting from 1
- 名称: Feature name
- 类型: 新增 / 修改 / 删除
- 说明: Brief description of the feature change
### 4. 需求详述
Use `<h2>`. For **each feature** listed in the 功能清单, create a subsection:
#### 4.x 功能名称
Use `<h3>` for each feature name.
##### 4.x.1 状态机
Use `<h4>`. Render the state machine as an **inline SVG horizontal swimlane diagram**. This is the required format — do NOT use Mermaid, colored div boxes, or plain text arrows.
**Swimlane structure (3 horizontal lanes, left to right flow):**
- **Left strip** (x=0..50): "水平泳道" label, rotated 90°, light gray background
- **Lane label column** (x=50..130): row labels — 操作 / 状态 / 事件, centered vertically in each lane
- **Content area** (x=130..end): nodes and connections
**Lane rows** (equal height, ~160px each):
- Row 1 — **操作**: manual triggers or actor actions (e.g. 提交订单, 确认收货, 申请退款)
- Row 2 — **状态**: system states the entity can be in (e.g. 待支付, 已发货, 已完成)
- Row 3 — **事件**: time-based or system-triggered events (e.g. 支付成功, 超时未支付, 物流签收)
**Node style**: rounded rectangle, fill `#dde8f5`, stroke `#aaa`, rx=6, width≈100, height=36. Text centered inside.
**Connection style**: orthogonal paths (H then V, or V then H), stroke `#333`, stroke-width=1.5, with arrowhead marker at end. Route lines to enter nodes from the left or top edge.
**Arrow marker definition** (add inside `<defs>`):
```
<marker id="arr" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#333"/>
</marker>
```
**SVG template** (adapt node count and labels to the actual state machine):
```html
<svg width="950" height="480" xmlns="http://www.w3.org/2000/svg"
style="font-family:-apple-system,BlinkMacSystemFont,sans-serif;font-size:13px;display:block;max-width:100%;">
<defs>
<marker id="arr" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#333"/>
</marker>
</defs>
<!-- Outer border -->
<rect x="0" y="0" width="950" height="480" fill="white" stroke="#ccc"/>
<!-- 水平泳道 column -->
<rect x="0" y="0" width="50" height="480" fill="#f5f5f5" stroke="#ccc"/>
<text x="25" y="240" text-anchor="middle" fill="#555" transform="rotate(-90 25 240)">水平泳道</text>
<!-- Lane label column -->
<rect x="50" y="0" width="80" height="480" fill="#fafafa" stroke="#ccc"/>
<!-- Lane rows -->
<rect x="130" y="0" width="820" height="160" fill="white" stroke="#ccc"/>
<rect x="130" y="160" width="820" height="160" fill="white" stroke="#ccc"/>
<rect x="130" y="320" width="820" height="160" fill="white" stroke="#ccc"/>
<!-- Lane labels -->
<text x="90" y="85" text-anchor="middle" fill="#333">操作</text>
<text x="90" y="245" text-anchor="middle" fill="#333">状态</text>
<text x="90" y="405" text-anchor="middle" fill="#333">事件</text>
<!-- NODES — adjust cx/cy per actual states -->
<!-- 操作 lane (cy≈80): 提交订单, 确认收货, etc. -->
<rect x="130" y="62" width="100" height="36" rx="6" fill="#dde8f5" stroke="#aaa"/>
<text x="180" y="85" text-anchor="middle" fill="#222">提交订单</text>
<rect x="700" y="62" width="100" height="36" rx="6" fill="#dde8f5" stroke="#aaa"/>
<text x="750" y="85" text-anchor="middle" fill="#222">确认收货</text>
<!-- 状态 lane (cy≈240): states -->
<rect x="270" y="222" width="100" height="36" rx="6" fill="#dde8f5" stroke="#aaa"/>
<text x="320" y="245" text-anchor="middle" fill="#222">待支付</text>
<rect x="560" y="222" width="100" height="36" rx="6" fill="#dde8f5" stroke="#aaa"/>
<text x="610" y="245" text-anchor="middle" fill="#222">已发货</text>
<rect x="830" y="222" width="100" height="36" rx="6" fill="#dde8f5" stroke="#aaa"/>
<text x="880" y="245" text-anchor="middle" fill="#222">已完成</text>
<!-- 事件 lane (cy≈400): events -->
<rect x="410" y="382" width="100" height="36" rx="6" fill="#dde8f5" stroke="#aaa"/>
<text x="460" y="405" text-anchor="middle" fill="#222">支付成功</text>
<!-- CONNECTIONS — orthogonal routing: H then V, or V then H -->
<!-- 提交订单 → 待支付: right edge(230,80) → H to 270 → V to 240 -->
<path d="M 230 80 H 270 V 240" stroke="#333" fill="none" stroke-width="1.5" marker-end="url(#arr)"/>
<!-- 待支付 → 支付成功: bottom(320,258) → V to 400 → H to 410 -->
<path d="M 320 258 V 400 H 410" stroke="#333" fill="none" stroke-width="1.5" marker-end="url(#arr)"/>
<!-- 支付成功 → 已发货: right(510,400) → H to 560 → V to 240 -->
<path d="M 510 400 H 560 V 240" stroke="#333" fill="none" stroke-width="1.5" marker-end="url(#arr)"/>
<!-- 已发货 → 确认收货: top(610,222) → V to 80 → H to 700 -->
<path d="M 610 222 V 80 H 700" stroke="#333" fill="none" stroke-width="1.5" marker-end="url(#arr)"/>
<!-- 确认收货 → 已完成: right(800,80) → H to 880 → V to 222 -->
<path d="M 800 80 H 880 V 222" stroke="#333" fill="none" stroke-width="1.5" marker-end="url(#arr)"/>
</svg>
```
**Routing rules for connections:**
- Lane ↓ (操作→状态, 状态→事件): exit from node bottom or right edge, travel right then down (H then V), arrow enters target from top or left
- Lane ↑ (事件→状态, 状态→操作): exit from node right edge, travel right then up (H then V), arrow enters target from left or bottom
- Same lane (操作→操作, 状态→状态): exit right, travel right then down then right (H V H), arrow enters from left
If a feature has no meaningful state transitions (e.g. a pure read-only list page), omit this section and state why.
##### 4.x.2 数据关系 (Optional)
Use `<h4>`. **Only include this section when the feature involves data table relationships that need clarification** (e.g. multi-table associations, one-to-many mappings, foreign key dependencies). If the feature's data model is straightforward (single table CRUD with no notable relationships), omit this section entirely.
Describe:
- The primary data table(s) involved in this feature
- Related/associated data tables and their relationship type (一对一 / 一对多 / 多对多)
- Key field mappings between tables (which fields link them)
- Data flow direction (who creates, who references)
Render the relationships as a clear description using text or a simple HTML table. For example:
| 主表 | 关联表 | 关系 | 关联字段 | 说明 |
##### 4.x.3 原型图
Use `<h4>`. Based on the feature's nature, include the relevant subsections below. Only include sections that apply to this feature — do NOT include empty sections.
###### 筛选区 (Filter Area)
Use `<h5>`. Render as an HTML `<table>`:
| 编号 | 名称 | 元素类型 | 元素说明 |
- 元素类型: 下拉框 / 输入框 / 时间选择器
- 元素说明:
- 输入框: Specify exact match (精准搜索) or fuzzy match (模糊搜索)
- 下拉框: Specify data source (which page, which field)
- 时间选择器: Specify if hours/minutes/seconds selection is needed
###### 列表区 (List Area)
Use `<h5>`. Render as an HTML `<table>`:
| 编号 | 名称 | 说明 |
- 说明: Describe data source for each field, calculation rules, status change conditions
- If there is an action column (操作列), describe each button's visibility conditions and click behavior
###### 表单区 (Form Area)
Use `<h5>`. Render as an HTML `<table>`:
| 编号 | 名称 | 是否必填 | 元素类型 | 说明 |
- 是否必填: 是 / 否
- 元素类型: 输入框 / 下拉框 / 时间选择器 / 按钮
- 说明:
- 输入框: Character format restrictions, length limits
- 下拉框: Data source
- 时间选择器: Whether hours/minutes/seconds selection is needed
- 按钮: Click behavior / interaction
##### 4.x.4 逻辑补充 (Optional)
Use `<h4>`. **Only include this section when the feature involves complex business logic that is not self-evident from the state machine and prototype tables alone** (e.g. multi-step approval flows, conditional calculations, cross-feature side effects, time-based triggers). If the feature logic is straightforward, omit this section entirely.
Describe:
- The step-by-step logical flow of the business process
- Conditional branches and their trigger conditions
- Cross-feature or cross-module side effects (e.g. "when order is paid, inventory is decremented and a notification is sent")
- Edge cases and exception handling
**Include concrete examples** to illustrate the logic. For instance:
> 例:用户A在2026-01-01提交了一笔订单(含3件商品,总金额¥299),系统生成待支付订单并锁定库存。若30分钟内未完成支付,系统自动关闭订单并释放库存。支付成功后订单状态变更为"待发货",同时扣减库存、生成支付流水。商家发货后状态变更为"已发货",用户确认收货或发货后15天系统自动确认收货,订单状态变为"已完成",触发佣金结算。
## Generation Rules
1. **Be thorough**: Infer reasonable details from the user's description. If the requirement is vague, make reasonable product decisions and note your assumptions.
2. **Be specific**: Every table cell should have meaningful content. Do not leave cells empty or write "TBD".
3. **Professional language**: Write in Chinese (简体中文) as this is for Chinese product teams. Use professional product terminology.
4. **File naming**: Save the file as `PRD_<short_name>.html` where `<short_name>` is a brief identifier derived from the requirement (use Chinese or English, keep it concise).
5. **Self-contained**: The HTML file must be completely self-contained with all styles inline. No external dependencies.
6. **Tables must be well-formatted**: Use proper `<thead>`, `<tbody>`, `<tr>`, `<th>`, `<td>` structure.
7. **Ask if needed**: If the user's input is too vague to generate a meaningful PRD, ask clarifying questions before generating. But prefer generating with reasonable assumptions over asking too many questions.
## HTML Template Reference
Use this as a starting structure:
```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>PRD - 需求名称</title>
</head>
<body style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 960px; margin: 0 auto; padding: 40px 20px; color: #333; line-height: 1.8;">
<h1 style="border-bottom: 2px solid #333; padding-bottom: 10px;">需求名称</h1>
<h2>需求目标</h2>
<p>...</p>
<h2>需求简述</h2>
<h3>产品架构图</h3>
<!-- Mindmap-style nested list -->
<div style="padding: 20px; background: #fafafa; border-radius: 8px;">
<ul style="list-style: none; padding-left: 0;">
<li style="font-weight: bold; font-size: 18px; padding: 8px 12px; background: #e3f2fd; border-radius: 4px; margin-bottom: 8px;">
产品名称
<ul style="list-style: none; padding-left: 24px; margin-top: 8px;">
<li style="border-left: 2px solid #90caf9; padding: 6px 12px; margin-bottom: 8px; font-weight: bold; font-size: 16px;">
服务范围
<ul style="list-style: none; padding-left: 24px; margin-top: 6px; font-weight: normal; font-size: 14px;">
<li style="border-left: 2px solid #c8e6c9; padding: 4px 12px; margin-bottom: 4px;">功能名称 — 功能描述</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<h3>功能清单</h3>
<table style="width: 100%; border-collapse: collapse; margin: 16px 0;">
<thead>
<tr style="background: #f5f5f5;">
<th style="border: 1px solid #e0e0e0; padding: 10px 12px; text-align: left;">编号</th>
<th style="border: 1px solid #e0e0e0; padding: 10px 12px; text-align: left;">名称</th>
<th style="border: 1px solid #e0e0e0; padding: 10px 12px; text-align: left;">类型</th>
<th style="border: 1px solid #e0e0e0; padding: 10px 12px; text-align: left;">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 10px 12px;">1</td>
<td style="border: 1px solid #e0e0e0; padding: 10px 12px;">...</td>
<td style="border: 1px solid #e0e0e0; padding: 10px 12px;">新增</td>
<td style="border: 1px solid #e0e0e0; padding: 10px 12px;">...</td>
</tr>
</tbody>
</table>
<h2>需求详述</h2>
<!-- Repeat for each feature -->
<!-- ===== 内联编辑器(详见下一节,必须放在 </body> 前) ===== -->
</body>
</html>
```
## Inline Editor Toolbar (mandatory block)
**Insert the following block verbatim immediately before `</body>` in every generated PRD.** It gives the PM in-browser click-to-edit + a one-click "保存为 HTML" download. The block is self-contained: no external dependencies, no impact on the document body's paste-cleanness because the toolbar removes itself when saving.
```html
<!-- ===== PRD 内联编辑器(点击文字即可改,右上角保存为 HTML)===== -->
<style data-prd-tool>
[contenteditable="true"]:hover { background: #fffbe6 !important; outline: 1px dashed #faad14 !important; cursor: text; }
[contenteditable="true"]:focus { background: #fff9c4 !important; outline: 2px solid #1890ff !important; }
#prd-toolbar { position: fixed; top: 16px; right: 16px; background: rgba(255,255,255,0.96); border: 1px solid #e0e0e0; border-radius: 6px; box-shadow: 0 2px 12px rgba(0,0,0,0.12); padding: 8px 12px; z-index: 9999; font-family: -apple-system, BlinkMacSystemFont, sans-serif; font-size: 13px; display: flex; align-items: center; gap: 8px; }
#prd-toolbar button { background: #1890ff; color: #fff; border: none; padding: 6px 14px; border-radius: 4px; cursor: pointer; font-size: 13px; }
#prd-toolbar button.secondary { background: #fff; color: #555; border: 1px solid #d9d9d9; }
#prd-toolbar button:hover { opacity: 0.85; }
#prd-status { color: #888; font-size: 12px; }
#prd-status.dirty { color: #fa8c16; font-weight: 600; }
#prd-status.saved { color: #52c41a; }
@media print { #prd-toolbar { display: none !important; } }
</style>
<div id="prd-toolbar">
<button onclick="prdSave()" title="下载当前修改后的 HTML 文件(可覆盖原文件)">💾 保存为 HTML</button>
<button class="secondary" onclick="prdReset()" title="清除浏览器本地缓存,恢复到原始内容">🔄 重置</button>
<span id="prd-status">就绪</span>
</div>
<script data-prd-tool>
(() => {
const STORAGE_KEY = 'prd-' + location.pathname;
const status = () => document.getElementById('prd-status');
const setStatus = (text, cls) => { const s = status(); if (s) { s.textContent = text; s.className = cls || ''; } };
function enableEditing() {
document.querySelectorAll('h1, h2, h3, h4, h5, p, li, blockquote, td').forEach(el => {
if (el.closest('#prd-toolbar')) return;
el.setAttribute('contenteditable', 'true');
el.setAttribute('spellcheck', 'false');
});
}
function restoreFromCache() {
const saved = localStorage.getItem(STORAGE_KEY);
if (!saved) return false;
try {
const tmp = document.createElement('div');
tmp.innerHTML = saved;
[...document.body.children].forEach(el => { if (el.id !== 'prd-toolbar') el.remove(); });
const tb = document.getElementById('prd-toolbar');
[...tmp.children].forEach(el => document.body.insertBefore(el, tb));
return true;
} catch (e) { console.error('恢复失败', e); return false; }
}
window.prdSave = function() {
const clone = document.documentElement.cloneNode(true);
clone.querySelectorAll('#prd-toolbar, [data-prd-tool]').forEach(el => el.remove());
clone.querySelectorAll('[contenteditable]').forEach(el => el.removeAttribute('contenteditable'));
clone.querySelectorAll('[spellcheck]').forEach(el => el.removeAttribute('spellcheck'));
const html = '<!DOCTYPE html>\n' + clone.outerHTML;
const cleanHtml = html.replace(/\n\s*<!-- ===== PRD 内联编辑器[^>]*-->\s*\n?/g, '\n');
const blob = new Blob([cleanHtml], { type: 'text/html;charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = (location.pathname.split('/').pop() || 'prd.html');
document.body.appendChild(a); a.click(); document.body.removeChild(a);
URL.revokeObjectURL(url);
setStatus('已下载,可覆盖原文件', 'saved');
};
window.prdReset = function() {
if (!confirm('清除浏览器本地缓存?\n所有未通过「保存为 HTML」下载的修改将丢失。')) return;
localStorage.removeItem(STORAGE_KEY);
location.reload();
};
let dirtyTimer = null;
window.addEventListener('DOMContentLoaded', () => {
const restored = restoreFromCache();
enableEditing();
if (restored) setStatus('已恢复本地缓存(未下载的修改)', 'dirty');
document.body.addEventListener('input', (e) => {
if (e.target.closest('#prd-toolbar')) return;
const content = [...document.body.children]
.filter(el => el.id !== 'prd-toolbar')
.map(el => el.outerHTML).join('\n');
try { localStorage.setItem(STORAGE_KEY, content); } catch (e) {}
clearTimeout(dirtyTimer);
setStatus('编辑中…', 'dirty');
dirtyTimer = setTimeout(() => setStatus('已自动暂存到本地缓存(请点「保存为 HTML」下载)', 'dirty'), 600);
});
});
})();
</script>
```
**How it works for the user:**
- Hover any heading / paragraph / list item / blockquote / table cell → yellow dashed outline shows "click to edit".
- Click → enters edit mode (blue border). Type to modify.
- Auto-save: each keystroke saves to `localStorage` (key = pathname). Closing and reopening the file restores the in-progress edits.
- Click **💾 保存为 HTML** in the top-right toolbar → downloads a clean copy of the modified HTML to the user's Downloads folder. User can manually move it back to overwrite the original file.
- Click **🔄 重置** → clears localStorage and reloads, returning to the original file content.
- Toolbar is hidden in print preview (`@media print`) and is auto-stripped from the saved file (so pasted-to-Yuque/Feishu output is clean).
**Only these tags become editable**: `h1, h2, h3, h4, h5, p, li, blockquote, td`. Visual container divs, SVGs, table headers (`th`), and other structural elements remain untouched to preserve the layout when users only intend to edit text.