Refactor project name from "Open Claude Design" to "Open Design"

- Updated project name in package.json, package-lock.json, and README files.
- Changed CLI commands and references from "ocd" to "od".
- Adjusted file structure references in documentation and code to reflect new naming conventions.
- Enhanced .gitignore to include new runtime data files.
- Updated metadata in LICENSE file to match new project name.
This commit is contained in:
pftom
2026-04-28 14:48:45 +08:00
parent a98096a042
commit af3f96379a
122 changed files with 952 additions and 474 deletions
+9
View File
@@ -3,7 +3,16 @@ dist
.DS_Store
*.log
.vite
# Local runtime data — auto-created by the daemon on first start.
# Holds app.sqlite (project metadata), projects/<id>/ (per-project artifacts,
# the agent's CWD), and artifacts/ (one-off renders). Never commit.
.od
# Legacy folder name from before the rename; keep ignored so existing
# clones don't accidentally stage stale runtime data.
.ocd
tsconfig.tsbuildinfo
.claude-sessions/*
+1 -1
View File
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2026 Open Claude Design contributors
Copyright 2026 Open Design contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
+8 -5
View File
@@ -10,7 +10,7 @@ npm run dev:all # starts daemon (:7456) + Vite (:5173) together
open http://localhost:5173
```
On first load, the app detects your installed code-agent CLI (Claude Code / Codex / Gemini / OpenCode / Cursor Agent / Qwen), picks it automatically, and defaults to `web-prototype` skill + `Neutral Modern` design system. Type a prompt and hit **Send**. The agent streams into the left pane; the `<artifact>` tag is parsed out and the HTML renders live on the right. When it finishes, click **Save to disk** to persist the artifact under `./.ocd/artifacts/<timestamp>-<slug>/index.html`.
On first load, the app detects your installed code-agent CLI (Claude Code / Codex / Gemini / OpenCode / Cursor Agent / Qwen), picks it automatically, and defaults to `web-prototype` skill + `Neutral Modern` design system. Type a prompt and hit **Send**. The agent streams into the left pane; the `<artifact>` tag is parsed out and the HTML renders live on the right. When it finishes, click **Save to disk** to persist the artifact under `./.od/artifacts/<timestamp>-<slug>/index.html`.
The **Design system** dropdown ships with 71 built-in systems — 2 hand-authored starters (Neutral Modern, Warm Editorial) and 69 product systems imported from [`awesome-design-md`](https://github.com/VoltAgent/awesome-design-md), grouped by category (AI & LLM, Developer Tools, Productivity, Backend, Design Tools, Fintech, E-Commerce, Media, Automotive). Pick one to skin every prototype in that brand's aesthetic.
@@ -57,9 +57,9 @@ Swap the skill or the design system in the top bar and the next send uses the ne
## File map
```
open-claude-design/
open-design/
├── daemon/ # Node/Express — spawns local agents + serves APIs
│ ├── cli.js # `ocd` bin entry (also used by npm scripts)
│ ├── cli.js # `od` bin entry (also used by npm scripts)
│ ├── server.js # /api/agents /api/skills /api/design-systems /api/chat /api/upload /api/artifacts/save
│ ├── agents.js # PATH scanner for claude/codex/gemini/opencode/cursor-agent/qwen
│ ├── skills.js # SKILL.md loader (frontmatter parser)
@@ -96,7 +96,10 @@ open-claude-design/
│ ├── components/ # ChatPane, PreviewPane, AgentPicker, SkillPicker, DesignSystemPicker, SettingsDialog
│ └── state/config.ts # localStorage persistence
├── docs/ # product vision + spec
├── .ocd/artifacts/ # saved HTML outputs (gitignored)
├── .od/ # runtime data (gitignored, auto-created)
│ ├── app.sqlite # projects / conversations / messages / tabs
│ ├── artifacts/ # one-off "Save to disk" renders
│ └── projects/<id>/ # per-project working dir + agent cwd
└── vite.config.ts # /api proxy to :7456
```
@@ -111,6 +114,6 @@ open-claude-design/
This Quickstart is the runnable seed of the spec in [`docs/`](docs/). The spec describes where this grows (see [`docs/roadmap.md`](docs/roadmap.md)). Highlights:
- `docs/architecture.md` proposes Next.js; we picked Vite for a simpler dev loop. The daemon contract is identical, so migrating is a port, not a rewrite.
- `docs/skills-protocol.md` describes the full `ocd:` frontmatter (typed inputs, sliders, capability gating). This MVP reads `name` / `description` / `triggers` / `ocd.mode` / `ocd.design_system.requires` only — extend `daemon/skills.js` to add the rest.
- `docs/skills-protocol.md` describes the full `od:` frontmatter (typed inputs, sliders, capability gating). This MVP reads `name` / `description` / `triggers` / `od.mode` / `od.design_system.requires` only — extend `daemon/skills.js` to add the rest.
- `docs/agent-adapters.md` foresees richer dispatch (capability detection, streaming tool-calls). Our `daemon/agents.js` is a minimal dispatcher — enough to prove the wiring.
- `docs/modes.md` lists four modes: prototype / deck / template / design-system. We ship skills for the first two; the picker already filters by `mode`.
+52 -34
View File
@@ -1,9 +1,9 @@
# Open Claude Design
# Open Design
> **Claude Code, but for design.** A local-first, web-deployable open replica of Anthropic's [Claude Design][cd] — your existing coding agent (Claude Code, Codex, Cursor Agent, Gemini CLI, OpenCode, Qwen) becomes the design engine, driven by composable **Skills** and **71 brand-grade Design Systems**.
<p align="center">
<img src="docs/assets/banner.png" alt="Open Claude Design banner" width="100%" />
<img src="docs/assets/banner.svg" alt="Open Design banner — placeholder, replace with the live UI hero shot" width="100%" />
</p>
<p align="center">
@@ -22,13 +22,13 @@
Anthropic's [Claude Design][cd] (released 2026-04-17, Opus 4.7) showed what happens when an LLM stops writing prose and starts shipping design artifacts. It went viral — and stayed closed, paid-only, cloud-only, locked to Anthropic's model and Anthropic's skills.
**Open Claude Design (OCD) is the open substrate.** We don't build an agent — the strongest coding agents already live on your laptop. We wire them into a skill-driven design workflow that runs on `pnpm dev`, deploys to Vercel, and stays BYOK at every layer.
**Open Design (OD) is the open substrate.** We don't build an agent — the strongest coding agents already live on your laptop. We wire them into a skill-driven design workflow that runs on `pnpm dev`, deploys to Vercel, and stays BYOK at every layer.
Type `make me a magazine-style pitch deck for our seed round`. The interactive question form pops up before the model improvises a single pixel. The agent picks one of five curated visual directions. A live `TodoWrite` plan streams into the UI. The daemon builds a real on-disk project folder with a seed template, layout library, and self-check checklist. The agent reads them — pre-flight enforced — runs a five-dimensional critique against its own output, and emits a single `<artifact>` that renders in a sandboxed iframe seconds later.
That's not "AI tries to design something". That's an AI that has been trained, by the prompt stack, to behave like a senior designer with a working filesystem, a deterministic palette library, and a checklist culture.
OCD stands on four open-source shoulders:
OD stands on four open-source shoulders:
- [**`alchaincyf/huashu-design`**](https://github.com/alchaincyf/huashu-design) — the design-philosophy compass. Junior-Designer workflow, the 5-step brand-asset protocol, the anti-AI-slop checklist, the 5-dimensional self-critique, and the "5 schools × 20 design philosophies" idea behind our direction picker — all distilled into [`src/prompts/discovery.ts`](src/prompts/discovery.ts).
- [**`op7418/guizang-ppt-skill`**](https://github.com/op7418/guizang-ppt-skill) — the deck mode. Bundled verbatim under [`skills/guizang-ppt/`](skills/guizang-ppt/) with original LICENSE preserved; magazine-style layouts, WebGL hero, P0/P1/P2 checklists.
@@ -52,46 +52,46 @@ OCD stands on four open-source shoulders:
## Demo
> Screenshots are placeholders — the live UI is what the screenshots will be of. Replace the `docs/screenshots/*.png` files in PR.
> **Screenshots pending.** Every card below is a placeholder SVG — replace `docs/screenshots/*.svg` with real `.png`/`.jpg` captures and bump the `<img src=…>` extension when you do.
<table>
<tr>
<td width="50%">
<img src="docs/screenshots/01-entry-view.png" alt="Entry view: pick skill + design system + brief" /><br/>
<img src="docs/screenshots/01-entry-view.svg" alt="01 · Entry view — placeholder, replace with the real screenshot" /><br/>
<sub><b>Entry view</b> — pick a skill, pick a design system, type the brief. The same surface for prototypes, decks, mobile apps, dashboards, and editorial pages.</sub>
</td>
<td width="50%">
<img src="docs/screenshots/02-question-form.png" alt="Turn-1 discovery question form" /><br/>
<sub><b>Turn-1 discovery form</b> — before the model writes a pixel, OCD locks the brief: surface, audience, tone, brand context, scale. 30 seconds of radios beats 30 minutes of redirects.</sub>
<img src="docs/screenshots/02-question-form.svg" alt="02 · Discovery form — placeholder, replace with the real screenshot" /><br/>
<sub><b>Turn-1 discovery form</b> — before the model writes a pixel, OD locks the brief: surface, audience, tone, brand context, scale. 30 seconds of radios beats 30 minutes of redirects.</sub>
</td>
</tr>
<tr>
<td width="50%">
<img src="docs/screenshots/03-direction-picker.png" alt="Direction picker — 5 deterministic visual directions" /><br/>
<img src="docs/screenshots/03-direction-picker.svg" alt="03 · Direction picker — placeholder, replace with the real screenshot" /><br/>
<sub><b>Direction picker</b> — when the user has no brand, the agent emits a second form with 5 curated directions (Monocle / Modern Minimal / Tech Utility / Brutalist / Soft Warm). One radio click → a deterministic palette + font stack, no model freestyle.</sub>
</td>
<td width="50%">
<img src="docs/screenshots/04-todo-progress.png" alt="Live TodoWrite plan streaming into the UI" /><br/>
<img src="docs/screenshots/04-todo-progress.svg" alt="04 · Live todo progress — placeholder, replace with the real screenshot" /><br/>
<sub><b>Live todo progress</b> — the agent's plan streams as a live card. <code>in_progress</code> → <code>completed</code> updates land in real time. The user can redirect cheaply, mid-flight.</sub>
</td>
</tr>
<tr>
<td width="50%">
<img src="docs/screenshots/05-preview-iframe.png" alt="Sandboxed iframe preview of the generated artifact" /><br/>
<img src="docs/screenshots/05-preview-iframe.svg" alt="05 · Sandboxed preview — placeholder, replace with the real screenshot" /><br/>
<sub><b>Sandboxed preview</b> — every <code>&lt;artifact&gt;</code> renders in a clean srcdoc iframe. Editable in place via the file workspace; downloadable as HTML, PDF, ZIP.</sub>
</td>
<td width="50%">
<img src="docs/screenshots/06-design-systems-library.png" alt="71-system design-system library with palette swatches" /><br/>
<img src="docs/screenshots/06-design-systems-library.svg" alt="06 · 71-system library — placeholder, replace with the real screenshot" /><br/>
<sub><b>71-system library</b> — every product system shows its 4-color signature. Click for the full <code>DESIGN.md</code>, swatch grid, and live showcase.</sub>
</td>
</tr>
<tr>
<td width="50%">
<img src="docs/screenshots/07-magazine-deck.png" alt="Magazine-style horizontal deck output" /><br/>
<img src="docs/screenshots/07-magazine-deck.svg" alt="07 · Magazine deck — placeholder, replace with the real screenshot" /><br/>
<sub><b>Deck mode (guizang-ppt)</b> — the bundled <a href="https://github.com/op7418/guizang-ppt-skill"><code>guizang-ppt-skill</code></a> drops in unchanged. Magazine layouts, WebGL hero backgrounds, single-file HTML output, PDF export.</sub>
</td>
<td width="50%">
<img src="docs/screenshots/08-mobile-app.png" alt="Mobile app prototype with iPhone 15 Pro frame" /><br/>
<img src="docs/screenshots/08-mobile-app.svg" alt="08 · Mobile prototype — placeholder, replace with the real screenshot" /><br/>
<sub><b>Mobile prototype</b> — pixel-accurate iPhone 15 Pro chrome (Dynamic Island, status bar SVGs, home indicator). Multi-screen prototypes use the shared <code>/frames/</code> assets so the agent never re-draws a phone.</sub>
</td>
</tr>
@@ -113,13 +113,13 @@ The 9-section `DESIGN.md` schema from [`VoltAgent/awesome-design-md`][acd2] —
### 4 · The interactive question form prevents 80% of redirects.
OCD's prompt stack hard-codes a `RULE 1`: every fresh design brief begins with a `<question-form id="discovery">` instead of code. Surface · audience · tone · brand context · scale · constraints. A long brief still leaves design decisions open — visual tone, color stance, scale — exactly the things the form locks down in 30 seconds. The cost of a wrong direction is one chat round, not one finished deck.
OD's prompt stack hard-codes a `RULE 1`: every fresh design brief begins with a `<question-form id="discovery">` instead of code. Surface · audience · tone · brand context · scale · constraints. A long brief still leaves design decisions open — visual tone, color stance, scale — exactly the things the form locks down in 30 seconds. The cost of a wrong direction is one chat round, not one finished deck.
This is the **Junior-Designer mode** distilled from [`huashu-design`](https://github.com/alchaincyf/huashu-design): batch the questions up front, show something visible early (even a wireframe with grey blocks), let the user redirect cheaply. Combined with the brand-asset protocol (locate · download · `grep` hex · write `brand-spec.md` · vocalise), it's the single biggest reason output stops feeling like AI freestyle and starts feeling like a designer who paid attention before painting.
### 5 · The daemon makes the agent feel like it's on your laptop, because it is.
The daemon spawns the CLI with `cwd` set to the project's artifact folder under `.ocd/projects/<id>/`. The agent gets `Read`, `Write`, `Bash`, `WebFetch` — real tools against a real filesystem. It can `Read` the skill's `assets/template.html`, `grep` your CSS for hex values, write a `brand-spec.md`, drop generated images, and produce `.pptx` / `.zip` / `.pdf` files that show up in the file workspace as download chips when the turn ends. Sessions, conversations, messages, tabs persist in a local SQLite DB — pop the project open tomorrow and the agent's todo card is right where you left it.
The daemon spawns the CLI with `cwd` set to the project's artifact folder under `.od/projects/<id>/`. The agent gets `Read`, `Write`, `Bash`, `WebFetch` — real tools against a real filesystem. It can `Read` the skill's `assets/template.html`, `grep` your CSS for hex values, write a `brand-spec.md`, drop generated images, and produce `.pptx` / `.zip` / `.pdf` files that show up in the file workspace as download chips when the turn ends. Sessions, conversations, messages, tabs persist in a local SQLite DB — pop the project open tomorrow and the agent's todo card is right where you left it.
### 6 · The prompt stack is the product.
@@ -158,7 +158,7 @@ Every layer is composable. Every layer is a file you can edit. Read [`src/prompt
│ /api/chat (SSE) │
│ │
└─────────┬────────────┘
│ spawn(cli, [...], { cwd: .ocd/projects/<id> })
│ spawn(cli, [...], { cwd: .od/projects/<id> })
┌──────────────────────────────────────────────────────────┐
│ claude · codex · cursor-agent · gemini · opencode · qwen│
@@ -171,15 +171,15 @@ Every layer is composable. Every layer is a file you can edit. Read [`src/prompt
| Frontend | Vite 5 + React 18 + TypeScript |
| Daemon | Node 18+ · Express · SSE streaming · `better-sqlite3` for projects/conversations/messages/tabs |
| Agent transport | `child_process.spawn` with `claude-stream-json` parser for Claude Code, line-buffered plain stdout for the rest |
| Storage | Plain files in `.ocd/projects/<id>/` + SQLite at `.ocd/db.sqlite` (gitignored) |
| Storage | Plain files in `.od/projects/<id>/` + SQLite at `.od/db.sqlite` (gitignored) |
| Preview | Sandboxed iframe via `srcdoc` + per-skill `<artifact>` parser |
| Export | HTML (inline assets) · PDF (browser print) · PPTX (skill-defined) · ZIP (archiver) |
## Quickstart
```bash
git clone https://github.com/<your-org>/open-claude-design.git
cd open-claude-design
git clone https://github.com/nexu-io/open-design.git
cd open-design
pnpm install # or npm install
pnpm dev:all # daemon (:7456) + Vite (:5173)
open http://localhost:5173
@@ -190,22 +190,40 @@ The first load:
1. Detects which agent CLIs you have on `PATH` and picks one automatically.
2. Loads 19 skills + 71 design systems.
3. Pops the welcome dialog so you can paste an Anthropic key (only needed for the BYOK fallback path).
4. **Auto-creates `./.od/`** — the local runtime folder for the SQLite project DB, per-project artifacts, and saved renders. There is no `od init` step; the daemon `mkdir`s everything it needs on boot.
Type a prompt, hit **Send**, watch the question form arrive, fill it, watch the todo card stream, watch the artifact render. Click **Save to disk** or download as a project ZIP.
### First-run state (`./.od/`)
The daemon owns one hidden folder at the repo root. Everything in it is gitignored and machine-local — never commit it.
```
.od/
├── app.sqlite ← projects · conversations · messages · open tabs
├── artifacts/ ← one-off "Save to disk" renders (timestamped)
└── projects/<id>/ ← per-project working dir, also the agent's cwd
```
| Want to… | Do this |
|---|---|
| Inspect what's in there | `ls -la .od && sqlite3 .od/app.sqlite '.tables'` |
| Reset to a clean slate | stop the daemon, `rm -rf .od`, run `pnpm dev:all` again |
| Move it elsewhere | not supported yet — the path is hard-coded relative to the repo |
Full file map, scripts, and troubleshooting → [`QUICKSTART.md`](QUICKSTART.md).
## Repository structure
```
open-claude-design/
open-design/
├── README.md ← this file
├── README.zh-CN.md ← 简体中文
├── QUICKSTART.md ← run / build / deploy guide
├── package.json ← pnpm workspace, single bin: ocd
├── package.json ← pnpm workspace, single bin: od
├── daemon/ ← Node + Express, the only server
│ ├── cli.js ← `ocd` bin entry point
│ ├── cli.js ← `od` bin entry point
│ ├── server.js ← /api/* routes (projects, chat, files, exports)
│ ├── agents.js ← PATH scanner + per-CLI argv builders
│ ├── claude-stream.js ← streaming JSON parser for Claude Code stdout
@@ -288,7 +306,7 @@ open-claude-design/
├── docs/
│ ├── spec.md ← product spec, scenarios, differentiation
│ ├── architecture.md ← topologies, data flow, components
│ ├── skills-protocol.md ← extended SKILL.md ocd: frontmatter
│ ├── skills-protocol.md ← extended SKILL.md od: frontmatter
│ ├── agent-adapters.md ← per-CLI detection + dispatch
│ ├── modes.md ← prototype / deck / template / design-system
│ ├── references.md ← long-form provenance
@@ -296,15 +314,15 @@ open-claude-design/
│ ├── schemas/ ← JSON schemas
│ └── examples/ ← canonical artifact examples
└── .ocd/ ← runtime data, gitignored
└── .od/ ← runtime data, gitignored, auto-created
├── app.sqlite ← projects / conversations / messages / tabs
├── projects/<id>/ ← per-project working folder (agent's cwd)
── artifacts/ ← saved one-off renders
└── db.sqlite ← projects / conversations / messages / tabs
── artifacts/ ← saved one-off renders
```
## Skills
19 skills ship in the box. Each is a folder under [`skills/`](skills/) following the Claude Code [`SKILL.md`][skill] convention with an extended `ocd:` frontmatter (`mode`, `platform`, `scenario`, `preview`, `design_system`).
19 skills ship in the box. Each is a folder under [`skills/`](skills/) following the Claude Code [`SKILL.md`][skill] convention with an extended `od:` frontmatter (`mode`, `platform`, `scenario`, `preview`, `design_system`).
### Showcase examples
@@ -354,7 +372,7 @@ Adding a skill takes one folder. Read [`docs/skills-protocol.md`](docs/skills-pr
## Design Systems
<p align="center">
<img src="docs/assets/design-systems-library.png" alt="71 design systems library" width="100%" />
<img src="docs/assets/design-systems-library.svg" alt="71 design systems library — placeholder, replace with the real screenshot" width="100%" />
</p>
71 systems out of the box, each as a single [`DESIGN.md`](design-systems/README.md):
@@ -386,7 +404,7 @@ The library is imported via [`scripts/sync-design-systems.mjs`](scripts/sync-des
## Visual directions
When the user has no brand spec, the agent emits a second form with five curated directions — the OCD adaptation of [`huashu-design`'s "5 schools × 20 design philosophies" fallback](https://github.com/alchaincyf/huashu-design#%E8%AE%BE%E8%AE%A1%E6%96%B9%E5%90%91%E9%A1%BE%E9%97%AE-fallback). Each direction is a deterministic spec — palette in OKLch, font stack, layout posture cues, references — that the agent binds verbatim into the seed template's `:root`. One radio click → a fully specified visual system. No improvisation, no AI-slop.
When the user has no brand spec, the agent emits a second form with five curated directions — the OD adaptation of [`huashu-design`'s "5 schools × 20 design philosophies" fallback](https://github.com/alchaincyf/huashu-design#%E8%AE%BE%E8%AE%A1%E6%96%B9%E5%90%91%E9%A1%BE%E9%97%AE-fallback). Each direction is a deterministic spec — palette in OKLch, font stack, layout posture cues, references — that the agent binds verbatim into the seed template's `:root`. One radio click → a fully specified visual system. No improvisation, no AI-slop.
| Direction | Mood | Refs |
|---|---|---|
@@ -400,7 +418,7 @@ Full spec → [`src/prompts/directions.ts`](src/prompts/directions.ts).
## Anti-AI-slop machinery
The whole machinery below is the [`huashu-design`](https://github.com/alchaincyf/huashu-design) playbook, ported into OCD's prompt-stack and made enforceable per-skill via the side-file pre-flight. Read [`src/prompts/discovery.ts`](src/prompts/discovery.ts) for the live wording:
The whole machinery below is the [`huashu-design`](https://github.com/alchaincyf/huashu-design) playbook, ported into OD's prompt-stack and made enforceable per-skill via the side-file pre-flight. Read [`src/prompts/discovery.ts`](src/prompts/discovery.ts) for the live wording:
- **Question form first.** Turn 1 is `<question-form>` only — no thinking, no tools, no narration. The user chooses defaults at radio speed.
- **Brand-spec extraction.** When the user attaches a screenshot or URL, the agent runs a five-step protocol (locate · download · grep hex · codify `brand-spec.md` · vocalise) before writing CSS. **Never guesses brand colors from memory.**
@@ -411,7 +429,7 @@ The whole machinery below is the [`huashu-design`](https://github.com/alchaincyf
## Comparison
| Axis | [Claude Design][cd] (Anthropic) | [Open CoDesign][ocod] | **Open Claude Design** |
| Axis | [Claude Design][cd] (Anthropic) | [Open CoDesign][ocod] | **Open Design** |
|---|---|---|---|
| License | Closed | MIT | **Apache-2.0** |
| Form factor | Web (claude.ai) | Desktop (Electron) | **Web app + local daemon** |
@@ -481,8 +499,8 @@ Long-form provenance write-up — what we take from each, what we deliberately d
- [ ] Comment-mode surgical edits (click element → instruction → patch) — pattern from [`open-codesign`][ocod]
- [ ] AI-emitted tweaks panel (model surfaces the parameters worth tweaking) — pattern from [`open-codesign`][ocod]
- [ ] Vercel + tunnel deployment recipe (Topology B)
- [ ] One-command `npx ocd init` to scaffold a project with `DESIGN.md`
- [ ] Skill marketplace (`ocd skills install <github-repo>`)
- [ ] One-command `npx od init` to scaffold a project with `DESIGN.md`
- [ ] Skill marketplace (`od skills install <github-repo>`)
Phased delivery → [`docs/roadmap.md`](docs/roadmap.md).
+52 -34
View File
@@ -1,9 +1,9 @@
# Open Claude Design
# Open Design
> **给设计的 Claude Code。** 一个本地优先、可部署到 Vercel 的开源 [Claude Design][cd] 复刻 —— 你机器上已经装好的 coding agentClaude Code、Codex、Cursor Agent、Gemini CLI、OpenCode、Qwen)就是设计引擎,由可组合的 **Skills** 和 **71 套品牌级 Design System** 驱动。
<p align="center">
<img src="docs/assets/banner.png" alt="Open Claude Design banner" width="100%" />
<img src="docs/assets/banner.svg" alt="Open Design banner —— 占位图,等待替换为真实产品截图" width="100%" />
</p>
<p align="center">
@@ -22,13 +22,13 @@
Anthropic 的 [Claude Design][cd]2026-04-17 发布,基于 Opus 4.7)让大家第一次看到:当一个 LLM 不再写废话、开始直接交付设计成品,会是什么样子。它瞬间出圈 —— 然后保持闭源、付费、只跑在云上、绑定 Anthropic 的模型和 Anthropic 的内部 skill。
**Open Claude DesignOCD)是它的开源底座。** 我们不做 agent —— 你笔记本上最强的 coding agent 已经装好了。我们要做的,是把它接进一个 skill 驱动的设计工作流,跑在一个普通的 Web 应用里:本地 `pnpm dev`,云端 `vercel deploy`,每一层都 BYOK(自带 Key)。
**Open DesignOD)是它的开源底座。** 我们不做 agent —— 你笔记本上最强的 coding agent 已经装好了。我们要做的,是把它接进一个 skill 驱动的设计工作流,跑在一个普通的 Web 应用里:本地 `pnpm dev`,云端 `vercel deploy`,每一层都 BYOK(自带 Key)。
输入「帮我做一份杂志风的种子轮 pitch deck」。在模型挥洒第一个像素之前,**初始化问题表单**已经先跳出来。Agent 从 5 套精挑的视觉方向里选一个。一张活的 `TodoWrite` 计划卡片实时流入 UI。Daemon 在磁盘上构建出一个真实的项目目录,里面有 seed 模板、布局库、自检 checklist。Agent **强制 pre-flight** 读取它们,对自己的输出跑一轮**五维评审**,几秒后吐出一个 `<artifact>`,渲染在沙盒 iframe 里。
这不是「AI 试图做点设计」。这是一个被提示词栈训练得像高级设计师一样工作的 AI —— 有可用的文件系统、有确定性的色板库、有 checklist 文化。
OCD 站在四个开源项目的肩膀上:
OD 站在四个开源项目的肩膀上:
- [**`alchaincyf/huashu-design`**(花叔的画术)](https://github.com/alchaincyf/huashu-design) —— 设计哲学的指南针。Junior-Designer 工作流、5 步品牌资产协议、anti-AI-slop checklist、五维自评审、以及方向选择器背后的「5 流派 × 20 种设计哲学」思路 —— 全部蒸馏进 [`src/prompts/discovery.ts`](src/prompts/discovery.ts)。
- [**`op7418/guizang-ppt-skill`**(歸藏的杂志风 PPT skill](https://github.com/op7418/guizang-ppt-skill) —— Deck 模式。原样捆绑在 [`skills/guizang-ppt/`](skills/guizang-ppt/) 下,原 LICENSE 保留;杂志版式、WebGL hero、P0/P1/P2 checklist。
@@ -52,46 +52,46 @@ OCD 站在四个开源项目的肩膀上:
## 效果展示
> 截图位为占位 —— 真实 UI 就是这些截图要拍的对象,请在 PR 里替换 `docs/screenshots/*.png`
> **截图位待补。** 下方每张卡片都是占位 SVG —— 截好真实图后把 `docs/screenshots/*.svg` 替换为 `.png` / `.jpg`,并把对应 `<img src=…>` 的扩展名同步改掉即可
<table>
<tr>
<td width="50%">
<img src="docs/screenshots/01-entry-view.png" alt="入口页:选 skill + 选 design system + 写需求" /><br/>
<img src="docs/screenshots/01-entry-view.svg" alt="01 · 入口页 —— 占位图,等待替换为真实截图" /><br/>
<sub><b>入口页</b> —— 选 skill、选 design system、写一行需求。同一个表面服务原型、deck、移动端、dashboard、editorial 页面所有 mode。</sub>
</td>
<td width="50%">
<img src="docs/screenshots/02-question-form.png" alt="第一轮 discovery 表单" /><br/>
<sub><b>初始化问题表单</b> —— 模型动笔之前,OCD 先把需求锁住:surface、受众、调性、品牌上下文、规模。30 秒勾选项秒杀 30 分钟来回返工。</sub>
<img src="docs/screenshots/02-question-form.svg" alt="02 · 初始化问题表单 —— 占位图,等待替换为真实截图" /><br/>
<sub><b>初始化问题表单</b> —— 模型动笔之前,OD 先把需求锁住:surface、受众、调性、品牌上下文、规模。30 秒勾选项秒杀 30 分钟来回返工。</sub>
</td>
</tr>
<tr>
<td width="50%">
<img src="docs/screenshots/03-direction-picker.png" alt="5 套确定性视觉方向选择器" /><br/>
<img src="docs/screenshots/03-direction-picker.svg" alt="03 · 方向选择器 —— 占位图,等待替换为真实截图" /><br/>
<sub><b>方向选择器</b> —— 用户没有品牌上下文时,agent 自动跳第二个表单,5 套精选方向(Monocle / Modern Minimal / Tech Utility / Brutalist / Soft Warm)一个 radio 选完,色板 + 字体栈直接锁定,没有 freestyle 空间。</sub>
</td>
<td width="50%">
<img src="docs/screenshots/04-todo-progress.png" alt="Live TodoWrite 进度卡片" /><br/>
<img src="docs/screenshots/04-todo-progress.svg" alt="04 · 实时 todo 进度 —— 占位图,等待替换为真实截图" /><br/>
<sub><b>实时 todo 进度</b> —— Agent 的计划以活卡片形式流入 UI。<code>in_progress</code> → <code>completed</code> 实时切换。用户能在中途以极低成本介入纠偏。</sub>
</td>
</tr>
<tr>
<td width="50%">
<img src="docs/screenshots/05-preview-iframe.png" alt="沙盒 iframe 预览生成的 artifact" /><br/>
<img src="docs/screenshots/05-preview-iframe.svg" alt="05 · 沙盒预览 —— 占位图,等待替换为真实截图" /><br/>
<sub><b>沙盒预览</b> —— 每个 <code>&lt;artifact&gt;</code> 都在干净的 srcdoc iframe 里渲染。可在文件工作区里就地编辑;可下载为 HTML / PDF / ZIP。</sub>
</td>
<td width="50%">
<img src="docs/screenshots/06-design-systems-library.png" alt="71 套 design system 库 + 调色板" /><br/>
<img src="docs/screenshots/06-design-systems-library.svg" alt="06 · 71 套 design system 库 —— 占位图,等待替换为真实截图" /><br/>
<sub><b>71 套 design system 库</b> —— 每套产品系统都展示 4 色色卡。点进去看完整的 <code>DESIGN.md</code>、色板网格、live showcase。</sub>
</td>
</tr>
<tr>
<td width="50%">
<img src="docs/screenshots/07-magazine-deck.png" alt="杂志风横向翻页 deck 输出" /><br/>
<img src="docs/screenshots/07-magazine-deck.svg" alt="07 · 杂志风 deck —— 占位图,等待替换为真实截图" /><br/>
<sub><b>Deck 模式(guizang-ppt</b> —— 内置的 <a href="https://github.com/op7418/guizang-ppt-skill"><code>guizang-ppt-skill</code></a> 原样接入。杂志版式、WebGL hero 背景、单文件 HTML 输出、可导 PDF。</sub>
</td>
<td width="50%">
<img src="docs/screenshots/08-mobile-app.png" alt="带 iPhone 15 Pro 外壳的移动端原型" /><br/>
<img src="docs/screenshots/08-mobile-app.svg" alt="08 · 移动端原型 —— 占位图,等待替换为真实截图" /><br/>
<sub><b>移动端原型</b> —— 像素级精确的 iPhone 15 Pro chrome(灵动岛、状态栏 SVG、Home Indicator)。多屏原型直接复用 <code>/frames/</code> 共享资源,agent 永远不需要重新画一遍手机。</sub>
</td>
</tr>
@@ -113,13 +113,13 @@ Daemon 启动时扫 `PATH`,找 [`claude`](https://docs.anthropic.com/en/docs/c
### 4 · 初始化问题表单干掉 80% 的来回返工
OCD 的提示词栈把 `RULE 1` 写死了:每个新设计任务都从 `<question-form id="discovery">` 开始,**不是代码**。Surface · 受众 · 调性 · 品牌上下文 · 规模 · 约束。一段写得很长的需求里仍然有大量留白:视觉调性、色彩立场、规模 —— 而表单恰恰把这些用 30 秒勾选项锁死。错方向的代价是一轮对话,不是一份做完的 deck。
OD 的提示词栈把 `RULE 1` 写死了:每个新设计任务都从 `<question-form id="discovery">` 开始,**不是代码**。Surface · 受众 · 调性 · 品牌上下文 · 规模 · 约束。一段写得很长的需求里仍然有大量留白:视觉调性、色彩立场、规模 —— 而表单恰恰把这些用 30 秒勾选项锁死。错方向的代价是一轮对话,不是一份做完的 deck。
这就是从 [`huashu-design`](https://github.com/alchaincyf/huashu-design) 蒸馏出来的 **Junior-Designer 模式**:开工前一次性批量问完,尽早 show 出一些可见的东西(哪怕只是灰色方块的 wireframe),让用户用最低成本介入纠偏。再叠加品牌资产协议(定位 · 下载 · `grep` hex · 写 `brand-spec.md` · 复述),这是输出从「AI freestyle」跳到「先看资料再画图的设计师」最关键的一步。
### 5 · Daemon 让 agent 感觉自己就在你笔记本上 —— 因为它就是
Daemon `spawn` CLI 时,`cwd` 设到该项目在 `.ocd/projects/<id>/` 下的 artifact 文件夹。Agent 拿到的 `Read` / `Write` / `Bash` / `WebFetch` 都是真工具,作用在真文件系统上。它能 `Read` skill 的 `assets/template.html`,能 `grep` 你的 CSS 拿 hex,能写一份 `brand-spec.md`,能落地生成的图片,能产出 `.pptx` / `.zip` / `.pdf` —— 这些文件在 turn 结束的时候作为下载 chip 出现在文件工作区里。Session、对话、消息、tab 都持久化在本地 SQLite 里 —— 明天再打开这个项目,agent 的 todo 卡片还在你昨天停下的地方。
Daemon `spawn` CLI 时,`cwd` 设到该项目在 `.od/projects/<id>/` 下的 artifact 文件夹。Agent 拿到的 `Read` / `Write` / `Bash` / `WebFetch` 都是真工具,作用在真文件系统上。它能 `Read` skill 的 `assets/template.html`,能 `grep` 你的 CSS 拿 hex,能写一份 `brand-spec.md`,能落地生成的图片,能产出 `.pptx` / `.zip` / `.pdf` —— 这些文件在 turn 结束的时候作为下载 chip 出现在文件工作区里。Session、对话、消息、tab 都持久化在本地 SQLite 里 —— 明天再打开这个项目,agent 的 todo 卡片还在你昨天停下的地方。
### 6 · 提示词栈本身就是产品
@@ -158,7 +158,7 @@ DISCOVERY 指令 turn-1 表单、turn-2 品牌分支、TodoWrite、
│ /api/chat (SSE) │
│ │
└─────────┬────────────┘
│ spawn(cli, [...], { cwd: .ocd/projects/<id> })
│ spawn(cli, [...], { cwd: .od/projects/<id> })
┌──────────────────────────────────────────────────────────┐
│ claude · codex · cursor-agent · gemini · opencode · qwen│
@@ -171,15 +171,15 @@ DISCOVERY 指令 turn-1 表单、turn-2 品牌分支、TodoWrite、
| 前端 | Vite 5 + React 18 + TypeScript |
| Daemon | Node 18+ · Express · SSE 流 · `better-sqlite3` 存项目/对话/消息/tab |
| Agent 传输层 | `child_process.spawn`Claude Code 走 `claude-stream-json` 解析器,其余走 line-buffered plain stdout |
| 存储 | 纯文件 `.ocd/projects/<id>/` + SQLite `.ocd/db.sqlite`(已 gitignore |
| 存储 | 纯文件 `.od/projects/<id>/` + SQLite `.od/app.sqlite`(已 gitignoredaemon 启动自建 |
| 预览 | 沙盒 iframe`srcdoc`+ 每个 skill 的 `<artifact>` parser |
| 导出 | HTML(内联资源)· PDF(浏览器打印)· PPTX(skill 自定义)· ZIParchiver |
## Quickstart
```bash
git clone https://github.com/<your-org>/open-claude-design.git
cd open-claude-design
git clone https://github.com/nexu-io/open-design.git
cd open-design
pnpm install # 或 npm install
pnpm dev:all # daemon (:7456) + Vite (:5173) 一起起
open http://localhost:5173
@@ -190,22 +190,40 @@ open http://localhost:5173
1. 检测你 `PATH` 上有哪些 agent CLI,自动选一个。
2. 加载 19 个 skill + 71 套 design system。
3. 弹欢迎对话框,让你贴 Anthropic key(仅 BYOK 兜底路径需要)。
4. **自动创建 `./.od/`** —— 本地运行时目录,存放 SQLite 项目库、各项目工作区、保存下来的 artifact。**没有** `od init` 这一步,daemon 启动时会自己 `mkdir`
输入需求,回车,看 question form 跳出来,填,看 todo 卡片流动,看 artifact 渲染。点 **Save to disk** 或导出整个项目 ZIP。
### 第一次跑起来(`./.od/` 解释)
Daemon 在仓库根下维护一个隐藏目录,里面所有内容都已 gitignore,纯本机数据,**不要** commit。
```
.od/
├── app.sqlite ← 项目 · 对话 · 消息 · 打开的 tab
├── artifacts/ ← Save to disk 一次性渲染(带时间戳)
└── projects/<id>/ ← 每个项目的工作目录,也是 agent 的 cwd
```
| 想做什么 | 怎么做 |
|---|---|
| 看一眼里面有啥 | `ls -la .od && sqlite3 .od/app.sqlite '.tables'` |
| 完全清空,从零再来 | 先停 daemon,再 `rm -rf .od`,然后重新 `pnpm dev:all` |
| 换到别的位置 | 暂不支持 —— 路径是相对仓库根写死的 |
完整文件地图、脚本、排错 → [`QUICKSTART.md`](QUICKSTART.md)。
## 仓库结构
```
open-claude-design/
open-design/
├── README.md ← 英文
├── README.zh-CN.md ← 本文件
├── QUICKSTART.md ← 跑 / 构建 / 部署
├── package.json ← 单 bin: ocd
├── package.json ← 单 bin: od
├── daemon/ ← Node + Express,唯一的服务端
│ ├── cli.js ← `ocd` 二进制入口
│ ├── cli.js ← `od` 二进制入口
│ ├── server.js ← /api/* 路由(projects、chat、files、exports
│ ├── agents.js ← PATH 扫描器 + 各 CLI 的 argv 拼装
│ ├── claude-stream.js ← Claude Code stdout 流式 JSON 解析
@@ -288,7 +306,7 @@ open-claude-design/
├── docs/
│ ├── spec.md ← 产品定义、场景、差异化
│ ├── architecture.md ← 拓扑、数据流、组件
│ ├── skills-protocol.md ← 扩展 SKILL.md 的 ocd: frontmatter
│ ├── skills-protocol.md ← 扩展 SKILL.md 的 od: frontmatter
│ ├── agent-adapters.md ← 各 CLI 检测 + 派发
│ ├── modes.md ← prototype / deck / template / design-system
│ ├── references.md ← 详尽的引用与师承
@@ -296,15 +314,15 @@ open-claude-design/
│ ├── schemas/ ← JSON schema
│ └── examples/ ← 标准 artifact 样例
└── .ocd/ ← 运行时数据,已 gitignore
└── .od/ ← 运行时数据,已 gitignoredaemon 启动自建
├── app.sqlite ← 项目 / 对话 / 消息 / tab
├── projects/<id>/ ← 每个项目的工作目录(agent 的 cwd)
── artifacts/ ← 单次保存的 artifact
└── db.sqlite ← 项目 / 对话 / 消息 / tab
── artifacts/ ← 单次保存的 artifact
```
## 内置 Skills
19 个 skill,每个一个文件夹,都遵循 Claude Code 的 [`SKILL.md`][skill] 规范,并叠加 OCD 的 `ocd:` frontmatter`mode``platform``scenario``preview``design_system`)。
19 个 skill,每个一个文件夹,都遵循 Claude Code 的 [`SKILL.md`][skill] 规范,并叠加 OD 的 `od:` frontmatter`mode``platform``scenario``preview``design_system`)。
### 示例展示(Showcase examples
@@ -354,7 +372,7 @@ open-claude-design/
## Design System
<p align="center">
<img src="docs/assets/design-systems-library.png" alt="71 套 design system 库" width="100%" />
<img src="docs/assets/design-systems-library.svg" alt="71 套 design system 库 —— 占位图,等待替换为真实截图" width="100%" />
</p>
71 套开箱即用,每套一个 [`DESIGN.md`](design-systems/README.md)
@@ -386,7 +404,7 @@ open-claude-design/
## 视觉方向
当用户没有品牌资产时,agent 会跳第二个表单,5 套精选方向 —— 这是 [`huashu-design` 的「设计方向顾问 · 5 流派 × 20 种设计哲学」 fallback](https://github.com/alchaincyf/huashu-design#%E8%AE%BE%E8%AE%A1%E6%96%B9%E5%90%91%E9%A1%BE%E9%97%AE-fallback) 在 OCD 里的落地。每一套都是确定性 spec —— OKLch 色板、字体栈、版式姿态、参考列表 —— agent 直接把它**原样**绑进 seed 模板的 `:root`。一个 radio 选完,整套视觉系统全部锁定。零 freestyle,零 AI slop。
当用户没有品牌资产时,agent 会跳第二个表单,5 套精选方向 —— 这是 [`huashu-design` 的「设计方向顾问 · 5 流派 × 20 种设计哲学」 fallback](https://github.com/alchaincyf/huashu-design#%E8%AE%BE%E8%AE%A1%E6%96%B9%E5%90%91%E9%A1%BE%E9%97%AE-fallback) 在 OD 里的落地。每一套都是确定性 spec —— OKLch 色板、字体栈、版式姿态、参考列表 —— agent 直接把它**原样**绑进 seed 模板的 `:root`。一个 radio 选完,整套视觉系统全部锁定。零 freestyle,零 AI slop。
| 方向 | 调性 | 参考 |
|---|---|---|
@@ -400,7 +418,7 @@ open-claude-design/
## 反 AI Slop 机制
下面整套机制都是 [`huashu-design`](https://github.com/alchaincyf/huashu-design) 的 playbook,被移植进 OCD 的提示词栈,并通过 skill 副文件 pre-flight 让每个 skill 都能落地执行。看 [`src/prompts/discovery.ts`](src/prompts/discovery.ts) 是真实文案:
下面整套机制都是 [`huashu-design`](https://github.com/alchaincyf/huashu-design) 的 playbook,被移植进 OD 的提示词栈,并通过 skill 副文件 pre-flight 让每个 skill 都能落地执行。看 [`src/prompts/discovery.ts`](src/prompts/discovery.ts) 是真实文案:
- **先表单。** Turn 1 必须是 `<question-form>`**不准** thinking、不准 tools、不准旁白。用户用 radio 速度选默认。
- **品牌资产协议。** 用户贴截图或 URL 时,agent 走 5 步流程(定位 · 下载 · grep hex · 写 `brand-spec.md` · 复述)才能开始写 CSS。**绝不从记忆里猜品牌色**。
@@ -411,7 +429,7 @@ open-claude-design/
## 横向对比
| 维度 | [Claude Design][cd]Anthropic | [Open CoDesign][ocod] | **Open Claude Design** |
| 维度 | [Claude Design][cd]Anthropic | [Open CoDesign][ocod] | **Open Design** |
|---|---|---|---|
| License | 闭源 | MIT | **Apache-2.0** |
| 形态 | Web (claude.ai) | 桌面 (Electron) | **Web 应用 + 本地 daemon** |
@@ -481,8 +499,8 @@ Daemon 启动时从 `PATH` 自动检测,无需配置。
- [ ] 评论模式手术刀编辑(点元素 → 指令 → 局部 patch)—— 模式来自 [`open-codesign`][ocod]
- [ ] AI 自吐 tweaks 面板(模型自己抛出值得调的参数)—— 模式来自 [`open-codesign`][ocod]
- [ ] Vercel + 隧道部署食谱(Topology B
- [ ] 一行 `npx ocd init` 脚手架带 `DESIGN.md`
- [ ] Skill 市场(`ocd skills install <github-repo>`
- [ ] 一行 `npx od init` 脚手架带 `DESIGN.md`
- [ ] Skill 市场(`od skills install <github-repo>`
分阶段交付计划在 [`docs/roadmap.md`](docs/roadmap.md)。
+1 -1
View File
@@ -43,7 +43,7 @@ path inside its inner viewport:
></iframe>
\`\`\`
In an OCD-managed project, the recommended pattern is:
In an OD-managed project, the recommended pattern is:
\`\`\`
my-project/
+3 -3
View File
@@ -2,7 +2,7 @@
import { startServer } from './server.js';
const args = process.argv.slice(2);
let port = Number(process.env.OCD_PORT) || 7456;
let port = Number(process.env.OD_PORT) || 7456;
let open = true;
for (let i = 0; i < args.length; i++) {
@@ -12,7 +12,7 @@ for (let i = 0; i < args.length; i++) {
} else if (a === '--no-open') {
open = false;
} else if (a === '-h' || a === '--help') {
console.log(`Usage: ocd [--port <n>] [--no-open]
console.log(`Usage: od [--port <n>] [--no-open]
Starts a local daemon that:
* scans PATH for installed code-agent CLIs (claude, codex, gemini, opencode, cursor-agent, ...)
@@ -24,7 +24,7 @@ Starts a local daemon that:
}
startServer({ port }).then(url => {
console.log(`[ocd] listening on ${url}`);
console.log(`[od] listening on ${url}`);
if (open) {
const opener = process.platform === 'darwin' ? 'open'
: process.platform === 'win32' ? 'start'
+2 -2
View File
@@ -1,6 +1,6 @@
// SQLite-backed persistence for projects, conversations, messages, and the
// per-project set of open file tabs. The on-disk project folder under
// .ocd/projects/<id>/ is still the single owner of the user's actual files
// .od/projects/<id>/ is still the single owner of the user's actual files
// (HTML artifacts, sketches, uploads); this database tracks the metadata
// that used to live in localStorage.
@@ -12,7 +12,7 @@ let dbInstance = null;
export function openDatabase(projectRoot) {
if (dbInstance) return dbInstance;
const dir = path.join(projectRoot, '.ocd');
const dir = path.join(projectRoot, '.od');
fs.mkdirSync(dir, { recursive: true });
const file = path.join(dir, 'app.sqlite');
const db = new Database(file);
+5 -5
View File
@@ -143,7 +143,7 @@ export function lintArtifact(rawHtml) {
severity: 'P0',
id: 'left-accent-card',
message: 'Rounded card with a coloured left border — the canonical AI-slop card pattern.',
fix: 'Drop either the border-radius (set 0px) or the border-left. Cards in the OCD seed use hairline borders all-round, no left accent.',
fix: 'Drop either the border-radius (set 0px) or the border-left. Cards in the OD seed use hairline borders all-round, no left accent.',
snippet: clip(lam[0]),
});
}
@@ -262,19 +262,19 @@ export function lintArtifact(rawHtml) {
}
// ── P2-1: missing comment-mode anchor on <section> ────────────────
// Either `data-ocd-id` (web/mobile prototypes) or `data-screen-label`
// Either `data-od-id` (web/mobile prototypes) or `data-screen-label`
// (decks) counts. Whichever the artifact uses, every <section> should
// carry one so the chat layer can target it.
const sections = html.match(/<section\b[^>]*>/gi) ?? [];
const tagged = sections.filter(
(s) => /data-ocd-id\s*=/.test(s) || /data-screen-label\s*=/.test(s),
(s) => /data-od-id\s*=/.test(s) || /data-screen-label\s*=/.test(s),
).length;
if (sections.length > 0 && tagged < sections.length) {
out.push({
severity: 'P2',
id: 'missing-section-anchor',
message: `${sections.length - tagged} of ${sections.length} <section>s lack data-ocd-id (or data-screen-label).`,
fix: 'Add data-ocd-id="kebab-slug" (or data-screen-label="01 Cover" for slides) to every top-level <section> so comment mode can target it.',
message: `${sections.length - tagged} of ${sections.length} <section>s lack data-od-id (or data-screen-label).`,
fix: 'Add data-od-id="kebab-slug" (or data-screen-label="01 Cover" for slides) to every top-level <section> so comment mode can target it.',
});
}
+1 -1
View File
@@ -1,5 +1,5 @@
// Project files registry. Each project is a folder under
// <projectRoot>/.ocd/projects/<projectId>/. The frontend's project list
// <projectRoot>/.od/projects/<projectId>/. The frontend's project list
// (localStorage) carries metadata; this module is the single owner of the
// on-disk content (HTML artifacts, sketches, uploaded images, pasted text).
//
+4 -4
View File
@@ -50,11 +50,11 @@ const PROJECT_ROOT = path.resolve(__dirname, '..');
const STATIC_DIR = path.join(PROJECT_ROOT, 'dist');
const SKILLS_DIR = path.join(PROJECT_ROOT, 'skills');
const DESIGN_SYSTEMS_DIR = path.join(PROJECT_ROOT, 'design-systems');
const ARTIFACTS_DIR = path.join(PROJECT_ROOT, '.ocd', 'artifacts');
const PROJECTS_DIR = path.join(PROJECT_ROOT, '.ocd', 'projects');
const ARTIFACTS_DIR = path.join(PROJECT_ROOT, '.od', 'artifacts');
const PROJECTS_DIR = path.join(PROJECT_ROOT, '.od', 'projects');
fs.mkdirSync(PROJECTS_DIR, { recursive: true });
const UPLOAD_DIR = path.join(os.tmpdir(), 'ocd-uploads');
const UPLOAD_DIR = path.join(os.tmpdir(), 'od-uploads');
fs.mkdirSync(UPLOAD_DIR, { recursive: true });
fs.mkdirSync(ARTIFACTS_DIR, { recursive: true });
@@ -580,7 +580,7 @@ export async function startServer({ port = 7456 } = {}) {
// No mtime-based caching — frames are static and small.
app.use('/frames', express.static(path.join(PROJECT_ROOT, 'assets', 'frames')));
// Project files. Each project owns a flat folder under .ocd/projects/<id>/
// Project files. Each project owns a flat folder under .od/projects/<id>/
// containing every file the user has uploaded, pasted, sketched, or that
// the agent has generated. Names are sanitized; paths are confined to the
// project's own folder (see daemon/projects.js).
+11 -11
View File
@@ -24,20 +24,20 @@ export async function listSkills(skillsRoot) {
const raw = await readFile(skillPath, 'utf8');
const { data, body } = parseFrontmatter(raw);
const hasAttachments = await dirHasAttachments(dir);
const mode = data.ocd?.mode || inferMode(body, data.description);
const mode = data.od?.mode || inferMode(body, data.description);
out.push({
id: data.name || entry.name,
name: data.name || entry.name,
description: data.description || '',
triggers: Array.isArray(data.triggers) ? data.triggers : [],
mode,
platform: normalizePlatform(data.ocd?.platform, mode, body, data.description),
scenario: normalizeScenario(data.ocd?.scenario, body, data.description),
previewType: data.ocd?.preview?.type || 'html',
designSystemRequired: data.ocd?.design_system?.requires ?? true,
defaultFor: normalizeDefaultFor(data.ocd?.default_for),
upstream: typeof data.ocd?.upstream === 'string' ? data.ocd.upstream : null,
featured: normalizeFeatured(data.ocd?.featured),
platform: normalizePlatform(data.od?.platform, mode, body, data.description),
scenario: normalizeScenario(data.od?.scenario, body, data.description),
previewType: data.od?.preview?.type || 'html',
designSystemRequired: data.od?.design_system?.requires ?? true,
defaultFor: normalizeDefaultFor(data.od?.default_for),
upstream: typeof data.od?.upstream === 'string' ? data.od.upstream : null,
featured: normalizeFeatured(data.od?.featured),
examplePrompt: derivePrompt(data),
body: hasAttachments ? withSkillRootPreamble(body, dir) : body,
dir,
@@ -85,7 +85,7 @@ function normalizeDefaultFor(value) {
return [String(value)];
}
// Coerce `ocd.featured` into a numeric priority. Lower numbers float to the
// Coerce `od.featured` into a numeric priority. Lower numbers float to the
// top of the Examples gallery; `true` is treated as priority 1; anything
// missing/unrecognised becomes null so non-featured skills keep their
// natural alphabetical order.
@@ -99,12 +99,12 @@ function normalizeFeatured(value) {
return null;
}
// Prefer an explicitly authored `ocd.example_prompt`. Fall back to the
// Prefer an explicitly authored `od.example_prompt`. Fall back to the
// skill description's first sentence — it's already written in actionable
// language ("Admin / analytics dashboard in a single HTML file…") so it
// serves as a passable starter prompt.
function derivePrompt(data) {
const explicit = data.ocd?.example_prompt;
const explicit = data.od?.example_prompt;
if (typeof explicit === 'string' && explicit.trim()) return explicit.trim();
const desc = typeof data.description === 'string' ? data.description.trim() : '';
if (!desc) return '';
+1 -1
View File
@@ -6,7 +6,7 @@ will read it as part of its system prompt.
## What's bundled
- **`default/`** — Neutral Modern. Hand-authored starter for the OCD spec.
- **`default/`** — Neutral Modern. Hand-authored starter for the OD spec.
- **`warm-editorial/`** — Warm Editorial. Hand-authored serif starter.
- **69 product systems**, imported from
[`VoltAgent/awesome-design-md`](https://github.com/VoltAgent/awesome-design-md)
+18 -18
View File
@@ -2,7 +2,7 @@
**Parent:** [`spec.md`](spec.md) · **Siblings:** [`architecture.md`](architecture.md) · [`skills-protocol.md`](skills-protocol.md) · [`modes.md`](modes.md)
The adapter layer is OCD's most load-bearing design decision. We delegate the **entire agent loop** — model calls, tool use, context management, permission handling, resume, cancel — to the user's existing code agent CLI. OCD's job is to detect it, feed it a skill + prompt + working directory, and stream its output back to the web UI.
The adapter layer is OD's most load-bearing design decision. We delegate the **entire agent loop** — model calls, tool use, context management, permission handling, resume, cancel — to the user's existing code agent CLI. OD's job is to detect it, feed it a skill + prompt + working directory, and stream its output back to the web UI.
> **Thesis:** The code agent space has already converged on a few strong implementations (Claude Code, Codex, Cursor Agent, Gemini CLI, OpenCode, OpenClaw). Reimplementing a 7th is worse than just talking to all of them.
>
@@ -70,7 +70,7 @@ type AgentEvent =
## 2. Detection strategy
Run all adapters' `detect()` in parallel on daemon start, then cache results in `~/.open-claude-design/agents.json` with a 24h TTL. Re-detect on daemon `SIGHUP`.
Run all adapters' `detect()` in parallel on daemon start, then cache results in `~/.open-design/agents.json` with a 24h TTL. Re-detect on daemon `SIGHUP`.
Each adapter uses **two signals**:
@@ -98,7 +98,7 @@ If both signals agree, detection is confident. If only one signal fires, we mark
Skills travel into each agent via one of three strategies, in order of preference:
### 4.1 Native skill loading (preferred)
Agent scans its own `~/.<agent>/skills/` on launch. We symlink OCD's skill into that dir (see [`skills-protocol.md`](skills-protocol.md) §3) and let the agent pick it up natively. Zero prompt overhead.
Agent scans its own `~/.<agent>/skills/` on launch. We symlink OD's skill into that dir (see [`skills-protocol.md`](skills-protocol.md) §3) and let the agent pick it up natively. Zero prompt overhead.
- **Works for:** Claude Code. Codex (version-dependent). OpenCode.
@@ -131,10 +131,10 @@ The adapter declares which strategy to use via `capabilities().nativeSkillLoadin
- Invocation: direct Anthropic Messages API with `stream: true`.
- Skill loading: prompt injection only — read the skill dir, inline everything.
- Tool use: we register `Read/Write/Edit` as tools, implement them in the daemon against the artifact cwd, and run the loop ourselves. This is the one place OCD does own the loop — because the user has no agent at all. Keep it as dumb as possible.
- Tool use: we register `Read/Write/Edit` as tools, implement them in the daemon against the artifact cwd, and run the loop ourselves. This is the one place OD does own the loop — because the user has no agent at all. Keep it as dumb as possible.
- Surgical edits: approximated by regenerating the whole target file with "only change X" in the prompt.
- Model: Claude Sonnet 4.6 default; Opus 4.7 behind a flag.
- **Why ship this at all?** Topology C requires it (no daemon available in a pure-Vercel deploy). Also, users trying OCD for the first time without a CLI installed still get a working experience.
- **Why ship this at all?** Topology C requires it (no daemon available in a pure-Vercel deploy). Also, users trying OD for the first time without a CLI installed still get a working experience.
### 5.3 Codex
@@ -173,7 +173,7 @@ The web UI reads `agents.capabilities()` and disables features that the active a
| Comment mode (click to refine) | `surgicalEdit: true` | Hidden; show tooltip explaining why |
| Streaming tool-call feed | `streaming: true` | Show a spinner only |
| Resume interrupted run | `resume: true` | "Cancel + restart" only |
| Skill picker shows skill with `ocd.capabilities_required` | all listed caps | Skill greyed out with reason |
| Skill picker shows skill with `od.capabilities_required` | all listed caps | Skill greyed out with reason |
This is how we avoid "works on my Claude Code, breaks on your Gemini" — we detect, degrade, and document.
@@ -192,7 +192,7 @@ Switching mid-run is not allowed (cancel first). The artifact is agent-agnostic;
## 8. Fallback chain
If the user's preferred agent fails (crash, auth, timeout), OCD offers a one-click fallback in this order:
If the user's preferred agent fails (crash, auth, timeout), OD offers a one-click fallback in this order:
1. User's preferred agent (e.g. Cursor Agent)
2. Any other detected agent (Claude Code, if installed)
@@ -206,14 +206,14 @@ First run:
```
$ pnpm dev
[ocd] daemon starting on :7431
[ocd] detecting agents…
[ocd] ✓ claude-code v0.6.3 (auth: ok, skills dir linked)
[ocd] ✓ codex v0.8.1 (auth: ok)
[ocd] ✗ cursor-agent (not installed)
[ocd] ✗ gemini-cli (installed but not authenticated; run `gemini auth login`)
[ocd] ✓ api-fallback (ANTHROPIC_API_KEY found)
[ocd] daemon ready; 3 agents available
[od] daemon starting on :7431
[od] detecting agents…
[od] ✓ claude-code v0.6.3 (auth: ok, skills dir linked)
[od] ✓ codex v0.8.1 (auth: ok)
[od] ✗ cursor-agent (not installed)
[od] ✗ gemini-cli (installed but not authenticated; run `gemini auth login`)
[od] ✓ api-fallback (ANTHROPIC_API_KEY found)
[od] daemon ready; 3 agents available
```
Web UI mirrors this in an agent-selector dropdown, with unauthenticated agents shown greyed out with a fix-it tooltip.
@@ -222,8 +222,8 @@ Web UI mirrors this in an agent-selector dropdown, with unauthenticated agents s
We inherit the underlying agent's permission model rather than building our own. This means:
- **Claude Code** respects its own `--allowed-tools` and `--permission-mode` flags. OCD passes through user preferences.
- **Codex / Cursor** sandbox by workspace; OCD always sets cwd to the artifact dir so nothing outside is visible by default.
- **Claude Code** respects its own `--allowed-tools` and `--permission-mode` flags. OD passes through user preferences.
- **Codex / Cursor** sandbox by workspace; OD always sets cwd to the artifact dir so nothing outside is visible by default.
- **API fallback** is the one case we own. We implement a whitelist: only `Read`, `Write`, `Edit` tools, all rooted at the artifact cwd. Network access is off.
The daemon never grants more authority to an agent than it had on its own. We don't run the agent in a privileged mode "for convenience."
@@ -253,6 +253,6 @@ Each adapter is a separate module so community contributions can add new ones wi
## 12. Open questions
- **Nested agents.** What if Claude Code's agent itself spawns a subagent? We receive events from the outer process only. v1 policy: surface only top-level events; summarize subagent activity as "sub-task" placeholder.
- **Billing awareness.** Some agents bill per message, some per token. OCD doesn't track cost in MVP; v1 adds an optional "usage" event from adapters that expose it.
- **Billing awareness.** Some agents bill per message, some per token. OD doesn't track cost in MVP; v1 adds an optional "usage" event from adapters that expose it.
- **Windows support.** PATH scanning and `spawn` semantics differ on Windows. v1 targets macOS and Linux; Windows is best-effort.
- **Docker-contained agents.** Some users run Claude Code in a container. Adapter needs a "remote" mode — probably same interface but talks over SSH. Phase 2+.
+24 -24
View File
@@ -13,7 +13,7 @@ This doc describes the system topology, runtime modes, data flow, and file layou
## 1. Three deployment topologies
OCD is a web app plus a local daemon. The split means the same UI can run in three shapes:
OD is a web app plus a local daemon. The split means the same UI can run in three shapes:
### Topology A — Fully local (the default)
@@ -24,7 +24,7 @@ OCD is a web app plus a local daemon. The split means the same UI can run in thr
│ │ │
│ │ ws://localhost:7431 │
│ ▼ │
│ ocd daemon (Node, long-running) │
│ od daemon (Node, long-running) │
│ │ │
│ ▼ │
│ spawns: claude / codex / cursor / … │
@@ -36,22 +36,22 @@ One `pnpm dev` starts both the Next.js app and the daemon (via a predev script).
### Topology B — Web on Vercel + daemon on user's machine
```
browser ──► ocd.yourdomain.com (Vercel)
browser ──► od.yourdomain.com (Vercel)
│ ws(s):// user-provided URL (e.g. cloudflared tunnel)
ocd daemon on user's laptop
od daemon on user's laptop
spawns: claude / codex / …
```
The user runs `ocd daemon --expose` which prints a tunnel URL; they paste the URL into the deployed web app's "Connect daemon" screen. Daemon holds secrets; Vercel holds nothing sensitive.
The user runs `od daemon --expose` which prints a tunnel URL; they paste the URL into the deployed web app's "Connect daemon" screen. Daemon holds secrets; Vercel holds nothing sensitive.
### Topology C — Web on Vercel + direct API (no daemon)
```
browser ──► ocd.yourdomain.com (Vercel serverless)
browser ──► od.yourdomain.com (Vercel serverless)
Anthropic Messages API (BYOK stored in browser)
@@ -91,8 +91,8 @@ The three topologies share the same web bundle; the difference is which transpor
│ │
▼ ▼
┌─ agent CLIs ─┐ ┌─ filesystem ─┐
│ claude │ │ ./.ocd/ │
│ codex │ │ ~/.ocd/ │
│ claude │ │ ./.od/ │
│ codex │ │ ~/.od/ │
│ cursor-agent │ │ skills/ │
│ gemini │ │ DESIGN.md │
│ opencode │ └──────────────┘
@@ -107,10 +107,10 @@ The three topologies share the same web bundle; the difference is which transpor
- **Why Next.js, not Vite SPA?** We want SSR for the marketing landing page + serverless routes for Topology C's direct-API path + Vercel deployment as a first-class citizen. An SPA would need a separate server for any of that.
- **State:** Zustand for session/artifact stores. Browser-side only; hydrated from daemon on connect.
- **Iframe preview:** Vendored React 18 + Babel standalone for JSX artifacts, following [Open CoDesign][ocod]'s approach. HTML artifacts load raw. See [§5](#5-preview-renderer).
- **Comment mode:** Click captures `[data-ocd-id]` on preview DOM, opens a popover, sends `{artifact_id, element_id, note}` to daemon → agent gets a surgical edit instruction.
- **Comment mode:** Click captures `[data-od-id]` on preview DOM, opens a popover, sends `{artifact_id, element_id, note}` to daemon → agent gets a surgical edit instruction.
- **Slider UI:** When an agent emits a "tweak parameter" tool call (see [`skills-protocol.md`](skills-protocol.md) §4.2), the web app renders a live-update control that re-sends parameterized prompts without round-tripping the chat.
### 3.2 Local daemon (`ocd daemon`)
### 3.2 Local daemon (`od daemon`)
Single binary via `pkg` or a thin Node script distributed over npm. Responsibilities:
@@ -155,7 +155,7 @@ Conflicts resolve by priority (higher wins). Each skill parsed once; watched for
Plain files on disk. Conventional layout per project:
```
./.ocd/
./.od/
├── config.json # project-level daemon config
├── artifacts/
│ ├── 2026-04-24T10-03-12-landing/
@@ -169,8 +169,8 @@ Plain files on disk. Conventional layout per project:
```
Rationale:
- **Plain files** → users can `git add ./.ocd/artifacts/` and review designs in PRs.
- **`artifact.json` metadata** → OCD can reconstruct the artifact tree without a DB.
- **Plain files** → users can `git add ./.od/artifacts/` and review designs in PRs.
- **`artifact.json` metadata** → OD can reconstruct the artifact tree without a DB.
- **`history.jsonl` not SQLite** → append-only, git-friendly, greppable. [Open CoDesign][ocod] uses SQLite; we deliberately don't.
- **Sessions separate from artifacts** → sessions are ephemeral UI state; artifacts are durable.
@@ -195,7 +195,7 @@ Rationale:
3. Daemon:
a. picks active skill (prototype-skill)
b. loads design-system (DESIGN.md)
c. materializes a new artifact dir under ./.ocd/artifacts/<slug>/
c. materializes a new artifact dir under ./.od/artifacts/<slug>/
d. invokes agent adapter with:
- system: skill's SKILL.md contents + DESIGN.md
- user: original prompt
@@ -242,9 +242,9 @@ Rationale:
| File | Purpose |
|---|---|
| `~/.open-claude-design/config.toml` | daemon-global: default agent preference, keys (optional, BYOK), telemetry opt-in (default off) |
| `~/.open-claude-design/agents.json` | cached agent detection results |
| `./.ocd/config.json` | project-local: active design system, preferred skills, preferred mode |
| `~/.open-design/config.toml` | daemon-global: default agent preference, keys (optional, BYOK), telemetry opt-in (default off) |
| `~/.open-design/agents.json` | cached agent detection results |
| `./.od/config.json` | project-local: active design system, preferred skills, preferred mode |
| `./skills/<skill>/SKILL.md` | skill manifest (standard Claude Code format) |
| `./DESIGN.md` | active design system ([awesome-claude-design][acd] format) |
@@ -288,35 +288,35 @@ pnpm dev # starts daemon on :7431, next on :3000
services:
daemon:
image: openclaudedesign/daemon
volumes: [ "~/.open-claude-design:/root/.open-claude-design", "./:/workspace" ]
volumes: [ "~/.open-design:/root/.open-design", "./:/workspace" ]
ports: ["7431:7431"]
web:
image: openclaudedesign/web
ports: ["3000:3000"]
environment: [ "OCD_DAEMON_URL=ws://daemon:7431" ]
environment: [ "OD_DAEMON_URL=ws://daemon:7431" ]
```
### Vercel + local daemon (Topology B)
```sh
vercel deploy # web only
ocd daemon --expose # user runs locally; prints tunnel URL
od daemon --expose # user runs locally; prints tunnel URL
# user pastes URL into /connect UI
```
### Vercel direct (Topology C)
```sh
vercel deploy # same bundle
# flip VERCEL env flag OCD_MODE=direct to hide daemon-connect UI
# flip VERCEL env flag OD_MODE=direct to hide daemon-connect UI
```
## 9. Security model
| Surface | Threat | Mitigation |
|---|---|---|
| Daemon WebSocket | Arbitrary local process talks to daemon | Token handshake; token printed on `ocd daemon` start, required in WS URL |
| Daemon WebSocket | Arbitrary local process talks to daemon | Token handshake; token printed on `od daemon` start, required in WS URL |
| Artifact code in preview | XSS/cookie theft from host | `<iframe sandbox="allow-scripts">`, no `allow-same-origin` |
| Agent running on user's machine | Agent reads/writes outside project | Adapter sets `cwd` to artifact dir; relies on agent's own permission system (Claude Code's `--allowed-tools` etc.) |
| User secrets | Leak to cloud | BYOK stored only in daemon's `config.toml` (mode 0600) or browser `localStorage` in Topology C, never sent to OCD's own servers (we don't have any) |
| User secrets | Leak to cloud | BYOK stored only in daemon's `config.toml` (mode 0600) or browser `localStorage` in Topology C, never sent to OD's own servers (we don't have any) |
| Skill from untrusted source | Malicious skill in `~/.claude/skills/` | Install-time warning; skills run under the agent's permission model, not ours |
| Vercel web bundle | Compromised build | Standard Vercel integrity; bundle has zero secrets |
@@ -326,7 +326,7 @@ We inherit the agent's permission model on purpose — we don't invent our own s
- Daemon startup: < 500 ms (lazy adapter init).
- Agent detection: < 200 ms (parallel PATH probes).
- First generation latency: dominated by agent model time; OCD overhead should be < 50 ms.
- First generation latency: dominated by agent model time; OD overhead should be < 50 ms.
- Preview reload: debounced 100 ms on artifact file writes.
- Skill index: cold scan < 100 ms for ~50 skills; watched with `chokidar`.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 MiB

+43
View File
@@ -0,0 +1,43 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2400 800" preserveAspectRatio="xMidYMid meet" role="img" aria-label="Hero banner placeholder">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBF7EF"/>
<stop offset="100%" stop-color="#EFE7D7"/>
</linearGradient>
</defs>
<rect width="2400" height="800" fill="url(#bg)"/>
<rect x="32" y="32" width="2336" height="736" rx="28" ry="28"
fill="none" stroke="#C2532D" stroke-width="3" stroke-dasharray="16 12" opacity="0.85"/>
<g transform="translate(1200 340)" stroke="#1F1B16" stroke-width="6"
stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.9">
<rect x="-110" y="-72" width="220" height="144" rx="18"/>
<rect x="-36" y="-94" width="72" height="26" rx="8"/>
<circle r="42"/>
<circle r="18"/>
</g>
<text x="1200" y="430" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="34" font-weight="600" letter-spacing="6" fill="#C2532D">
OPEN DESIGN
</text>
<text x="1200" y="510" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="56" font-weight="700" fill="#1F1B16">
Hero banner
</text>
<text x="1200" y="575" text-anchor="middle"
font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
font-size="26" fill="#6B6258">
docs/assets/banner.svg
</text>
<text x="1200" y="640" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="24" fill="#6B6258">
Replace with a wide product screenshot or marketing illustration.
</text>
<text x="1200" y="744" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="20" letter-spacing="4" fill="#6B6258" opacity="0.85">
SCREENSHOT PENDING · 截图占位
</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 MiB

+43
View File
@@ -0,0 +1,43 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid meet" role="img" aria-label="Design Systems library placeholder">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBF7EF"/>
<stop offset="100%" stop-color="#EFE7D7"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect x="32" y="32" width="1536" height="836" rx="28" ry="28"
fill="none" stroke="#C2532D" stroke-width="3" stroke-dasharray="16 12" opacity="0.85"/>
<g transform="translate(800 390)" stroke="#1F1B16" stroke-width="6"
stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.9">
<rect x="-110" y="-72" width="220" height="144" rx="18"/>
<rect x="-36" y="-94" width="72" height="26" rx="8"/>
<circle r="42"/>
<circle r="18"/>
</g>
<text x="800" y="480" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="34" font-weight="600" letter-spacing="6" fill="#C2532D">
71 DESIGN SYSTEMS
</text>
<text x="800" y="560" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="56" font-weight="700" fill="#1F1B16">
Design Systems library
</text>
<text x="800" y="625" text-anchor="middle"
font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
font-size="26" fill="#6B6258">
docs/assets/design-systems-library.svg
</text>
<text x="800" y="690" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="24" fill="#6B6258">
Replace with a screenshot of the design-system browser.
</text>
<text x="800" y="844" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="20" letter-spacing="4" fill="#6B6258" opacity="0.85">
SCREENSHOT PENDING · 截图占位
</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File
+4 -4
View File
@@ -8,7 +8,7 @@ triggers:
- "saas landing"
- "marketing page"
- "product landing"
ocd:
od:
mode: prototype
preview:
type: html
@@ -83,7 +83,7 @@ Output a single self-contained `index.html` with:
- System font fallbacks if DESIGN.md fonts aren't loadable from Google Fonts etc.
- No external JS.
- Semantic HTML (`<header>`, `<main>`, `<section>`, `<footer>`).
- Each editable element tagged with `data-ocd-id="<unique-slug>"` so the host app's comment mode can target it.
- Each editable element tagged with `data-od-id="<unique-slug>"` so the host app's comment mode can target it.
## 5. Self-check
@@ -112,9 +112,9 @@ saas-landing-skill/
```
Things to notice:
- The `ocd:` front-matter block is optional for Claude-Code-only compatibility, but adding it lights up OCD's typed inputs, sliders, preview metadata, and capability gating.
- The `od:` front-matter block is optional for Claude-Code-only compatibility, but adding it lights up OD's typed inputs, sliders, preview metadata, and capability gating.
- The workflow below the front-matter is plain Markdown that the agent reads as its system prompt.
- DESIGN.md is treated as a collaborator, not an override. The skill gives the agent authority to override when the brief conflicts, but never to invent new tokens.
- `data-ocd-id` tagging is how we wire elements to comment mode. Skills that want comment-mode compatibility must annotate their output.
- `data-od-id` tagging is how we wire elements to comment mode. Skills that want comment-mode compatibility must annotate their output.
See [`../../skills-protocol.md`](../../skills-protocol.md) for the full protocol.
+5 -5
View File
@@ -2,7 +2,7 @@
**Parent:** [`spec.md`](spec.md) · **Siblings:** [`architecture.md`](architecture.md) · [`skills-protocol.md`](skills-protocol.md) · [`agent-adapters.md`](agent-adapters.md)
OCD exposes four user-facing modes. Modes are not arbitrary; each maps to a distinct **skill type** (see [`skills-protocol.md`](skills-protocol.md) §4) and a distinct **workflow shape**. Keeping them separate lets us tune UI affordances, export pipelines, and default skills per mode.
OD exposes four user-facing modes. Modes are not arbitrary; each maps to a distinct **skill type** (see [`skills-protocol.md`](skills-protocol.md) §4) and a distinct **workflow shape**. Keeping them separate lets us tune UI affordances, export pipelines, and default skills per mode.
| Mode | What you get | Time to first result | Skill type |
|---|---|---|---|
@@ -24,14 +24,14 @@ One high-fidelity screen or flow. User brief → working HTML/JSX in a sandboxed
```
[ mode picker: Prototype ]
[ skill picker: saas-landing | dashboard | login-flow | … ]
[ inputs form (if skill declares ocd.inputs) ]
[ inputs form (if skill declares od.inputs) ]
[ free-text prompt box ]
[ generate ]
[ streaming tool-call feed · artifact tree · preview iframe ]
[ comment mode (if adapter supports surgicalEdit) ]
[ parameter sliders (if skill declares ocd.parameters) ]
[ parameter sliders (if skill declares od.parameters) ]
[ export: html · pdf · zip ]
```
@@ -54,7 +54,7 @@ One high-fidelity screen or flow. User brief → working HTML/JSX in a sandboxed
### Refinement surfaces
- **Chat:** free-text "move the CTA above the fold."
- **Comment mode:** click an element → popover → "make this card glassmorphic." Only available if `capabilities.surgicalEdit === true`.
- **Sliders:** any `ocd.parameters` the skill declared. Slider movements re-prompt with the parameter value only; no full regeneration.
- **Sliders:** any `od.parameters` the skill declared. Slider movements re-prompt with the parameter value only; no full regeneration.
### Default v1 skills
- `saas-landing`
@@ -82,7 +82,7 @@ Same as Prototype, but:
- Export adds `pptx` and `pdf` as first-class options
### Inputs
- Slide count (skill usually declares `ocd.inputs.slide_count`)
- Slide count (skill usually declares `od.inputs.slide_count`)
- Topic / outline (free text or structured)
- Theme preset (skill-defined enum; e.g. `editorial | minimal | brutalist`)
- DESIGN.md (optional — many deck skills don't need one because they have their own theme system)
+6 -6
View File
@@ -74,8 +74,8 @@ Every external project this spec leans on. Three questions per entry: what is it
- **Related URLs:** claude.ai/design, getdesign.md, Discord community
- **Why it matters:** Defines the de-facto portable design-system format for AI agents.
- **What we borrow:**
- **The entire `DESIGN.md` format, unchanged.** We adopt their 9-section schema as OCD's canonical design-system format.
- Ecosystem compatibility: any of their 68 DESIGN.md files works as an OCD active design system out of the box.
- **The entire `DESIGN.md` format, unchanged.** We adopt their 9-section schema as OD's canonical design-system format.
- Ecosystem compatibility: any of their 68 DESIGN.md files works as an OD active design system out of the box.
- **What we don't:**
- Their curated list itself — we don't fork their 68 files; we reference upstream.
- Their Discord / community layer — not our product.
@@ -87,10 +87,10 @@ Every external project this spec leans on. Three questions per entry: what is it
- **What it is:** A Claude Code skill producing magazine-style, horizontal-swipe web decks. Structure: `SKILL.md` + `assets/template.html` + `references/{components,layouts,themes,checklist}.md`. 6-step workflow. Single-file HTML output with embedded CSS/WebGL. Keyboard/scroll/touch navigation.
- **Why it matters:** Reference implementation of a high-quality Claude skill, and our default deck skill.
- **What we borrow:**
- **The whole skill, unmodified.** It's our default v1 `deck-skill`. A user runs `ocd skill add https://github.com/op7418/guizang-ppt-skill` and it works.
- **The whole skill, unmodified.** It's our default v1 `deck-skill`. A user runs `od skill add https://github.com/op7418/guizang-ppt-skill` and it works.
- Skill directory convention (`assets/` + `references/` + `SKILL.md`) as the pattern we document for skill authors.
- The "6-step workflow + quality-checklist rubric" pattern for authoring new skills.
- **What we don't:** Nothing — this is pure reuse. We add an `ocd:` block to its front-matter only if we want to expose theme sliders; the skill works without it.
- **What we don't:** Nothing — this is pure reuse. We add an `od:` block to its front-matter only if we want to expose theme sliders; the skill works without it.
---
@@ -111,7 +111,7 @@ Every external project this spec leans on. Three questions per entry: what is it
## Compatibility & differentiation matrix
| Dimension | [Claude Design][cd] | [Open CoDesign][ocod] | [multica][multica] | [cc-switch][ccsw] | **OCD** |
| Dimension | [Claude Design][cd] | [Open CoDesign][ocod] | [multica][multica] | [cc-switch][ccsw] | **OD** |
|---|---|---|---|---|---|
| Open source | ❌ | ✅ | ✅ | ✅ | ✅ |
| Primary form factor | Web (hosted) | Electron | Web + Go daemon | Tauri | **Next.js web + Node daemon** |
@@ -125,7 +125,7 @@ Every external project this spec leans on. Three questions per entry: what is it
| Template gallery | ✅ | ✅ (15) | ❌ | ❌ | **✅** |
| Design-system authoring mode | ❌ | ❌ | ❌ | ❌ | **✅** |
The two empty-column crossings where OCD lights up and others don't: **Vercel-deployable + design-system authoring**, and **uses existing code agent + first-class DESIGN.md**. That's the niche.
The two empty-column crossings where OD lights up and others don't: **Vercel-deployable + design-system authoring**, and **uses existing code agent + first-class DESIGN.md**. That's the niche.
---
+11 -11
View File
@@ -12,7 +12,7 @@ Phased plan from "spec-only today" to "usable MVP" to "published v1." All estima
**Deliverables:**
- [x] `README.md` + `docs/spec.md` + architecture / protocol / adapter / modes / references docs (this repo, as of now)
- [ ] `docs/schemas/skill-manifest.json` — JSON Schema for the `ocd:` front-matter block
- [ ] `docs/schemas/skill-manifest.json` — JSON Schema for the `od:` front-matter block
- [ ] `docs/schemas/design-system.md` — formal spec of the 9-section `DESIGN.md`
- [ ] `docs/schemas/protocol.md` — JSON-RPC method signatures
- [ ] `docs/schemas/adapter.md` — adapter interface in TypeScript, printed out
@@ -65,7 +65,7 @@ Phased plan from "spec-only today" to "usable MVP" to "published v1." All estima
- PDF / PPTX export
- Topology B (Vercel + tunneled local daemon)
- Docker compose file
- Skill tests (`ocd skill test`)
- Skill tests (`od skill test`)
- Auth / multi-user
### Week-by-week breakdown
@@ -78,7 +78,7 @@ Phased plan from "spec-only today" to "usable MVP" to "published v1." All estima
| 4 | API-fallback adapter | Anthropic Messages streaming; minimal tool loop (Read/Write/Edit rooted to artifact cwd); integration with skill prompt injection |
| 5 | Web UI — chat + artifact tree | Zustand session store; WS client; chat pane; artifact tree reflects filesystem; skill picker |
| 6 | Web UI — preview + export | sandboxed iframe with hot reload; JSX → vendored React/Babel runtime; export ZIP; export self-contained HTML (inline CSS) |
| 7 | Default skills | port `guizang-ppt-skill` (no modifications; add `ocd:` extension block); write `saas-landing` skill; write 12 DESIGN.md examples; docs for skill authors |
| 7 | Default skills | port `guizang-ppt-skill` (no modifications; add `od:` extension block); write `saas-landing` skill; write 12 DESIGN.md examples; docs for skill authors |
| 8 | Polish + dogfood | end-to-end dogfooding; performance pass (daemon <500ms cold start, first generation overhead <50ms); bug-fixing; first publishable alpha |
### MVP exit criteria
@@ -87,8 +87,8 @@ Phased plan from "spec-only today" to "usable MVP" to "published v1." All estima
2. With Claude Code installed: prototype + deck generation works end-to-end.
3. Without Claude Code installed: API-fallback produces prototypes (not decks — guizang-ppt-skill needs native skill loading).
4. A user can drop a DESIGN.md into the project root and subsequent generations respect it.
5. A third party can publish a skill repo; `ocd skill add <url>` installs it and it works.
6. Artifacts are plain files; `git add ./.ocd/artifacts/` and `git log` tell a sensible story.
5. A third party can publish a skill repo; `od skill add <url>` installs it and it works.
6. Artifacts are plain files; `git add ./.od/artifacts/` and `git log` tell a sensible story.
7. No Electron, no Tauri, no desktop packaging anywhere in the repo.
---
@@ -107,7 +107,7 @@ Phased plan from "spec-only today" to "usable MVP" to "published v1." All estima
**UI:**
- **Comment mode** (click element → surgical edit; only when `capabilities.surgicalEdit`)
- **Slider parameters** (live-tweak `ocd.parameters`)
- **Slider parameters** (live-tweak `od.parameters`)
- **Multi-frame preview** (desktop / tablet / phone)
- **Template gallery** UI with thumbnails
- **Design System editor** (split view: markdown ↔ sample-components preview)
@@ -129,18 +129,18 @@ Phased plan from "spec-only today" to "usable MVP" to "published v1." All estima
**Deployment:**
- Docker compose file
- Topology B: Vercel web + tunneled local daemon
- Ship a helper subcommand: `ocd daemon --expose` using `cloudflared` (opt-in, documented)
- Ship a helper subcommand: `od daemon --expose` using `cloudflared` (opt-in, documented)
**Dev experience:**
- `ocd skill test` with cheap-model runs
- Skill author starter template: `ocd skill scaffold`
- `od skill test` with cheap-model runs
- Skill author starter template: `od skill scaffold`
### v1 exit criteria
1. All four modes fully functional.
2. Three adapters working (Claude Code, Codex, Cursor Agent); fallback chain shipping.
3. PDF + PPTX export working for at least the `magazine-web-ppt` + `pitch-deck` skills.
4. Deployed example at `demo.open-claude-design.dev` (Topology C).
4. Deployed example at `demo.open-design.dev` (Topology C).
5. Skill author docs published; at least one third-party skill submitted.
6. Documentation site rebuilt from these spec docs.
@@ -176,7 +176,7 @@ v2 isn't promised. It's the direction if v1 lands.
| `guizang-ppt-skill` or similar upstream skill changes format | default deck skill breaks | pin git SHA in our default install; monitor upstream |
| DESIGN.md format evolves in awesome-claude-design | incompatibility | track upstream; adopt changes; our resolver is tolerant of missing sections |
| Anthropic ships an open-source Claude Design | differentiation collapses | our moat is the "uses user's existing agent" angle; Anthropic is unlikely to ship that |
| Skill security (malicious skill via `ocd skill add`) | user machine compromise | install-time warning; rely on agent's own permission model; document best practices |
| Skill security (malicious skill via `od skill add`) | user machine compromise | install-time warning; rely on agent's own permission model; document best practices |
---
Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

+43
View File
@@ -0,0 +1,43 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid meet" role="img" aria-label="Entry view placeholder">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBF7EF"/>
<stop offset="100%" stop-color="#EFE7D7"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect x="32" y="32" width="1536" height="836" rx="28" ry="28"
fill="none" stroke="#C2532D" stroke-width="3" stroke-dasharray="16 12" opacity="0.85"/>
<g transform="translate(800 390)" stroke="#1F1B16" stroke-width="6"
stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.9">
<rect x="-110" y="-72" width="220" height="144" rx="18"/>
<rect x="-36" y="-94" width="72" height="26" rx="8"/>
<circle r="42"/>
<circle r="18"/>
</g>
<text x="800" y="480" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="34" font-weight="600" letter-spacing="6" fill="#C2532D">
01
</text>
<text x="800" y="560" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="56" font-weight="700" fill="#1F1B16">
Entry view
</text>
<text x="800" y="625" text-anchor="middle"
font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
font-size="26" fill="#6B6258">
docs/screenshots/01-entry-view.svg
</text>
<text x="800" y="690" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="24" fill="#6B6258">
Pick skill · pick design system · write the brief.
</text>
<text x="800" y="844" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="20" letter-spacing="4" fill="#6B6258" opacity="0.85">
SCREENSHOT PENDING · 截图占位
</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 KiB

+43
View File
@@ -0,0 +1,43 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid meet" role="img" aria-label="Discovery form placeholder">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBF7EF"/>
<stop offset="100%" stop-color="#EFE7D7"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect x="32" y="32" width="1536" height="836" rx="28" ry="28"
fill="none" stroke="#C2532D" stroke-width="3" stroke-dasharray="16 12" opacity="0.85"/>
<g transform="translate(800 390)" stroke="#1F1B16" stroke-width="6"
stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.9">
<rect x="-110" y="-72" width="220" height="144" rx="18"/>
<rect x="-36" y="-94" width="72" height="26" rx="8"/>
<circle r="42"/>
<circle r="18"/>
</g>
<text x="800" y="480" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="34" font-weight="600" letter-spacing="6" fill="#C2532D">
02
</text>
<text x="800" y="560" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="56" font-weight="700" fill="#1F1B16">
Discovery form
</text>
<text x="800" y="625" text-anchor="middle"
font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
font-size="26" fill="#6B6258">
docs/screenshots/02-question-form.svg
</text>
<text x="800" y="690" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="24" fill="#6B6258">
Turn-1 question form: surface · audience · tone · brand · scale.
</text>
<text x="800" y="844" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="20" letter-spacing="4" fill="#6B6258" opacity="0.85">
SCREENSHOT PENDING · 截图占位
</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

+43
View File
@@ -0,0 +1,43 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid meet" role="img" aria-label="Direction picker placeholder">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBF7EF"/>
<stop offset="100%" stop-color="#EFE7D7"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect x="32" y="32" width="1536" height="836" rx="28" ry="28"
fill="none" stroke="#C2532D" stroke-width="3" stroke-dasharray="16 12" opacity="0.85"/>
<g transform="translate(800 390)" stroke="#1F1B16" stroke-width="6"
stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.9">
<rect x="-110" y="-72" width="220" height="144" rx="18"/>
<rect x="-36" y="-94" width="72" height="26" rx="8"/>
<circle r="42"/>
<circle r="18"/>
</g>
<text x="800" y="480" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="34" font-weight="600" letter-spacing="6" fill="#C2532D">
03
</text>
<text x="800" y="560" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="56" font-weight="700" fill="#1F1B16">
Direction picker
</text>
<text x="800" y="625" text-anchor="middle"
font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
font-size="26" fill="#6B6258">
docs/screenshots/03-direction-picker.svg
</text>
<text x="800" y="690" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="24" fill="#6B6258">
5 curated visual directions · deterministic palette + font stack.
</text>
<text x="800" y="844" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="20" letter-spacing="4" fill="#6B6258" opacity="0.85">
SCREENSHOT PENDING · 截图占位
</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

+43
View File
@@ -0,0 +1,43 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid meet" role="img" aria-label="Live todo progress placeholder">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBF7EF"/>
<stop offset="100%" stop-color="#EFE7D7"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect x="32" y="32" width="1536" height="836" rx="28" ry="28"
fill="none" stroke="#C2532D" stroke-width="3" stroke-dasharray="16 12" opacity="0.85"/>
<g transform="translate(800 390)" stroke="#1F1B16" stroke-width="6"
stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.9">
<rect x="-110" y="-72" width="220" height="144" rx="18"/>
<rect x="-36" y="-94" width="72" height="26" rx="8"/>
<circle r="42"/>
<circle r="18"/>
</g>
<text x="800" y="480" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="34" font-weight="600" letter-spacing="6" fill="#C2532D">
04
</text>
<text x="800" y="560" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="56" font-weight="700" fill="#1F1B16">
Live todo progress
</text>
<text x="800" y="625" text-anchor="middle"
font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
font-size="26" fill="#6B6258">
docs/screenshots/04-todo-progress.svg
</text>
<text x="800" y="690" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="24" fill="#6B6258">
Streaming TodoWrite plan · in_progress → completed in real time.
</text>
<text x="800" y="844" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="20" letter-spacing="4" fill="#6B6258" opacity="0.85">
SCREENSHOT PENDING · 截图占位
</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

+43
View File
@@ -0,0 +1,43 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid meet" role="img" aria-label="Sandboxed preview placeholder">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBF7EF"/>
<stop offset="100%" stop-color="#EFE7D7"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect x="32" y="32" width="1536" height="836" rx="28" ry="28"
fill="none" stroke="#C2532D" stroke-width="3" stroke-dasharray="16 12" opacity="0.85"/>
<g transform="translate(800 390)" stroke="#1F1B16" stroke-width="6"
stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.9">
<rect x="-110" y="-72" width="220" height="144" rx="18"/>
<rect x="-36" y="-94" width="72" height="26" rx="8"/>
<circle r="42"/>
<circle r="18"/>
</g>
<text x="800" y="480" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="34" font-weight="600" letter-spacing="6" fill="#C2532D">
05
</text>
<text x="800" y="560" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="56" font-weight="700" fill="#1F1B16">
Sandboxed preview
</text>
<text x="800" y="625" text-anchor="middle"
font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
font-size="26" fill="#6B6258">
docs/screenshots/05-preview-iframe.svg
</text>
<text x="800" y="690" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="24" fill="#6B6258">
Generated &lt;artifact&gt; rendered in an isolated srcdoc iframe.
</text>
<text x="800" y="844" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="20" letter-spacing="4" fill="#6B6258" opacity="0.85">
SCREENSHOT PENDING · 截图占位
</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 KiB

@@ -0,0 +1,43 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid meet" role="img" aria-label="71-system library placeholder">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBF7EF"/>
<stop offset="100%" stop-color="#EFE7D7"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect x="32" y="32" width="1536" height="836" rx="28" ry="28"
fill="none" stroke="#C2532D" stroke-width="3" stroke-dasharray="16 12" opacity="0.85"/>
<g transform="translate(800 390)" stroke="#1F1B16" stroke-width="6"
stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.9">
<rect x="-110" y="-72" width="220" height="144" rx="18"/>
<rect x="-36" y="-94" width="72" height="26" rx="8"/>
<circle r="42"/>
<circle r="18"/>
</g>
<text x="800" y="480" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="34" font-weight="600" letter-spacing="6" fill="#C2532D">
06
</text>
<text x="800" y="560" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="56" font-weight="700" fill="#1F1B16">
71-system library
</text>
<text x="800" y="625" text-anchor="middle"
font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
font-size="26" fill="#6B6258">
docs/screenshots/06-design-systems-library.svg
</text>
<text x="800" y="690" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="24" fill="#6B6258">
Brand-grade DESIGN.md catalog with 4-color signatures.
</text>
<text x="800" y="844" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="20" letter-spacing="4" fill="#6B6258" opacity="0.85">
SCREENSHOT PENDING · 截图占位
</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

+43
View File
@@ -0,0 +1,43 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid meet" role="img" aria-label="Magazine deck placeholder">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBF7EF"/>
<stop offset="100%" stop-color="#EFE7D7"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect x="32" y="32" width="1536" height="836" rx="28" ry="28"
fill="none" stroke="#C2532D" stroke-width="3" stroke-dasharray="16 12" opacity="0.85"/>
<g transform="translate(800 390)" stroke="#1F1B16" stroke-width="6"
stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.9">
<rect x="-110" y="-72" width="220" height="144" rx="18"/>
<rect x="-36" y="-94" width="72" height="26" rx="8"/>
<circle r="42"/>
<circle r="18"/>
</g>
<text x="800" y="480" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="34" font-weight="600" letter-spacing="6" fill="#C2532D">
07
</text>
<text x="800" y="560" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="56" font-weight="700" fill="#1F1B16">
Magazine deck
</text>
<text x="800" y="625" text-anchor="middle"
font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
font-size="26" fill="#6B6258">
docs/screenshots/07-magazine-deck.svg
</text>
<text x="800" y="690" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="24" fill="#6B6258">
guizang-ppt skill · horizontal pages · WebGL hero · single-file HTML.
</text>
<text x="800" y="844" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="20" letter-spacing="4" fill="#6B6258" opacity="0.85">
SCREENSHOT PENDING · 截图占位
</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

+43
View File
@@ -0,0 +1,43 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid meet" role="img" aria-label="Mobile prototype placeholder">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBF7EF"/>
<stop offset="100%" stop-color="#EFE7D7"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect x="32" y="32" width="1536" height="836" rx="28" ry="28"
fill="none" stroke="#C2532D" stroke-width="3" stroke-dasharray="16 12" opacity="0.85"/>
<g transform="translate(800 390)" stroke="#1F1B16" stroke-width="6"
stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.9">
<rect x="-110" y="-72" width="220" height="144" rx="18"/>
<rect x="-36" y="-94" width="72" height="26" rx="8"/>
<circle r="42"/>
<circle r="18"/>
</g>
<text x="800" y="480" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="34" font-weight="600" letter-spacing="6" fill="#C2532D">
08
</text>
<text x="800" y="560" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="56" font-weight="700" fill="#1F1B16">
Mobile prototype
</text>
<text x="800" y="625" text-anchor="middle"
font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
font-size="26" fill="#6B6258">
docs/screenshots/08-mobile-app.svg
</text>
<text x="800" y="690" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="24" fill="#6B6258">
iPhone 15 Pro frame · multi-screen · shared /frames/ assets.
</text>
<text x="800" y="844" text-anchor="middle"
font-family="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
font-size="20" letter-spacing="4" fill="#6B6258" opacity="0.85">
SCREENSHOT PENDING · 截图占位
</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

+41 -41
View File
@@ -2,9 +2,9 @@
**Parent:** [`spec.md`](spec.md) · **Siblings:** [`architecture.md`](architecture.md) · [`agent-adapters.md`](agent-adapters.md) · [`modes.md`](modes.md)
A **Skill** is the atomic unit of design capability in OCD. We adopt Claude Code's `SKILL.md` convention verbatim as the base format, then add optional fields for design-specific features (preview type, input schema, slider parameters). A skill written for plain Claude Code runs in OCD. An OCD skill that doesn't use our extensions runs in plain Claude Code.
A **Skill** is the atomic unit of design capability in OD. We adopt Claude Code's `SKILL.md` convention verbatim as the base format, then add optional fields for design-specific features (preview type, input schema, slider parameters). A skill written for plain Claude Code runs in OD. An OD skill that doesn't use our extensions runs in plain Claude Code.
> **Compatibility promise:** A skill like [`guizang-ppt-skill`](https://github.com/op7418/guizang-ppt-skill) works in OCD **without modification**. It just drops into `~/.claude/skills/` and OCD discovers it.
> **Compatibility promise:** A skill like [`guizang-ppt-skill`](https://github.com/op7418/guizang-ppt-skill) works in OD **without modification**. It just drops into `~/.claude/skills/` and OD discovers it.
---
@@ -40,11 +40,11 @@ triggers:
Body is free-form Markdown that describes the workflow the agent should follow — typically a numbered step list plus principles. This is what [guizang-ppt-skill](https://github.com/op7418/guizang-ppt-skill) does.
**OCD reads all of this as-is.** No changes required.
**OD reads all of this as-is.** No changes required.
## 2. OCD extensions (optional)
## 2. OD extensions (optional)
Skills can declare additional front-matter fields to unlock OCD-specific UI. All fields are optional; absent fields fall back to sensible defaults.
Skills can declare additional front-matter fields to unlock OD-specific UI. All fields are optional; absent fields fall back to sensible defaults.
```yaml
---
@@ -52,9 +52,9 @@ name: magazine-web-ppt
description: …
triggers: […]
# --- OCD extensions below this line ---
# --- OD extensions below this line ---
ocd:
od:
mode: deck # one of: prototype | deck | template | design-system
preview:
type: html # html | jsx | pptx | markdown
@@ -94,21 +94,21 @@ ocd:
---
```
### 2.1 What OCD uses each field for
### 2.1 What OD uses each field for
| Field | Used by |
|---|---|
| `ocd.mode` | routing (which mode picker the skill shows up under) |
| `ocd.preview.type` | picking the right iframe renderer |
| `ocd.design_system.requires` | whether to inject `DESIGN.md` |
| `ocd.design_system.sections` | pruning the injected DESIGN.md to relevant sections only (token savings) |
| `ocd.inputs` | rendering a typed form in the sidebar instead of only free-text |
| `ocd.parameters` | rendering live sliders that re-prompt on change |
| `ocd.outputs.primary` | which file the iframe loads |
| `ocd.outputs.secondary` | which files export pipelines read (e.g. `slides.json` for PPTX) |
| `ocd.capabilities_required` | gating: if the active agent lacks surgical edit, comment mode is disabled for this skill |
| `od.mode` | routing (which mode picker the skill shows up under) |
| `od.preview.type` | picking the right iframe renderer |
| `od.design_system.requires` | whether to inject `DESIGN.md` |
| `od.design_system.sections` | pruning the injected DESIGN.md to relevant sections only (token savings) |
| `od.inputs` | rendering a typed form in the sidebar instead of only free-text |
| `od.parameters` | rendering live sliders that re-prompt on change |
| `od.outputs.primary` | which file the iframe loads |
| `od.outputs.secondary` | which files export pipelines read (e.g. `slides.json` for PPTX) |
| `od.capabilities_required` | gating: if the active agent lacks surgical edit, comment mode is disabled for this skill |
### 2.2 If a skill omits `ocd:` entirely
### 2.2 If a skill omits `od:` entirely
Defaults:
- `mode`: inferred from name/description (best-effort keyword match) or "prototype"
@@ -133,15 +133,15 @@ Conflicts by `name` resolve to the higher-priority version. All locations are wa
### Symlink strategy (borrowed from [cc-switch](https://github.com/farion1231/cc-switch))
`cc-switch` maintains a central skill dir at `~/.cc-switch/skills/` and symlinks it into each agent's expected location (`~/.claude/skills/`, `~/.codex/skills/`, etc.). OCD can opt into the same model:
`cc-switch` maintains a central skill dir at `~/.cc-switch/skills/` and symlinks it into each agent's expected location (`~/.claude/skills/`, `~/.codex/skills/`, etc.). OD can opt into the same model:
```
~/.open-claude-design/skills/
~/.open-design/skills/
magazine-web-ppt/ (canonical location)
~/.claude/skills/
magazine-web-ppt → ~/.open-claude-design/skills/magazine-web-ppt
magazine-web-ppt → ~/.open-design/skills/magazine-web-ppt
~/.codex/skills/
magazine-web-ppt → ~/.open-claude-design/skills/magazine-web-ppt
magazine-web-ppt → ~/.open-design/skills/magazine-web-ppt
```
One install → every agent sees the skill. This is optional; users who only use one agent don't need it.
@@ -181,17 +181,17 @@ Each mode expects a slightly different skill shape. The required outputs and exp
- **Preview:** `markdown` (render the resulting DESIGN.md with a sample-components preview).
- **Primary output:** `DESIGN.md`.
- **Typical workflow:** analyze input → draft 9 sections per awesome-claude-design schema → generate sample component preview → finalize.
- **Post-run:** OCD prompts the user to set this DESIGN.md as the project's active design system.
- **Post-run:** OD prompts the user to set this DESIGN.md as the project's active design system.
## 5. The DESIGN.md as skill context
Every nondesign-system skill (modes 13) can consume the active `DESIGN.md`. OCD injects it as:
Every nondesign-system skill (modes 13) can consume the active `DESIGN.md`. OD injects it as:
1. **System-prompt prefix** (required sections only, per `ocd.design_system.sections`).
1. **System-prompt prefix** (required sections only, per `od.design_system.sections`).
2. **File available in CWD** named `DESIGN.md` — skills can `Read` it directly via their agent.
3. **Template variable** `{{ design_system }}` if the skill body references it in Mustache-style.
The 9-section DESIGN.md format is **not invented by OCD**; it's the [awesome-claude-design](https://github.com/VoltAgent/awesome-claude-design) convention, reproduced here for convenience:
The 9-section DESIGN.md format is **not invented by OD**; it's the [awesome-claude-design](https://github.com/VoltAgent/awesome-claude-design) convention, reproduced here for convenience:
```markdown
# <Brand Name>
@@ -212,27 +212,27 @@ Full schema and examples: [`schemas/design-system.md`](schemas/design-system.md)
## 6. Skill installation
```sh
ocd skill add https://github.com/op7418/guizang-ppt-skill
# → clones into ~/.open-claude-design/skills/magazine-web-ppt
od skill add https://github.com/op7418/guizang-ppt-skill
# → clones into ~/.open-design/skills/magazine-web-ppt
# → symlinks into ~/.claude/skills/ (and any other active agent dirs)
# → re-indexes registry
ocd skill add ./path/to/my-skill
od skill add ./path/to/my-skill
# → symlinks local dir (no copy) into skills registry
ocd skill list
od skill list
# → table: name, mode, source, agent compatibility
ocd skill remove <name>
od skill remove <name>
# → unlinks; does not delete the source
```
## 7. Worked example — running `guizang-ppt-skill` under OCD
## 7. Worked example — running `guizang-ppt-skill` under OD
The skill is unchanged. Here's the full path:
1. User: `ocd skill add https://github.com/op7418/guizang-ppt-skill`
2. Registry indexes it. No `ocd:` block in front-matter → defaults applied:
1. User: `od skill add https://github.com/op7418/guizang-ppt-skill`
2. Registry indexes it. No `od:` block in front-matter → defaults applied:
- `mode`: inferred from body mentioning "PPT" → `deck`.
- `preview.type`: sniffed from `assets/template.html``html`.
- `preview.entry`: `index.html` (convention).
@@ -241,12 +241,12 @@ The skill is unchanged. Here's the full path:
4. User types "给我做一份杂志风 8 页投资人 PPT".
5. Daemon dispatches to active agent (Claude Code) with:
- system message: skill's `SKILL.md` body
- cwd: `./.ocd/artifacts/2026-04-24-pitch-deck/`
- cwd: `./.od/artifacts/2026-04-24-pitch-deck/`
- files already placed in cwd: `template.html` (from skill's `assets/`)
6. Agent runs its 6-step workflow (clarify → copy template → populate → self-check → preview → refine).
7. OCD streams the agent's tool calls as UI events; artifact dir grows.
7. OD streams the agent's tool calls as UI events; artifact dir grows.
8. Agent signals done; daemon sets preview iframe to `index.html`.
9. User clicks "Export PPTX" — export pipeline notices the skill has no `slides.json` output (the upstream skill doesn't produce one). OCD falls back to "print to PDF then page-to-slide PPTX," which is uglier but works. This is a known limitation documented per-skill.
9. User clicks "Export PPTX" — export pipeline notices the skill has no `slides.json` output (the upstream skill doesn't produce one). OD falls back to "print to PDF then page-to-slide PPTX," which is uglier but works. This is a known limitation documented per-skill.
## 8. Writing a new skill — minimal example
@@ -266,7 +266,7 @@ description: |
triggers:
- "saas landing"
- "marketing page"
ocd:
od:
mode: prototype
preview:
type: html
@@ -303,7 +303,7 @@ ocd:
## 9. Testing skills
A skill ships with optional test inputs that OCD uses for CI:
A skill ships with optional test inputs that OD uses for CI:
```
<skill-root>/
@@ -313,10 +313,10 @@ A skill ships with optional test inputs that OCD uses for CI:
└── basic.expected.regex.txt # text regex assertions against the primary output
```
`ocd skill test <name>` runs the skill against each case using a cheap model (e.g. Haiku 4.5) and asserts on the manifest + regex. Low-fidelity but catches structural regressions.
`od skill test <name>` runs the skill against each case using a cheap model (e.g. Haiku 4.5) and asserts on the manifest + regex. Low-fidelity but catches structural regressions.
## 10. Open questions
- **Skill signing.** Can we verify a skill hasn't been tampered with between publish and install? Simplest answer: `ocd skill add` records the git commit SHA; reinstall-on-update warns on signature change. Deferred to v1.
- **Skill signing.** Can we verify a skill hasn't been tampered with between publish and install? Simplest answer: `od skill add` records the git commit SHA; reinstall-on-update warns on signature change. Deferred to v1.
- **Skill composition.** Can a `prototype-skill` call a `deck-skill` for a sub-artifact? Not in v1; skills are leaf-level. Composition would require a meta-skill concept, which is speculative.
- **Parameter stability.** When sliders change, should the agent re-plan or just re-render? Lean: re-render (fast path), with an "also re-plan" button for larger changes.
+11 -11
View File
@@ -1,4 +1,4 @@
# Open Claude Design — Product Spec
# Open Design — Product Spec
**Status:** Draft v0.1 · 2026-04-24
**Scope:** Product definition, scenarios, non-goals, high-level modules, and positioning against both [Anthropic's Claude Design][cd] and the existing open-source alternative ([Open CoDesign][ocod]).
@@ -27,7 +27,7 @@ Other docs:
## 2. Core bets (and why they're different)
| # | Bet | [Anthropic Claude Design][cd] | [Open CoDesign][ocod] | OCD |
| # | Bet | [Anthropic Claude Design][cd] | [Open CoDesign][ocod] | OD |
|---|---|---|---|---|
| 1 | Where the product runs | claude.ai only | Local Electron app | **Next.js web app**`pnpm dev`, `vercel deploy`, or `docker compose up` |
| 2 | Who owns the agent loop | Anthropic, closed | [Open CoDesign][ocod] itself, via [`pi-ai`][piai] | **The user's existing code agent CLI** (Claude Code, Codex, Cursor Agent, Gemini CLI, OpenCode, OpenClaw); direct Anthropic API as fallback |
@@ -47,16 +47,16 @@ The differentiation is not "yet another design generator." It is **an integratio
## 4. User scenarios
### S1 — "Give me a prototype"
User opens the web app, types *"Airbnb-style search page, use our internal design system"*, OCD picks the `prototype-skill`, resolves the user's `DESIGN.md`, dispatches to Claude Code with both files plus the brief, streams tool calls into the UI, and renders the resulting HTML in an iframe preview. User clicks an element, drops a comment, the agent rewrites just that region.
User opens the web app, types *"Airbnb-style search page, use our internal design system"*, OD picks the `prototype-skill`, resolves the user's `DESIGN.md`, dispatches to Claude Code with both files plus the brief, streams tool calls into the UI, and renders the resulting HTML in an iframe preview. User clicks an element, drops a comment, the agent rewrites just that region.
### S2 — "Make me a deck"
User says *"8-slide magazine-style pitch deck for my seed round"*. OCD routes to `deck-skill` (a fork of [`guizang-ppt-skill`][guizang]). Output is a single-file HTML deck; preview is the deck itself with arrow-key navigation; export is PDF/PPTX.
User says *"8-slide magazine-style pitch deck for my seed round"*. OD routes to `deck-skill` (a fork of [`guizang-ppt-skill`][guizang]). Output is a single-file HTML deck; preview is the deck itself with arrow-key navigation; export is PDF/PPTX.
### S3 — "Start from a template"
User picks "SaaS landing — Stripe-ish" from a gallery. Template is a pre-filled artifact bundle plus a `DESIGN.md` reference. Agent only fills content; structure is already there. This is the fastest mode — useful for users who don't want to prompt at all.
### S4 — "Set up our design system"
User uploads a screenshot, brand guide PDF, or Figma link. OCD runs `design-system-skill` which produces a `DESIGN.md` following the 9-section format. That file is then referenced by every subsequent generation — prototypes, decks, templates all pick up the tokens.
User uploads a screenshot, brand guide PDF, or Figma link. OD runs `design-system-skill` which produces a `DESIGN.md` following the 9-section format. That file is then referenced by every subsequent generation — prototypes, decks, templates all pick up the tokens.
These four scenarios map 1:1 to the four modes in [`modes.md`](modes.md).
@@ -69,7 +69,7 @@ These four scenarios map 1:1 to the four modes in [`modes.md`](modes.md).
└────────────┬─────────────────────────────────┬───────────────────┘
│ WebSocket (JSON-RPC) │ HTTPS (BYOK direct)
┌────────────▼──────────────────┐ ┌────────▼─────────────────┐
│ Local Daemon (ocd daemon) │ │ Anthropic Messages API │
│ Local Daemon (od daemon) │ │ Anthropic Messages API │
│ · agent detection │ │ (fallback when no CLI) │
│ · skill registry │ └──────────────────────────┘
│ · artifact store │
@@ -88,7 +88,7 @@ Module responsibilities:
- **Daemon** — long-running local process. Detects agents, registers skills, manages artifacts on disk, resolves the active design system, and brokers WebSocket sessions.
- **Agent adapters** — one adapter per supported CLI; see [`agent-adapters.md`](agent-adapters.md).
- **Skill registry** — scans `~/.claude/skills/`, `./skills/`, and `./.claude/skills/`; merges and exposes a typed catalog.
- **Artifact store** — project-scoped folder (default `./.ocd/`) holding generated files, version snapshots (git-friendly), and per-artifact metadata.
- **Artifact store** — project-scoped folder (default `./.od/`) holding generated files, version snapshots (git-friendly), and per-artifact metadata.
- **Design-system resolver** — loads the active `DESIGN.md`, injects it as skill context.
- **Preview renderer** — sandboxed iframe with vendored React + Babel for JSX artifacts; plain iframe for HTML; PDF via the daemon's headless Chrome.
- **Export pipeline** — HTML (inlined), PDF, PPTX, ZIP, Markdown.
@@ -122,20 +122,20 @@ We are **not** trying to out-feature [Claude Design][cd]. Claude Design has Anth
- **Skills as files.** Version them in git. Fork them. Ship them to teammates as a repo. Run your team's branded deck skill without rebuilding a product.
- **Design systems as files.** A `DESIGN.md` is an artifact you can review in a PR. Claude Design's "design system" lives in an ephemeral chat.
In short: Claude Design is a product; OCD is a **substrate**.
In short: Claude Design is a product; OD is a **substrate**.
## 9. Success criteria for v1
- One developer can `git clone && pnpm install && pnpm dev`, point at their Claude Code install, and produce a prototype in under 5 minutes.
- A third party can author a skill in a separate git repo, publish it, and have a user install it by running `ocd skill add <git-url>` without touching OCD's source.
- A design system author can write a `DESIGN.md`, point OCD at it, and have the style propagate across prototype / deck / template outputs.
- A third party can author a skill in a separate git repo, publish it, and have a user install it by running `od skill add <git-url>` without touching OD's source.
- A design system author can write a `DESIGN.md`, point OD at it, and have the style propagate across prototype / deck / template outputs.
- Deploying to Vercel with a local daemon works end-to-end (the daemon is reachable via localhost tunnel or a user-provided URL).
- Swapping the underlying agent from Claude Code to Codex requires zero skill changes.
## 10. Open questions (to resolve before coding)
- **Daemon ↔ Vercel bridge.** Do we ship a reverse-tunnel helper (like `cloudflared`), require the user to set one up, or punt to "run locally for now"? My current lean: punt for MVP, helper in v1.
- **Artifact versioning.** Git, or SQLite, or both? [Open CoDesign][ocod] uses SQLite; that's easier but less reviewable. Lean: write artifacts as plain files + a `.ocd/history.jsonl` log. Git is the user's business.
- **Artifact versioning.** Git, or SQLite, or both? [Open CoDesign][ocod] uses SQLite; that's easier but less reviewable. Lean: write artifacts as plain files + a `.od/history.jsonl` log. Git is the user's business.
- **Comment mode on non-Claude-Code agents.** Claude Code supports surgical edits via its tool loop. Codex and Gemini CLI are less graceful. Do we degrade to "regenerate whole file" for weaker agents? Lean: yes, document clearly in the adapter table.
- **Skill trust model.** Skills can shell out via the agent. We should at minimum warn on install, and probably sandbox the agent's cwd to the project directory. Claude Code's permission mode handles this for us if we use it; Codex is looser. Needs a per-adapter note.
+1 -1
View File
@@ -6,7 +6,7 @@
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
<link rel="mask-icon" href="/logo.svg" color="#1F1B16" />
<meta name="theme-color" content="#F4EFE6" />
<title>Open Claude Design</title>
<title>Open Design</title>
</head>
<body>
<div id="root"></div>
+3 -3
View File
@@ -1,11 +1,11 @@
{
"name": "open-claude-design",
"name": "open-design",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "open-claude-design",
"name": "open-design",
"version": "0.1.0",
"dependencies": {
"@anthropic-ai/sdk": "^0.32.1",
@@ -16,7 +16,7 @@
"react-dom": "^18.3.1"
},
"bin": {
"ocd": "daemon/cli.js"
"od": "daemon/cli.js"
},
"devDependencies": {
"@types/react": "^18.3.12",
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "open-claude-design",
"name": "open-design",
"version": "0.1.0",
"private": true,
"type": "module",
"description": "Local-first design product: detects your installed code-agent CLI, runs design skills + design systems, streams artifacts into a sandboxed preview.",
"license": "Apache-2.0",
"bin": {
"ocd": "./daemon/cli.js"
"od": "./daemon/cli.js"
},
"scripts": {
"daemon": "node daemon/cli.js --no-open",
+2 -2
View File
@@ -1,5 +1,5 @@
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64' fill='none' role='img' aria-label='Open Claude Design'>
<title>Open Claude Design</title>
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64' fill='none' role='img' aria-label='Open Design'>
<title>Open Design</title>
<g stroke='#1F1B16' stroke-width='3.4' stroke-linecap='square' fill='none'>
<path d='M10 24 L10 10 L24 10' />
<path d='M40 10 L54 10 L54 24' />

Before

Width:  |  Height:  |  Size: 670 B

After

Width:  |  Height:  |  Size: 656 B

+2 -2
View File
@@ -14,7 +14,7 @@ triggers:
- "newsletter"
- "博客"
- "文章"
ocd:
od:
mode: prototype
platform: desktop
scenario: marketing
@@ -57,7 +57,7 @@ Produce a single long-form article page — editorial layout, no chrome.
rule (typically 680720px).
- Drop caps (`first-letter`) only if the DS mood is editorial / serif —
skip on tech-y DSes.
- `data-ocd-id` on the headline, hero, body, pull quote, related grid.
- `data-od-id` on the headline, hero, body, pull quote, related grid.
5. **Self-check**:
- Type hierarchy is unambiguous — H1 is clearly the headline; H2s are
section dividers; pull quotes do not compete with H1.
+2 -2
View File
@@ -34,7 +34,7 @@
</style>
</head>
<body>
<article class="wrap" data-ocd-id="article">
<article class="wrap" data-od-id="article">
<nav class="top"><a href="#">← Filebase blog</a></nav>
<div class="eyebrow">Engineering</div>
<h1>Why we rewrote our sync engine in Rust</h1>
@@ -43,7 +43,7 @@
<span>By Mira Hassan · April 22, 2026 · 8 min read</span>
</div>
<p class="lede">For two years our Go sync engine was good enough. Then video editors started joining the customer list, and the GC pauses we'd been politely ignoring turned into bug reports we couldn't ignore.</p>
<div class="hero-figure" data-ocd-id="hero-figure"></div>
<div class="hero-figure" data-od-id="hero-figure"></div>
<p>The decision wasn't sudden. We'd been watching the GC pause distribution shift for six months before we admitted what the data was telling us. P50 latency was great. P99 was a horror movie. Customers syncing 30 GB of <code>.psd</code> files in active editing sessions were the ones writing in.</p>
+2 -2
View File
@@ -19,7 +19,7 @@ triggers:
- "review my landing page"
- "评审"
- "复盘"
ocd:
od:
mode: prototype
platform: desktop
scenario: design
@@ -52,7 +52,7 @@ the *huashu-design* expert-critique flow.
A single self-contained `<artifact type="text/html">` review report
including:
1. **Header** — what artifact was reviewed, date, reviewer ("OCD ·
1. **Header** — what artifact was reviewed, date, reviewer ("OD ·
Critique skill"), 1-line verdict
2. **Radar chart** (inline SVG, no library) showing the 5 scores
3. **Five dimension cards**, each with:
+2 -2
View File
@@ -389,7 +389,7 @@
<span>·</span>
<span>2026.04.27</span>
<span>·</span>
<span>OCD · Critique skill</span>
<span>OD · Critique skill</span>
</div>
<h1 class="hd-title">magazine-web-ppt<br>example deck</h1>
</div>
@@ -662,7 +662,7 @@
</div>
<footer class="ft">
<span>OCD · Critique skill · v0.1</span>
<span>OD · Critique skill · v0.1</span>
<span>5 dimensions · Phil / Hier / Det / Func / Innov</span>
<span class="br">github.com/alchaincyf/huashu-design</span>
</footer>
+2 -2
View File
@@ -12,7 +12,7 @@ triggers:
- "control panel"
- "后台"
- "管理后台"
ocd:
od:
mode: prototype
platform: desktop
scenario: operations
@@ -49,7 +49,7 @@ Produce a single-screen admin / analytics dashboard.
- `<!doctype html>` through `</html>`, CSS in one inline `<style>` block.
- CSS Grid for the overall layout; Flexbox inside cards.
- Semantic HTML: `<aside>`, `<header>`, `<main>`, `<section>`.
- Tag each logical region with `data-ocd-id="slug"` for comment mode.
- Tag each logical region with `data-od-id="slug"` for comment mode.
5. **Charts**: inline SVG only, no JS libraries. A line chart is ~10 lines of
`<polyline>` with a subtle area fill. A bar chart is N `<rect>`s with
DS-accent fill. Label axes lightly (muted text, smaller scale).
+6 -6
View File
@@ -48,7 +48,7 @@
</style>
</head>
<body>
<aside class="sidebar" data-ocd-id="sidebar">
<aside class="sidebar" data-od-id="sidebar">
<div class="brand">◐ Pulse</div>
<nav class="nav">
<a href="#" class="active">Overview</a>
@@ -63,7 +63,7 @@
</nav>
</aside>
<main>
<div class="topbar" data-ocd-id="topbar">
<div class="topbar" data-od-id="topbar">
<h1>Overview · April 2026</h1>
<div class="right">
<button class="btn-secondary">Last 30 days ▾</button>
@@ -71,7 +71,7 @@
</div>
</div>
<div class="kpis" data-ocd-id="kpis">
<div class="kpis" data-od-id="kpis">
<div class="kpi"><div class="label">MRR</div><div class="value">$48.2K</div><div class="delta up">+12.4% MoM</div></div>
<div class="kpi"><div class="label">Active accounts</div><div class="value">3,184</div><div class="delta up">+204 this month</div></div>
<div class="kpi"><div class="label">Churn (30d)</div><div class="value">2.1%</div><div class="delta down">+0.4 pp</div></div>
@@ -79,7 +79,7 @@
</div>
<div class="panels-row">
<div class="panel" data-ocd-id="chart-panel">
<div class="panel" data-od-id="chart-panel">
<h3>Revenue · 30 days</h3>
<div class="chart">
<svg viewBox="0 0 600 240" preserveAspectRatio="none">
@@ -87,7 +87,7 @@
</svg>
</div>
</div>
<div class="panel" data-ocd-id="signups-panel">
<div class="panel" data-od-id="signups-panel">
<h3>New accounts</h3>
<table>
<thead><tr><th>Account</th><th>Plan</th><th>Status</th></tr></thead>
@@ -101,7 +101,7 @@
</div>
</div>
<div class="panel" data-ocd-id="recent-events">
<div class="panel" data-od-id="recent-events">
<h3>Recent events</h3>
<table>
<thead><tr><th>Time</th><th>Account</th><th>Event</th><th>Plan</th></tr></thead>
+2 -2
View File
@@ -16,7 +16,7 @@ triggers:
- "consumer dashboard"
- "约会应用"
- "婚恋"
ocd:
od:
mode: prototype
platform: desktop
scenario: personal
@@ -72,7 +72,7 @@ accent, lots of negative space, *no* swipe deck or hookup tropes.
- Background creamy off-white, body serif, mono labels everywhere.
- Use `font-feature-settings: 'tnum'` on the metric numerals.
- SVG bar chart with ~30 bars, varied heights.
- `data-ocd-id` on ticker, sidebar, kpi grid, chart, trend.
- `data-od-id` on ticker, sidebar, kpi grid, chart, trend.
5. **Self-check**:
- Reads as restrained, editorial, slightly funny — not horny.
- Single accent token used in 34 places max (one KPI, two highlight
+6 -6
View File
@@ -110,7 +110,7 @@
</style>
</head>
<body>
<div class="ticker" data-ocd-id="ticker">
<div class="ticker" data-od-id="ticker">
<div class="left">
<span>YOUR DATING LIFE, MEASURED BY THE COMPANY YOU KEEP</span>
<span style="opacity:0.6;">·</span>
@@ -120,7 +120,7 @@
</div>
<div class="layout">
<aside class="rail" data-ocd-id="rail">
<aside class="rail" data-od-id="rail">
<div class="brand">mutuals<span class="dot">.</span></div>
<div class="user">
<div class="avatar">si</div>
@@ -159,8 +159,8 @@
</div>
</aside>
<main data-ocd-id="main">
<section class="grid" data-ocd-id="kpis">
<main data-od-id="main">
<section class="grid" data-od-id="kpis">
<div class="stat">
<div class="label">Mutuals on file</div>
<div class="value"><em>1,842</em></div>
@@ -210,7 +210,7 @@
</div>
</section>
<section class="panel" data-ocd-id="bars">
<section class="panel" data-od-id="bars">
<div class="panel-head">
<h3>mutuals — <em>last 30 days</em></h3>
<div class="meta">↑ TRENDING UP · +3 CLOSE MUTUALS THIS MONTH · TWO VIA THE SAME OFFSITE</div>
@@ -252,7 +252,7 @@
<div class="axis"><span>MAR 18</span><span>MAR 25</span><span>APR 1</span><span>APR 8</span><span>APR 15</span><span>TODAY</span></div>
</section>
<section class="panel lower-panel" data-ocd-id="trend">
<section class="panel lower-panel" data-od-id="trend">
<div class="panel-head">
<h3>match rate — <em>last 12 weeks</em></h3>
<div class="meta">STEADY CLIMB FROM 8% → 14%. ATTRIBUTABLE TO ONE COMMUNITY JOIN (FOUNDERS WHO POST, WK 4).</div>
+2 -2
View File
@@ -18,7 +18,7 @@ triggers:
- "ebook"
- "电子指南"
- "电子书"
ocd:
od:
mode: prototype
platform: desktop
scenario: marketing
@@ -71,7 +71,7 @@ serif display headings, careful column rhythm.
- `<!doctype html>` through `</html>`, CSS inline.
- Pages are 600×860 paper-tone cards with 6px shadow, slight rotation
opposing each other (±0.6deg) for a magazine-on-desk feel.
- `data-ocd-id` on cover, spread, toc, pull-quote, exercise.
- `data-od-id` on cover, spread, toc, pull-quote, exercise.
5. **Self-check**:
- Type hierarchy is editorial — title owns page 1, sub-title owns page 2.
- Italic accent appears once per page.
+5 -5
View File
@@ -137,7 +137,7 @@
</style>
</head>
<body>
<article class="page left cover" data-ocd-id="cover">
<article class="page left cover" data-od-id="cover">
<div class="eyebrow">
<div class="left"><span class="dot"></span>STYLE &amp; FORMAT GUIDE FOR CREATORS</div>
<div class="right">2026 EDITION</div>
@@ -155,7 +155,7 @@
<h2 class="inside">What's <em>inside.</em></h2>
<div class="toc" data-ocd-id="toc">
<div class="toc" data-od-id="toc">
<div class="item"><span class="name">Find your voice</span><span class="leader"></span><span class="pn">04</span></div>
<div class="item"><span class="name">Pick a format</span><span class="leader"></span><span class="pn">12</span></div>
<div class="item"><span class="name">Tone &amp; tension</span><span class="leader"></span><span class="pn">18</span></div>
@@ -168,7 +168,7 @@
<div class="cover-footer"><span>FIND YOUR VOICE</span><span>01 / 64</span></div>
</article>
<article class="page right spread" data-ocd-id="spread">
<article class="page right spread" data-od-id="spread">
<div class="eyebrow">
<div class="left"><span class="dot"></span>CHAPTER 02 · TONE</div>
<div class="right">3 — RULES, 1 — EXERCISE</div>
@@ -187,13 +187,13 @@
</div>
</div>
<div class="pullquote" data-ocd-id="pullquote">
<div class="pullquote" data-od-id="pullquote">
<span class="open">"</span>
Specificity is the unlock — write what only you saw.
<span class="by">— AUNY · CHAPTER 02</span>
</div>
<div class="exercise" data-ocd-id="exercise">
<div class="exercise" data-od-id="exercise">
<span class="label">EXERCISE</span>
<span class="text">Rewrite your last three captions without the words <em>just</em>, <em>really</em>, or <em>very</em>. Keep what survives.</span>
</div>
+2 -2
View File
@@ -11,7 +11,7 @@ triggers:
- "tutorial"
- "api reference"
- "文档"
ocd:
od:
mode: prototype
platform: desktop
scenario: engineering
@@ -48,7 +48,7 @@ Produce a single, three-column documentation page in one HTML file.
- Code blocks: monospace token, soft surface fill, copy-button affordance
(visual only — no JS needed).
- Anchor IDs on every H2/H3 so the TOC links work.
- `data-ocd-id` on the nav, article, and TOC.
- `data-od-id` on the nav, article, and TOC.
5. **Prose**: write at least 350 words of believable docs. Include at least
one shell command, one code snippet (515 lines), one callout, one table.
6. **Self-check**:
+4 -4
View File
@@ -45,12 +45,12 @@
</style>
</head>
<body>
<header class="topbar" data-ocd-id="topbar">
<header class="topbar" data-od-id="topbar">
<span class="brand">◰ Filebase docs</span>
<input placeholder="Search · ⌘K" />
</header>
<div class="layout">
<nav class="sidebar" data-ocd-id="sidebar">
<nav class="sidebar" data-od-id="sidebar">
<div class="group">
<div class="group-label">Getting started</div>
<a href="#" class="active">Quickstart</a>
@@ -70,7 +70,7 @@
<a href="#">Subcommands</a>
</div>
</nav>
<article data-ocd-id="article">
<article data-od-id="article">
<div class="crumbs">Docs Getting started Quickstart</div>
<h1>Quickstart</h1>
<p class="lede">Sync your first folder in under five minutes. The CLI is the fastest path; the desktop app and the API client all wrap the same engine.</p>
@@ -110,7 +110,7 @@ build/</code></pre>
<a href="#" style="text-align: right;"><small>Next →</small>Conflict resolution</a>
</div>
</article>
<aside class="toc" data-ocd-id="toc">
<aside class="toc" data-od-id="toc">
<div class="toc-label">On this page</div>
<a href="#install" class="active">1. Install the CLI</a>
<a href="#auth">2. Authenticate</a>
+2 -2
View File
@@ -15,7 +15,7 @@ triggers:
- "mjml"
- "邮件营销"
- "邮件模板"
ocd:
od:
mode: prototype
platform: desktop
scenario: marketing
@@ -65,7 +65,7 @@ email body. Treat it like a marketing artifact: one big idea, one CTA.
so the email-on-page metaphor reads.
- No external images — use inline SVG or DS-tinted gradient blocks for the
product photo.
- `data-ocd-id` on the masthead, hero, headline, CTA, specs.
- `data-od-id` on the masthead, hero, headline, CTA, specs.
5. **Self-check**:
- Email reads top to bottom in 810 seconds.
- One CTA. Accent appears at most twice (eyebrow + CTA, or headline word).
+8 -8
View File
@@ -68,8 +68,8 @@
</style>
</head>
<body>
<div class="frame" data-ocd-id="email">
<header class="masthead" data-ocd-id="masthead">
<div class="frame" data-od-id="email">
<header class="masthead" data-od-id="masthead">
<div class="wordmark">
<span class="mark"></span>
<span class="lockup">SPORT TEST</span>
@@ -78,7 +78,7 @@
<nav class="nav"><a href="#">SHOP</a><a href="#">JOURNAL</a><a href="#">MEMBERS</a></nav>
</header>
<div class="hero" data-ocd-id="hero">
<div class="hero" data-od-id="hero">
<div class="stamp-tl">— SPORT TEST</div>
<svg class="shoe" viewBox="0 0 600 280" aria-hidden="true">
<defs>
@@ -113,18 +113,18 @@
<div class="stamp-br">DROP 04 · 04—2026</div>
</div>
<section class="article" data-ocd-id="article">
<section class="article" data-od-id="article">
<div class="eyebrow"><span class="bar"></span>NEW · MAX-CUSHION TRAINER · EMBER FLARE</div>
<h1 class="lockup" data-ocd-id="headline">
<h1 class="lockup" data-od-id="headline">
Meet the<br/>
<span class="axis">Axis Pro.</span><br/>
A sneaker that runs.
</h1>
<p class="body">A plush, gel-cushioned trainer wrapped in a painterly flame-knit upper. Built for long days on the road, café runs, and everything between — softer underfoot, louder on the outside. Limited first drop in <em>Ember Flare</em>.</p>
<a class="cta" href="#" data-ocd-id="cta">Shop the Axis Pro <span class="arrow"></span></a>
<a class="cta" href="#" data-od-id="cta">Shop the Axis Pro <span class="arrow"></span></a>
</section>
<section class="specs" data-ocd-id="specs">
<section class="specs" data-od-id="specs">
<div class="head"><span class="bar"></span>SPECIFICATIONS · WOMEN'S</div>
<div class="specs-grid">
<div class="spec">
@@ -146,7 +146,7 @@
</div>
</section>
<footer class="footer" data-ocd-id="footer">
<footer class="footer" data-od-id="footer">
<div class="left">
<div class="marks"><span style="display:inline-block;width:18px;height:18px;background:var(--accent);transform:skew(-12deg);"></span><span class="lockup" style="font-family:'Anton',sans-serif;font-size:18px;letter-spacing:0.04em;">SPORT TEST</span></div>
<div>118 Stillman St · Brooklyn NY 11211</div>
+1 -1
View File
@@ -12,7 +12,7 @@ triggers:
- "sre doc"
- "service runbook"
- "运维手册"
ocd:
od:
mode: prototype
platform: desktop
scenario: engineering
+1 -1
View File
@@ -13,7 +13,7 @@ triggers:
- "mrr review"
- "财报"
- "财务报告"
ocd:
od:
mode: prototype
platform: desktop
scenario: finance
+2 -2
View File
@@ -18,7 +18,7 @@ triggers:
- "life management app"
- "游戏化"
- "习惯打卡"
ocd:
od:
mode: prototype
platform: mobile
scenario: personal
@@ -85,7 +85,7 @@ Three phone frames side-by-side, each one its own moment in the journey.
- `<!doctype html>` through `</html>`, CSS inline.
- All in CSS — no images. Use `linear-gradient` and inline SVG glyphs
for tile chips and tab icons.
- `data-ocd-id` on stage, each phone, each frame's regions.
- `data-od-id` on stage, each phone, each frame's regions.
9. **Self-check**:
- Three frames, each with a distinct purpose. Not three copies of the
same screen.
+10 -10
View File
@@ -171,16 +171,16 @@
</style>
</head>
<body>
<div class="stage-bar" data-ocd-id="stage-bar">
<div class="stage-bar" data-od-id="stage-bar">
<span>HI-FI PROTOTYPE · IPHONE</span>
<span class="word">level<span style="color:var(--accent);">.</span></span>
<span>3 SCREENS · LIGHT MODE</span>
</div>
<div class="phones" data-ocd-id="phones">
<div class="phones" data-od-id="phones">
<!-- Phone 1 — cover -->
<div class="phone" data-ocd-id="phone-cover">
<div class="phone" data-od-id="phone-cover">
<div class="screen cover">
<div class="status"><span>9:41</span><span class="right">·· 5G · 100%</span></div>
<div class="body">
@@ -194,14 +194,14 @@
</div>
<!-- Phone 2 — quests dashboard -->
<div class="phone" data-ocd-id="phone-home">
<div class="phone" data-od-id="phone-home">
<div class="screen home">
<div class="status"><span>9:41</span><span class="right">·· 5G · 100%</span></div>
<div class="head">
<h2>Good morning, Sam</h2>
<div class="bell">×3</div>
</div>
<div class="level-ribbon" data-ocd-id="level-ribbon">
<div class="level-ribbon" data-od-id="level-ribbon">
<div class="lv">14</div>
<div class="meta"><div class="label">LEVEL</div><div class="name">Level 14</div></div>
<div class="xp">1648 / 2480</div>
@@ -209,7 +209,7 @@
</div>
<div class="sub">8 quests waiting · earn <span class="pill">430 XP</span> today</div>
<div class="quests" data-ocd-id="quests">
<div class="quests" data-od-id="quests">
<div class="q q1">
<div class="glyph">B</div>
<p class="title">Body</p>
@@ -248,7 +248,7 @@
</div>
</div>
<div class="tabbar" data-ocd-id="tabbar-home">
<div class="tabbar" data-od-id="tabbar-home">
<div class="tab active"><div class="icon"></div>Today</div>
<div class="tab"><div class="icon"></div>Library</div>
<div class="tab center"><div class="icon">+</div>&nbsp;</div>
@@ -259,7 +259,7 @@
</div>
<!-- Phone 3 — detail -->
<div class="phone" data-ocd-id="phone-detail">
<div class="phone" data-od-id="phone-detail">
<div class="screen detail">
<div class="status"><span>9:41</span><span class="right">·· 5G · 100%</span></div>
<div class="topbar"><div class="back"></div>QUEST · 03 / 08</div>
@@ -269,7 +269,7 @@
<h2>20 minutes that change Wednesday.</h2>
<p>A short, repeatable strength block — pushups, planks, and one wildcard. No equipment. Sam, you've finished this 11 times this month.</p>
</div>
<div class="steps" data-ocd-id="steps">
<div class="steps" data-od-id="steps">
<h3>Today's micro-tasks</h3>
<div class="step done"><div class="check"></div><div class="name">Roll out the mat</div><div class="meta">+5 XP</div></div>
<div class="step"><div class="check"></div><div class="name">3 × 12 pushups</div><div class="meta">+30 XP</div></div>
@@ -277,7 +277,7 @@
<div class="step"><div class="check"></div><div class="name">Wildcard: lunges</div><div class="meta">+25 XP</div></div>
</div>
<div class="start">Start quest</div>
<div class="tabbar" data-ocd-id="tabbar-detail">
<div class="tabbar" data-od-id="tabbar-detail">
<div class="tab active"><div class="icon"></div>Today</div>
<div class="tab"><div class="icon"></div>Library</div>
<div class="tab center"><div class="icon">+</div>&nbsp;</div>
+1 -1
View File
@@ -16,7 +16,7 @@ triggers:
- "网页 PPT"
- "发布会"
- "分享 PPT"
ocd:
od:
mode: deck
scenario: marketing
featured: 9
+1 -1
View File
@@ -11,7 +11,7 @@ triggers:
- "first week"
- "入职"
- "新员工"
ocd:
od:
mode: prototype
platform: desktop
scenario: hr
+1 -1
View File
@@ -10,7 +10,7 @@ triggers:
- "billing statement"
- "发票"
- "账单"
ocd:
od:
mode: prototype
platform: desktop
scenario: finance
+1 -1
View File
@@ -12,7 +12,7 @@ triggers:
- "trello"
- "jira board"
- "看板"
ocd:
od:
mode: prototype
platform: desktop
scenario: operations
+2 -2
View File
@@ -17,7 +17,7 @@ triggers:
- "long-form poster"
- "杂志海报"
- "报纸版式"
ocd:
od:
mode: prototype
platform: desktop
scenario: marketing
@@ -67,7 +67,7 @@ Sunday paper. Long-form, deliberate, type-driven.
- Background uses a creamy paper tint (`#f3eee2` or DS canvas) plus a
subtle paper noise (`radial-gradient` dots at low opacity).
- 2-column body grid via CSS Grid; min-width 1100px page.
- `data-ocd-id` on header, headline, deck, each cell, footer.
- `data-od-id` on header, headline, deck, each cell, footer.
5. **Self-check**:
- Type hierarchy is unmistakable — headline owns the page.
- Strikethrough + italic accent both appear, exactly once each.
+12 -12
View File
@@ -138,55 +138,55 @@
</head>
<body>
<div class="page">
<div class="top-rule" data-ocd-id="top-rule">
<div class="top-rule" data-od-id="top-rule">
<span>01 · AI ENTHUSIAST</span>
<span>17 · APR · 2026</span>
</div>
<div class="eyebrow-row" data-ocd-id="eyebrow">— POSTED TODAY</div>
<div class="eyebrow-row" data-od-id="eyebrow">— POSTED TODAY</div>
<h1 class="headline" data-ocd-id="headline">
<h1 class="headline" data-od-id="headline">
You don't need <span class="strike">a designer</span><br />
to ship your <span class="accent">first draft</span><br />
anymore.
</h1>
<p class="deck" data-ocd-id="deck">
<p class="deck" data-od-id="deck">
Six honest ways I'm using AI to move faster from idea → artifact this week — <b>what works</b>, what I'd still hand to a human, and the exact prompts that got me there.
</p>
<div class="accent-rule"></div>
<div class="grid" data-ocd-id="grid">
<section class="cell" data-ocd-id="cell-1">
<div class="grid" data-od-id="grid">
<section class="cell" data-od-id="cell-1">
<div class="num"><span class="bar"></span>01 · SHIP FAST</div>
<h3>Clickable prototype in 90 seconds</h3>
<p>Describe the flow in plain English. Get a real, tappable prototype — not static screens. Export to HTML and share the link.</p>
<div class="quote">Onboarding flow for a fintech app — 5 screens, dark mode, rounded cards, haptic-style transitions.</div>
</section>
<section class="cell" data-ocd-id="cell-2">
<section class="cell" data-od-id="cell-2">
<div class="num"><span class="bar"></span>02 · PITCH</div>
<h3>Investor deck from a napkin idea</h3>
<p>Skip the template hunt. Draft the deck, refine it section-by-section, then export straight to PPTX or PDF — notes included.</p>
<div class="quote">10-slide seed pitch for a RAG tool for lawyers. Keep it minimal, data-first, one chart per slide.</div>
</section>
<section class="cell" data-ocd-id="cell-3">
<section class="cell" data-od-id="cell-3">
<div class="num"><span class="bar"></span>03 · BRAND LOCK</div>
<h3>Your design system, auto-applied</h3>
<p>Point the model at your tokens, components, or a codebase. Every new asset respects your type, color, and spacing scale.</p>
<div class="quote">Use our /design-system tokens. Build a pricing page variant. Match the radius + shadow of the marketing site.</div>
</section>
<section class="cell" data-ocd-id="cell-4">
<section class="cell" data-od-id="cell-4">
<div class="num"><span class="bar"></span>04 · MARKETING</div>
<h3>Landing pages &amp; launch collateral</h3>
<p>One-pagers, email headers, feature comparison grids — editable, on-brand, and ready to hand off in minutes, not days.</p>
<div class="quote">One-pager for a Series A launch. Headline, three proof points, CTA. Editorial feel, no stock photos.</div>
</section>
<section class="cell" data-ocd-id="cell-5">
<section class="cell" data-od-id="cell-5">
<div class="num"><span class="bar"></span>05 · HANDOFF</div>
<h3>Design → engineering bundle</h3>
<p>Finished the mock? Ship the whole handoff to your dev environment. Specs, tokens, components — no translation layer.</p>
<div class="quote">Export this mock to code. Wire the auth screen to Supabase. Add a loading state and empty state.</div>
</section>
<section class="cell" data-ocd-id="cell-6">
<section class="cell" data-od-id="cell-6">
<div class="num"><span class="bar"></span>06 · EXPLORE</div>
<h3>Ten directions in ten minutes</h3>
<p>Generate N visual directions side-by-side. Use sliders to dial tone: playful, brutalist, editorial, corporate — same copy.</p>
@@ -194,7 +194,7 @@
</section>
</div>
<div class="footer" data-ocd-id="footer">
<div class="footer" data-od-id="footer">
<div class="pro-tip">
<span class="badge">PRO TIP</span>
<span class="text">Don't prompt for <b>"a good design."</b> Prompt for a mood — <b>"serene", "brutalist", "Bloomberg terminal," "Sunday newspaper."</b> Aesthetic specificity is the unlock.</span>
+1 -1
View File
@@ -11,7 +11,7 @@ triggers:
- "1:1 notes"
- "all-hands recap"
- "会议纪要"
ocd:
od:
mode: prototype
platform: desktop
scenario: operations
+1 -1
View File
@@ -14,7 +14,7 @@ triggers:
- "app mockup"
- "移动端"
- "手机 app"
ocd:
od:
mode: prototype
platform: mobile
scenario: design
+6 -6
View File
@@ -1,6 +1,6 @@
<!doctype html>
<!--
OCD mobile-app seed.
OD mobile-app seed.
A pixel-accurate iPhone 15 Pro frame (390 × 844) with Dynamic Island,
status-bar SVG icons, and home indicator — drawn entirely in HTML/SVG, no
@@ -361,7 +361,7 @@
<div class="stage">
<div class="caption"><strong>[REPLACE] App</strong> · [REPLACE] Screen name</div>
<div class="device" data-ocd-id="device">
<div class="device" data-od-id="device">
<span class="btn-rail left-1" aria-hidden></span>
<span class="btn-rail left-2" aria-hidden></span>
<span class="btn-rail left-3" aria-hidden></span>
@@ -394,8 +394,8 @@
</div>
<!-- ─── Scrollable content (paste a layout from references/layouts.md HERE) ─── -->
<main class="content" data-ocd-id="content">
<div class="header" data-ocd-id="header">
<main class="content" data-od-id="content">
<div class="header" data-od-id="header">
<div>
<p class="greeting">Tuesday · April 22</p>
<h1>[REPLACE] Hi there.</h1>
@@ -405,7 +405,7 @@
</button>
</div>
<div class="pad stack" data-ocd-id="empty-slot">
<div class="pad stack" data-od-id="empty-slot">
<div class="card" style="text-align: center; padding: 28px 20px;">
<p class="meta" style="margin: 0 0 6px;">PASTE A LAYOUT FROM</p>
<p class="h3" style="margin: 0 0 6px;">references/layouts.md</p>
@@ -415,7 +415,7 @@
</main>
<!-- ─── Tab bar (drop if the screen kind doesn't have one) ─── -->
<nav class="tabbar" style="--tabs: 4;" data-ocd-id="tabbar">
<nav class="tabbar" style="--tabs: 4;" data-od-id="tabbar">
<a class="tab active">
<svg viewBox="0 0 24 24"><path d="M3 12 12 3l9 9"/><path d="M5 10v10h14V10"/></svg>
Home
+6 -6
View File
@@ -50,14 +50,14 @@
</style>
</head>
<body>
<div class="frame" data-ocd-id="frame">
<div class="frame" data-od-id="frame">
<div class="screen">
<div class="status"><span>9:41</span><span class="right">·· 5G · 100%</span></div>
<div class="header" data-ocd-id="header">
<div class="header" data-od-id="header">
<p class="greeting">Tuesday · April 22</p>
<h1>Two pomodoros to lunch.</h1>
</div>
<div class="timer-card" data-ocd-id="timer">
<div class="timer-card" data-od-id="timer">
<p class="label">Focus session</p>
<div class="countdown">15:42</div>
<div class="progress"><span></span></div>
@@ -66,7 +66,7 @@
<button class="primary">Pause</button>
</div>
</div>
<div class="section" data-ocd-id="stats">
<div class="section" data-od-id="stats">
<p class="label">Today</p>
<div class="stats">
<div class="stat"><div class="v">3</div><div class="l">Sessions</div></div>
@@ -74,13 +74,13 @@
<div class="stat"><div class="v">2</div><div class="l">Tasks done</div></div>
</div>
</div>
<div class="tasks" data-ocd-id="tasks">
<div class="tasks" data-od-id="tasks">
<p class="section label" style="padding: 0;">Up next</p>
<div class="task done"><div class="check"></div><div class="body"><div class="title">Review Q2 OKRs</div><div class="meta">25m · completed</div></div></div>
<div class="task"><div class="check"></div><div class="body"><div class="title">Draft sync-engine post</div><div class="meta">2 sessions estimated</div></div></div>
<div class="task"><div class="check"></div><div class="body"><div class="title">1:1 prep with Mira</div><div class="meta">1 session</div></div></div>
</div>
<nav class="tabbar" data-ocd-id="tabbar">
<nav class="tabbar" data-od-id="tabbar">
<div class="tab active"><div class="icon"></div>Focus</div>
<div class="tab"><div class="icon"></div>Tasks</div>
<div class="tab"><div class="icon">📊</div>Stats</div>
+2 -2
View File
@@ -11,11 +11,11 @@ Run this before emitting `<artifact>`. P0 must pass.
- [ ] **Tap targets ≥ 44px tall.** The seed's `.btn-primary` (48px), `.tab` (~50px), `.icon-btn` (36px ≥ touch with padding), `.list-row` (≥48px with padding) all pass. Don't ship a button under 44px.
- [ ] **Body text ≥ 14px.** `--fs-body: 15px` already enforces this on most copy. List-row sub text uses 13px max — that's the floor.
- [ ] **One accent, used at most twice on the screen.** Typically: one active tab + one CTA, OR one accent card + one tab. Never three.
- [ ] **No external image URLs.** Use the `.ph-img` placeholder class. External CDN images break the OCD preview iframe and look fake when they 404.
- [ ] **No external image URLs.** Use the `.ph-img` placeholder class. External CDN images break the OD preview iframe and look fake when they 404.
- [ ] **Tab bar matches the screen kind.** Onboarding / detail / checkout: drop the `<nav class="tabbar">` entirely. Feed / focus / profile: keep it.
- [ ] **Display headlines use `var(--font-display)` (serif).** The seed binds this via `.h1`, `.h2`, `.header h1`. Don't override headings to system-sans — it instantly looks like a stock template.
- [ ] **No emoji icons in the UI.** SVG monoline only. Emoji in copy is fine ("9:41 ☀️ Tuesday" is not, but "Sunny day in Berlin" is).
- [ ] **`data-ocd-id` on the device, content, header, and any major sections.**
- [ ] **`data-od-id` on the device, content, header, and any major sections.**
## P1 — should pass
+21 -21
View File
@@ -21,7 +21,7 @@ If you reach for a class not on this list, define it in the seed's `<style>` fir
Top: greeting + title. Body: 46 list rows, hairline-separated. Tab bar: yes.
```html
<div class="header" data-ocd-id="header">
<div class="header" data-od-id="header">
<div>
<p class="greeting">Tuesday · April 22</p>
<h1>Inbox</h1>
@@ -31,7 +31,7 @@ Top: greeting + title. Body: 46 list rows, hairline-separated. Tab bar: yes.
</button>
</div>
<section class="pad" data-ocd-id="filters" style="margin-bottom: 8px;">
<section class="pad" data-od-id="filters" style="margin-bottom: 8px;">
<div class="row" style="overflow-x: auto; padding-bottom: 4px;">
<span class="pill">All · 14</span>
<span class="tag">Mentions</span>
@@ -40,7 +40,7 @@ Top: greeting + title. Body: 46 list rows, hairline-separated. Tab bar: yes.
</div>
</section>
<section class="pad" data-ocd-id="feed">
<section class="pad" data-od-id="feed">
<div class="list-row">
<div class="avatar"></div>
<div class="body">
@@ -81,21 +81,21 @@ Top: greeting + title. Body: 46 list rows, hairline-separated. Tab bar: yes.
Hero image up top, eyebrow + title + meta, body text, primary action floating at the bottom. Tab bar: no.
```html
<div class="ph-img wide" style="border-radius: 0; aspect-ratio: 4/3;" data-ocd-id="hero">[ Hero image ]</div>
<div class="ph-img wide" style="border-radius: 0; aspect-ratio: 4/3;" data-od-id="hero">[ Hero image ]</div>
<section class="pad" style="padding-top: 18px;" data-ocd-id="meta">
<section class="pad" style="padding-top: 18px;" data-od-id="meta">
<span class="pill">Studio session</span>
<h1 class="h2" style="margin: 10px 0 6px;">Filebase v3 — what we shipped, what we cut.</h1>
<p class="meta">Mira Hassan · April 22 · 9 min read</p>
</section>
<section class="pad stack" style="margin-top: 18px; gap: 14px;" data-ocd-id="body">
<section class="pad stack" style="margin-top: 18px; gap: 14px;" data-od-id="body">
<p>The biggest unlock in v3 was the new content-defined chunker. On Final Cut projects, post-edit re-uploads dropped 38× — from full multi-GB pushes to the few hundred KB that actually changed.</p>
<p>What we cut: per-folder compression. It looked great on benchmarks; on real footage it was slower than no compression at all because the chunker was already doing the dedup work.</p>
<p>Next quarter: dual-region replication on R2 + S3, rolling out to Enterprise first.</p>
</section>
<section class="pad" style="padding-top: 24px; padding-bottom: 8px;" data-ocd-id="cta">
<section class="pad" style="padding-top: 24px; padding-bottom: 8px;" data-od-id="cta">
<button class="btn-primary">Save to library</button>
</section>
```
@@ -105,7 +105,7 @@ Hero image up top, eyebrow + title + meta, body text, primary action floating at
Illustration block + headline + subhead + paginator + primary CTA. Tab bar: no. Status bar still visible.
```html
<section class="pad stack" style="height: 100%; padding-top: 24px; padding-bottom: 24px; gap: 24px;" data-ocd-id="onboarding">
<section class="pad stack" style="height: 100%; padding-top: 24px; padding-bottom: 24px; gap: 24px;" data-od-id="onboarding">
<div class="ph-img square" style="aspect-ratio: 1/1; max-width: 240px; margin: 0 auto;">[ Illustration ]</div>
<div style="text-align: center;">
@@ -136,7 +136,7 @@ Illustration block + headline + subhead + paginator + primary CTA. Tab bar: no.
Avatar + name + meta row; stat row; tabbed content underneath. Tab bar: yes (often the surrounding app's tabs).
```html
<section class="pad" style="padding-top: 8px;" data-ocd-id="head">
<section class="pad" style="padding-top: 8px;" data-od-id="head">
<div class="row" style="gap: 16px;">
<div class="avatar" style="width: 64px; height: 64px;"></div>
<div>
@@ -150,7 +150,7 @@ Avatar + name + meta row; stat row; tabbed content underneath. Tab bar: yes (oft
</div>
</section>
<section class="pad" data-ocd-id="stats" style="margin-top: 18px;">
<section class="pad" data-od-id="stats" style="margin-top: 18px;">
<div class="grid-3">
<div class="card flat" style="text-align: center;">
<div class="num" style="font-size: 22px; letter-spacing: -0.02em;">218</div>
@@ -167,7 +167,7 @@ Avatar + name + meta row; stat row; tabbed content underneath. Tab bar: yes (oft
</div>
</section>
<section class="pad" data-ocd-id="tabs" style="margin-top: 12px;">
<section class="pad" data-od-id="tabs" style="margin-top: 12px;">
<div class="row" style="border-bottom: 1px solid var(--border); gap: 24px;">
<span style="padding: 12px 0; border-bottom: 2px solid var(--accent); color: var(--fg); font-weight: 500; font-size: 14px;">Posts</span>
<span style="padding: 12px 0; color: var(--muted); font-size: 14px;">Replies</span>
@@ -175,7 +175,7 @@ Avatar + name + meta row; stat row; tabbed content underneath. Tab bar: yes (oft
</div>
</section>
<section class="pad" data-ocd-id="post-list" style="margin-top: 4px;">
<section class="pad" data-od-id="post-list" style="margin-top: 4px;">
<div class="list-row" style="grid-template-columns: 1fr;">
<div class="body">
<div class="title">"Bandwidth pricing went up 4× — sync engine choice is no longer cosmetic."</div>
@@ -196,11 +196,11 @@ Avatar + name + meta row; stat row; tabbed content underneath. Tab bar: yes (oft
Stacked card sections (item summary → details → totals), bottom-fixed CTA. Tab bar: no.
```html
<section class="pad" style="padding-top: 12px;" data-ocd-id="title">
<section class="pad" style="padding-top: 12px;" data-od-id="title">
<h1 class="h2">Confirm order</h1>
</section>
<section class="pad" data-ocd-id="item">
<section class="pad" data-od-id="item">
<div class="card row" style="gap: 14px; align-items: flex-start;">
<div class="ph-img square" style="width: 64px; height: 64px; aspect-ratio: 1; border-radius: 10px;"></div>
<div style="flex: 1;">
@@ -211,7 +211,7 @@ Stacked card sections (item summary → details → totals), bottom-fixed CTA. T
</div>
</section>
<section class="pad stack" data-ocd-id="details" style="margin-top: 14px; gap: 10px;">
<section class="pad stack" data-od-id="details" style="margin-top: 14px; gap: 10px;">
<div class="card flat row-between">
<span>Seats</span>
<span class="num">40</span>
@@ -226,14 +226,14 @@ Stacked card sections (item summary → details → totals), bottom-fixed CTA. T
</div>
</section>
<section class="pad" data-ocd-id="totals" style="margin-top: 14px;">
<section class="pad" data-od-id="totals" style="margin-top: 14px;">
<div class="card row-between" style="border-top: 1px solid var(--fg); border-radius: 0; padding: 16px 0; background: transparent;">
<span style="font-weight: 600;">Total today</span>
<span class="num" style="font-size: 22px; letter-spacing: -0.01em;">$1,920</span>
</div>
</section>
<section class="pad" style="padding-top: 16px; padding-bottom: 12px;" data-ocd-id="cta">
<section class="pad" style="padding-top: 16px; padding-bottom: 12px;" data-od-id="cta">
<button class="btn-primary">Pay $1,920</button>
<p class="meta" style="text-align: center; margin: 12px 0 0;">By tapping Pay you agree to the terms.</p>
</section>
@@ -244,7 +244,7 @@ Stacked card sections (item summary → details → totals), bottom-fixed CTA. T
A single accent-coloured hero card dominates; small supporting content underneath. Tab bar: yes.
```html
<div class="header" data-ocd-id="header">
<div class="header" data-od-id="header">
<div>
<p class="greeting">Tuesday · April 22</p>
<h1>Two pomodoros to lunch.</h1>
@@ -254,7 +254,7 @@ A single accent-coloured hero card dominates; small supporting content underneat
</button>
</div>
<section class="pad" data-ocd-id="hero-card" style="margin-top: 4px;">
<section class="pad" data-od-id="hero-card" style="margin-top: 4px;">
<div class="card accent" style="padding: 28px 24px; text-align: center;">
<p class="meta" style="margin: 0 0 6px; color: rgba(255,255,255,0.72);">FOCUS SESSION</p>
<div class="num" style="font-size: 64px; line-height: 1; letter-spacing: -0.03em; font-weight: 600; margin: 8px 0 18px;">15:42</div>
@@ -266,7 +266,7 @@ A single accent-coloured hero card dominates; small supporting content underneat
</div>
</section>
<section class="pad" data-ocd-id="stats-row" style="margin-top: 18px;">
<section class="pad" data-od-id="stats-row" style="margin-top: 18px;">
<p class="meta" style="margin: 0 0 8px;">TODAY</p>
<div class="grid-3">
<div class="card"><div class="num" style="font-size: 22px;">3</div><div class="meta">Sessions</div></div>
@@ -275,7 +275,7 @@ A single accent-coloured hero card dominates; small supporting content underneat
</div>
</section>
<section class="pad" data-ocd-id="up-next" style="margin-top: 18px;">
<section class="pad" data-od-id="up-next" style="margin-top: 18px;">
<p class="meta" style="margin: 0 0 8px;">UP NEXT</p>
<div>
<div class="list-row" style="grid-template-columns: 22px 1fr auto;">
+1 -1
View File
@@ -12,7 +12,7 @@ triggers:
- "phone signup"
- "app onboarding"
- "移动端引导"
ocd:
od:
mode: prototype
platform: mobile
scenario: design
+2 -2
View File
@@ -18,7 +18,7 @@ triggers:
- "kinetic typography"
- "动态设计"
- "动效"
ocd:
od:
mode: prototype
platform: desktop
scenario: marketing
@@ -69,7 +69,7 @@ Lottie, etc.) can capture into a video.
- `<!doctype html>` through `</html>`, CSS inline.
- All motion uses CSS — no scripts, so HyperFrames or any frame-grabber
can capture it deterministically.
- `data-ocd-id` on stage, focal, ring, headline, chrome.
- `data-od-id` on stage, focal, ring, headline, chrome.
5. **Self-check**:
- The composition still reads as a poster with motion paused at frame 0.
- At least 3 layers move at different speeds (depth comes from delta
+5 -5
View File
@@ -148,7 +148,7 @@
</style>
</head>
<body>
<main data-ocd-id="stage">
<main data-od-id="stage">
<div class="chrome top">
<div>ANTHROPIC LABS — APR 17 · 2026</div>
<div class="right"><div class="rule"></div><div>HOW IT WORKS</div></div>
@@ -164,13 +164,13 @@
</div>
<div class="stage">
<div class="composition" data-ocd-id="composition">
<div class="composition" data-od-id="composition">
<div class="ring r1"></div>
<div class="ring r2"></div>
<div class="ring r3"></div>
<div class="ring r4"></div>
<div class="globe" data-ocd-id="globe">
<div class="globe" data-od-id="globe">
<svg viewBox="0 0 200 200" aria-hidden="true">
<defs>
<radialGradient id="globeShade" cx="35%" cy="32%" r="78%">
@@ -203,11 +203,11 @@
</div>
</div>
<div class="ring-labels" data-ocd-id="ring-labels" aria-hidden="true">
<div class="ring-labels" data-od-id="ring-labels" aria-hidden="true">
<!-- positioned around the outer ring; co-rotates with .ring -->
</div>
<div class="headline" data-ocd-id="headline">
<div class="headline" data-od-id="headline">
<span class="em">Reach</span> every <span class="accent">country.</span>
</div>
<div class="baseline"></div>
+1 -1
View File
@@ -11,7 +11,7 @@ triggers:
- "feature brief"
- "feature doc"
- "需求文档"
ocd:
od:
mode: prototype
platform: desktop
scenario: product
+2 -2
View File
@@ -12,7 +12,7 @@ triggers:
- "compare plans"
- "定价"
- "套餐"
ocd:
od:
mode: prototype
platform: desktop
scenario: sales
@@ -52,7 +52,7 @@ Produce a single-screen pricing page that respects the active DESIGN.md.
4. **Write** one self-contained HTML document:
- `<!doctype html>` through `</html>`, CSS in one inline `<style>`.
- CSS Grid for the plan-card row; CSS Grid for the comparison table.
- `data-ocd-id` on each tier card and each table row.
- `data-od-id` on each tier card and each table row.
5. **Money rendering**: use the display font for the big number, body for the
currency and "/mo" — sizes per DESIGN.md scale.
6. **Self-check**:
+4 -4
View File
@@ -50,7 +50,7 @@
</head>
<body>
<div class="wrap">
<header data-ocd-id="header">
<header data-od-id="header">
<h1>One flat rate. No throttling.</h1>
<p>Start free. Pick a paid tier the day you outgrow it. Switch yearly billing for two months off.</p>
<div class="toggle">
@@ -59,7 +59,7 @@
</div>
</header>
<section class="tiers" data-ocd-id="tiers">
<section class="tiers" data-od-id="tiers">
<div class="tier">
<h2>Solo</h2>
<p class="desc">For individuals.</p>
@@ -100,7 +100,7 @@
</div>
</section>
<section class="compare" data-ocd-id="compare">
<section class="compare" data-od-id="compare">
<h3>Plan comparison</h3>
<table>
<thead><tr><th>Feature</th><th>Solo</th><th>Team</th><th>Enterprise</th></tr></thead>
@@ -116,7 +116,7 @@
</table>
</section>
<section class="faq" data-ocd-id="faq">
<section class="faq" data-od-id="faq">
<h3>Common questions</h3>
<details><summary>Can I change tiers mid-month?</summary><p>Yes. Switching upward charges a prorated difference; downgrades take effect at the next billing cycle.</p></details>
<details><summary>Is there a free tier?</summary><p>14-day free trial on every paid tier. No credit card required.</p></details>
+4 -4
View File
@@ -8,7 +8,7 @@ triggers:
- "saas landing"
- "marketing page"
- "product landing"
ocd:
od:
mode: prototype
platform: desktop
scenario: marketing
@@ -85,7 +85,7 @@ Output a single self-contained `index.html` with:
- System font fallbacks if DESIGN.md fonts aren't loadable from Google Fonts etc.
- No external JS.
- Semantic HTML (`<header>`, `<main>`, `<section>`, `<footer>`).
- Each editable element tagged with `data-ocd-id="<unique-slug>"` so the host app's comment mode can target it.
- Each editable element tagged with `data-od-id="<unique-slug>"` so the host app's comment mode can target it.
## 5. Self-check
@@ -114,9 +114,9 @@ saas-landing-skill/
```
Things to notice:
- The `ocd:` front-matter block is optional for Claude-Code-only compatibility, but adding it lights up OCD's typed inputs, sliders, preview metadata, and capability gating.
- The `od:` front-matter block is optional for Claude-Code-only compatibility, but adding it lights up OD's typed inputs, sliders, preview metadata, and capability gating.
- The workflow below the front-matter is plain Markdown that the agent reads as its system prompt.
- DESIGN.md is treated as a collaborator, not an override. The skill gives the agent authority to override when the brief conflicts, but never to invent new tokens.
- `data-ocd-id` tagging is how we wire elements to comment mode. Skills that want comment-mode compatibility must annotate their output.
- `data-od-id` tagging is how we wire elements to comment mode. Skills that want comment-mode compatibility must annotate their output.
See [`../../skills-protocol.md`](../../skills-protocol.md) for the full protocol.
+7 -7
View File
@@ -55,7 +55,7 @@
</head>
<body>
<div class="wrap">
<header data-ocd-id="topnav">
<header data-od-id="topnav">
<span class="logo">◰ Filebase</span>
<nav>
<a href="#features">Features</a>
@@ -64,7 +64,7 @@
<button class="btn-secondary" style="margin-left: 12px;">Sign in</button>
</nav>
</header>
<section class="hero" data-ocd-id="hero">
<section class="hero" data-od-id="hero">
<h1>File sync that doesn't eat your bandwidth.</h1>
<p>Block-level deltas, end-to-end encryption, and a pricing model that doesn't punish you for working with video.</p>
<div class="cta">
@@ -74,7 +74,7 @@
</section>
</div>
<section class="features" id="features" data-ocd-id="features">
<section class="features" id="features" data-od-id="features">
<div class="wrap feature-grid">
<div class="feature">
<span class="num">01</span>
@@ -94,12 +94,12 @@
</div>
</section>
<section class="proof wrap" data-ocd-id="proof">
<section class="proof wrap" data-od-id="proof">
<h2>Used by teams at</h2>
<div class="logos"><span>Anthropic</span><span>Stripe</span><span>Linear</span><span>Vercel</span><span>Cursor</span></div>
</section>
<section class="pricing wrap" id="pricing" data-ocd-id="pricing">
<section class="pricing wrap" id="pricing" data-od-id="pricing">
<h2>Pricing</h2>
<p class="lede">Pick a tier. Switch or cancel any time.</p>
<div class="tiers">
@@ -140,7 +140,7 @@
</div>
</section>
<section class="closing" data-ocd-id="closing">
<section class="closing" data-od-id="closing">
<div class="wrap">
<h2>Sync less, ship more.</h2>
<p>14-day free trial. No credit card needed.</p>
@@ -148,6 +148,6 @@
</div>
</section>
<footer class="wrap" data-ocd-id="footer">© Filebase · Privacy · Terms · Status</footer>
<footer class="wrap" data-od-id="footer">© Filebase · Privacy · Terms · Status</footer>
</body>
</html>
+1 -1
View File
@@ -13,7 +13,7 @@ triggers:
- "presentation"
- "幻灯"
- "ppt 模板"
ocd:
od:
mode: deck
scenario: product
preview:
+3 -3
View File
@@ -1,6 +1,6 @@
<!doctype html>
<!--
OCD simple-deck seed.
OD simple-deck seed.
Single-file horizontal-swipe HTML deck. Each `<section class="slide">`
is one slide; the body uses CSS scroll-snap to lock to slide boundaries.
@@ -277,7 +277,7 @@
<script>
/*
Five hard rules for deck nav inside an iframe (the OCD preview is one).
Five hard rules for deck nav inside an iframe (the OD preview is one).
The naive `document.body.scrollLeft` pattern silently fails: clicks
register, but keyboard does nothing, and the counter freezes at "1 / N"
while the user is on slide 6.
@@ -292,7 +292,7 @@
var slides = document.querySelectorAll('.slide');
var counter = document.getElementById('deck-counter');
var progress = document.getElementById('deck-progress');
var KEY = 'ocd-deck-pos';
var KEY = 'od-deck-pos';
var active = 0;
function scroller() {
+7 -7
View File
@@ -51,21 +51,21 @@
</style>
</head>
<body>
<section class="slide title" data-ocd-id="slide-1">
<section class="slide title" data-od-id="slide-1">
<div class="eyebrow" style="color:#c96442;">Filebase · Series B · Q2 2026</div>
<h1>The bandwidth bill is the bug.</h1>
<p class="body">A sync engine that ships only what changed. Backed by 3,184 paying teams.</p>
</section>
<section class="slide" data-ocd-id="slide-2">
<section class="slide" data-od-id="slide-2">
<div class="eyebrow">Problem</div>
<h2>Every other tool re-uploads the whole file.</h2>
<p class="body">Edit one frame in a 4 GB Final Cut project; today's tools sync all 4 GB. The video, post-production, and design industries are eating multi-thousand-dollar bandwidth bills they shouldn't be.</p>
</section>
<section class="slide big-stat" data-ocd-id="slide-3">
<section class="slide big-stat" data-od-id="slide-3">
<div class="number">38×</div>
<div class="caption">less data moved over the wire vs. naive sync, on real customer workloads.</div>
</section>
<section class="slide" data-ocd-id="slide-4">
<section class="slide" data-od-id="slide-4">
<div class="eyebrow">Why now</div>
<h2>Three shifts make this market real.</h2>
<div class="grid-3">
@@ -74,12 +74,12 @@
<div class="pt"><h3 class="h">Bandwidth pricing</h3><p class="p">Egress costs 4× what it did in 2022. Storage is cheap; movement is expensive.</p></div>
</div>
</section>
<section class="slide" data-ocd-id="slide-5">
<section class="slide" data-od-id="slide-5">
<div class="quote-mark">"</div>
<p class="quote-text">Filebase pays for itself in the first month. We were going to hire a dedicated DevOps person to babysit our sync — instead we just switched.</p>
<p class="quote-author">— Mira Hassan, CTO at Northwind Studios</p>
</section>
<section class="slide title" data-ocd-id="slide-6">
<section class="slide title" data-od-id="slide-6">
<div class="eyebrow" style="color:#c96442;">Ask</div>
<h1>$22M to ship the next sync engine.</h1>
<p class="body">18-month runway, hire 14, expand to enterprise on-prem.</p>
@@ -95,7 +95,7 @@
// Detect the real scroller — when body has `display: flex` + `overflow-x: auto`
// the scroller can be body OR documentElement depending on the host (in
// particular, the OCD srcdoc iframe). Pick whichever actually overflows.
// particular, the OD srcdoc iframe). Pick whichever actually overflows.
function scroller() {
if (document.body.scrollWidth > document.body.clientWidth + 1) return document.body;
return document.scrollingElement || document.documentElement;
+2 -2
View File
@@ -17,7 +17,7 @@ triggers:
- "social series"
- "三连发"
- "轮播图"
ocd:
od:
mode: prototype
platform: desktop
scenario: marketing
@@ -71,7 +71,7 @@ own.
- `<!doctype html>` through `</html>`, CSS inline.
- Cards are sized via `width: clamp(280px, 30vw, 380px)` so 3 fit
comfortably across most desktops and stack at < 1100px.
- `data-ocd-id` on stage, each card, each headline.
- `data-od-id` on stage, each card, each headline.
6. **Self-check**:
- The three headlines together form one sentence and feel cinematic.
- Mono is used only for the wordmark index, the loop stamp, and the
+5 -5
View File
@@ -158,7 +158,7 @@
</style>
</head>
<body>
<div class="stage" data-ocd-id="stage">
<div class="stage" data-od-id="stage">
<div class="stage-head">
<div>
<h1>Three posts<span class="dot">.</span> One <em>beat</em><span class="dot">.</span></h1>
@@ -167,9 +167,9 @@
<span class="badge">SERIES · 01 → 03</span>
</div>
<div class="row" data-ocd-id="cards">
<div class="row" data-od-id="cards">
<article class="card c1" data-ocd-id="card-1">
<article class="card c1" data-od-id="card-1">
<div class="figure"></div>
<div class="scrim"></div>
<div class="top">
@@ -183,7 +183,7 @@
</div>
</article>
<article class="card c2" data-ocd-id="card-2">
<article class="card c2" data-od-id="card-2">
<div class="trees"></div>
<div class="figure"></div>
<div class="scrim"></div>
@@ -198,7 +198,7 @@
</div>
</article>
<article class="card c3" data-ocd-id="card-3">
<article class="card c3" data-od-id="card-3">
<div class="ridge"></div>
<div class="figure"></div>
<div class="scrim"></div>
+2 -2
View File
@@ -20,7 +20,7 @@ triggers:
- "精灵图"
- "像素动画"
- "复古动画"
ocd:
od:
mode: prototype
platform: desktop
scenario: marketing
@@ -73,7 +73,7 @@ display, looping CSS animations, kinetic Japanese / English display type.
- All animations use `@keyframes` + `animation: ... infinite`.
- Stage uses a fixed canvas ratio (e.g. 16:9 letterboxed) so the loop
reads as a single frame from a video.
- `data-ocd-id` on stage, year, sprite, caption, and tick ribbon.
- `data-od-id` on stage, year, sprite, caption, and tick ribbon.
8. **Self-check**:
- The page is one cohesive scene, not a collage. The eye lands on the
year first, then the sprite, then the caption.
+8 -8
View File
@@ -178,14 +178,14 @@
</style>
</head>
<body>
<div class="stage" data-ocd-id="stage">
<div class="stage" data-od-id="stage">
<span class="reg tl"></span>
<span class="reg tr"></span>
<span class="reg bl"></span>
<span class="reg br"></span>
<div class="topbar" data-ocd-id="topbar">
<div class="topbar" data-od-id="topbar">
<div class="slug">
<span class="jp">名次の番組</span>
<span class="en">EP. 01 · NINTENDO TRIVIA</span>
@@ -197,17 +197,17 @@
</div>
</div>
<div class="kana" data-ocd-id="kana"><span></span><span></span></div>
<div class="kana" data-od-id="kana"><span></span><span></span></div>
<div class="year-label" data-ocd-id="year-label">CHAPTER 01 · KYOTO · A PLAYING-CARD COMPANY</div>
<div class="year" data-ocd-id="year">
<div class="year-label" data-od-id="year-label">CHAPTER 01 · KYOTO · A PLAYING-CARD COMPANY</div>
<div class="year" data-od-id="year">
<span class="num">
1889
<span class="glitch" aria-hidden="true">1889</span>
</span><span class="jp-suffix"></span>
</div>
<div class="sprite-stack" data-ocd-id="sprite">
<div class="sprite-stack" data-od-id="sprite">
<div class="sprite-card">
<!-- Hanafuda card sprite — pixel-art flower -->
<svg width="120" height="160" viewBox="0 0 24 32" xmlns="http://www.w3.org/2000/svg" aria-label="Hanafuda card">
@@ -240,13 +240,13 @@
</div>
</div>
<div class="caption" data-ocd-id="caption">
<div class="caption" data-od-id="caption">
<strong>Nintendo started as a hanafuda maker.</strong>
Founded in Kyoto by Fusajiro Yamauchi to print hand-painted playing
cards. Mario wouldn&rsquo;t show up for another <em>ninety-six</em> years.
</div>
<div class="ribbon" data-ocd-id="ribbon">
<div class="ribbon" data-od-id="ribbon">
<div class="ribbon-track">
<div class="tick"><span class="dot"></span><span class="label">1889</span><span class="note">HANAFUDA · KYOTO</span></div>
<div class="tick"><span class="dot"></span><span class="label">1907</span><span class="note">WESTERN CARDS</span></div>
+1 -1
View File
@@ -11,7 +11,7 @@ triggers:
- "key results"
- "objectives"
- "目标"
ocd:
od:
mode: prototype
platform: desktop
scenario: product
+1 -1
View File
@@ -18,7 +18,7 @@ triggers:
- "可调参数面板"
- "side panel"
- "knobs"
ocd:
od:
mode: prototype
platform: desktop
scenario: design
+1 -1
View File
@@ -579,7 +579,7 @@ $ filebase sync --watch
<footer class="ft">
<span>© 2026 Filebase, Inc.</span>
<span>Privacy · Terms · Status</span>
<span>built with the OCD tweaks skill</span>
<span>built with the OD tweaks skill</span>
</footer>
</div>
+2 -2
View File
@@ -12,7 +12,7 @@ triggers:
- "single page"
- "marketing page"
- "homepage"
ocd:
od:
mode: prototype
platform: desktop
scenario: design
@@ -83,7 +83,7 @@ Wrap `index.html` in `<artifact>` tags. One sentence before describing what's th
- **Display font is serif** (Iowan Old Style / Charter / Georgia in the seed). Sans for body. Mono for numerics, captions, eyebrows.
- **Image placeholders, not external URLs.** Use the `.ph-img` class — never link to a stock photo CDN.
- **Mobile reflow already works** via the seed's media query at 920px. Don't break it by adding fixed widths.
- **`data-ocd-id` on every `<section>`** so comment mode can target it.
- **`data-od-id` on every `<section>`** so comment mode can target it.
## Output contract
+4 -4
View File
@@ -1,6 +1,6 @@
<!doctype html>
<!--
OCD web-prototype seed.
OD web-prototype seed.
Copy this file to <project>/index.html, then fill `<main id="content">` by
pasting blocks from `references/layouts.md`. Every class referenced in
@@ -293,7 +293,7 @@
</style>
</head>
<body>
<header class="topnav" data-ocd-id="topnav">
<header class="topnav" data-od-id="topnav">
<div class="container topnav-inner">
<span class="logo">[REPLACE] Brand</span>
<nav>
@@ -315,7 +315,7 @@
│ ► End with a CTA strip + footer (Layout 6 / footer below). │
└─────────────────────────────────────────────────────────────────┘
-->
<section class="section hero" data-ocd-id="hero">
<section class="section hero" data-od-id="hero">
<div class="container hero-center">
<p class="eyebrow">[REPLACE] Eyebrow</p>
<h1>[REPLACE] One sharp sentence about what this is.</h1>
@@ -328,7 +328,7 @@
</section>
</main>
<footer class="pagefoot" data-ocd-id="footer">
<footer class="pagefoot" data-od-id="footer">
<div class="container row-between">
<span>© [REPLACE] Brand · [REPLACE] Year</span>
<span class="meta">[REPLACE] tagline · contact@example.com</span>
+6 -6
View File
@@ -36,7 +36,7 @@
</style>
</head>
<body>
<header data-ocd-id="topnav">
<header data-od-id="topnav">
<span class="logo">🍅 Tomato</span>
<nav>
<a href="#features">Features</a>
@@ -45,7 +45,7 @@
</nav>
</header>
<main>
<section class="hero" data-ocd-id="hero">
<section class="hero" data-od-id="hero">
<h1>Twenty-five minutes at a time.</h1>
<p>The pomodoro timer that actually keeps your hands off Slack. Block notifications, log every cycle, ship more before lunch.</p>
<div class="cta">
@@ -54,23 +54,23 @@
</div>
</section>
<section class="features" id="features">
<div class="feature" data-ocd-id="feature-block">
<div class="feature" data-od-id="feature-block">
<div class="icon"></div>
<h3>Block on, not off</h3>
<p>Slack and email go quiet for 25 minutes. They come back loud at the break, with a digest.</p>
</div>
<div class="feature" data-ocd-id="feature-stats">
<div class="feature" data-od-id="feature-stats">
<div class="icon"></div>
<h3>Stats that don't lie</h3>
<p>Weekly review tells you which days you actually shipped versus which you only seemed busy.</p>
</div>
<div class="feature" data-ocd-id="feature-team">
<div class="feature" data-od-id="feature-team">
<div class="icon"></div>
<h3>Team-friendly silences</h3>
<p>Your status auto-updates so teammates know when to ask, when to wait, and when you're done.</p>
</div>
</section>
<section class="closing" data-ocd-id="closing">
<section class="closing" data-od-id="closing">
<h2>Stop measuring meetings. Start measuring focus.</h2>
<p>Free for solo. $4/mo per teammate after that.</p>
<button class="btn-primary">Try Tomato free</button>
+2 -2
View File
@@ -11,9 +11,9 @@ Run this before emitting `<artifact>`. P0 = must pass; P1 = should pass; P2 = ni
- [ ] **No emoji used as feature icons.** Use the inline SVG monoline marks shipped in Layout 3, or a tasteful single-character glyph in `--font-mono`. ✨ 🚀 🎯 are out.
- [ ] **No invented metrics.** Every number on the page came from the user, the brief, or is clearly labelled as a placeholder (e.g. `[REPLACE] · 38×`). "10× faster", "99.9% uptime" without source = remove.
- [ ] **No filler copy.** Zero "Feature One / Feature Two", lorem ipsum, "Lorem ipsum dolor". If a section feels empty, delete it; do not pad.
- [ ] **`data-ocd-id` on every top-level `<section>`.** Used by comment mode to target sections.
- [ ] **`data-od-id` on every top-level `<section>`.** Used by comment mode to target sections.
- [ ] **Mobile reflow works.** All `grid-2`, `grid-3`, `grid-4`, `grid-2-1`, `grid-1-2` collapse to one column at ≤920px (the default media query in `template.html` does this). Verify by mentally narrowing — no horizontal scroll.
- [ ] **No `scrollIntoView()` calls.** Breaks the OCD preview iframe. Use `scrollTo({...})` if you need scroll behaviour.
- [ ] **No `scrollIntoView()` calls.** Breaks the OD preview iframe. Use `scrollTo({...})` if you need scroll behaviour.
## P1 — should pass

Some files were not shown because too many files have changed in this diff Show More