Refactor project name from "Open Claude Design" to "Open Design" (#1)

* 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.

* Add contributing guidelines in English and Chinese

- Introduced CONTRIBUTING.md and CONTRIBUTING.zh-CN.md to provide clear instructions for contributors.
- Outlined contribution types, local setup instructions, and merging criteria for skills and design systems.
- Enhanced README files to reference the new contributing guidelines.
This commit is contained in:
Tom Huang 2026-04-28 16:03:35 +08:00 committed by GitHub
parent a98096a042
commit 6f6bf31dd2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
131 changed files with 2560 additions and 650 deletions

9
.gitignore vendored
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/*

266
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,266 @@
# Contributing to Open Design
Thanks for thinking about contributing. OD is small on purpose — most of the value lives in **files** (skills, design systems, prompt fragments) rather than framework code. That means the highest-leverage contributions are usually one folder, one Markdown file, or one PR-sized adapter.
This guide tells you exactly where to look for each type of contribution and what bar a PR has to clear before we merge it.
<p align="center"><b>English</b> · <a href="CONTRIBUTING.zh-CN.md">简体中文</a></p>
---
## Three things you can ship in one afternoon
| If you want to… | You're really adding | Where it lives | Ship size |
|---|---|---|---|
| Make OD render a new kind of artifact (an invoice, an iOS Settings screen, a one-pager…) | a **Skill** | [`skills/<your-skill>/`](skills/) | one folder, ~2 files |
| Make OD speak a new brand's visual language | a **Design System** | [`design-systems/<brand>/DESIGN.md`](design-systems/) | one Markdown file |
| Hook up a new coding-agent CLI | an **Agent adapter** | [`daemon/agents.js`](daemon/agents.js) | ~10 lines in one array |
| Add a feature, fix a bug, lift a UX pattern from [`open-codesign`][ocod] | code | `src/`, `daemon/` | normal PR |
| Improve docs, port a section to 中文, fix typos | docs | `README.md`, `README.zh-CN.md`, `docs/`, `QUICKSTART.md` | one PR |
If you're not sure which bucket your idea is in, [open a discussion / issue first](https://github.com/nexu-io/open-design/issues/new) and we'll point you at the right surface.
---
## Local setup
The full one-page setup lives in [`QUICKSTART.md`](QUICKSTART.md). The TL;DR for contributors:
```bash
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)
pnpm typecheck # tsc -b --noEmit
pnpm build # production build
```
Node 18+ is required. macOS, Linux, and WSL2 are tested daily. Windows native should work but isn't a primary target — file an issue if it doesn't.
You don't need any agent CLI on your `PATH` to develop OD itself — the daemon will tell you "no agents found" and fall back to the **Anthropic API · BYOK** path, which is the fastest dev loop anyway.
---
## Adding a new Skill
A skill is a folder under [`skills/`](skills/) with a `SKILL.md` at the root, following Claude Code's [`SKILL.md` convention][skill] plus our optional `od:` extension. **No registration step.** Drop the folder in, restart the daemon, the picker shows it.
### Skill folder layout
```text
skills/your-skill/
├── SKILL.md # required
├── assets/template.html # optional but recommended — the seed file
├── references/ # optional — knowledge files the agent reads
│ ├── layouts.md
│ ├── components.md
│ └── checklist.md
└── example.html # strongly recommended — a real, hand-built sample
```
### `SKILL.md` frontmatter
The first three keys are the Claude Code base spec — `name`, `description`, `triggers`. Everything under `od:` is OD-specific and optional, but **`od.mode`** decides which group the skill shows up in (Prototype / Deck / Template / Design system).
```yaml
---
name: your-skill
description: |
One-paragraph elevator pitch. The agent reads this verbatim to decide
if the user's brief matches. Be concrete: surface, audience, what's in
the artifact, what's not.
triggers:
- "your trigger phrase"
- "another phrase"
- "中文触发词"
od:
mode: prototype # prototype | deck | template | design-system
platform: desktop # desktop | mobile
scenario: marketing # free-form tag for grouping
featured: 1 # any positive integer surfaces it under "Showcase examples"
preview:
type: html # html | jsx | pptx | markdown
entry: index.html
design_system:
requires: true # does the skill read the active DESIGN.md?
sections: [color, typography, layout, components]
example_prompt: "A copy-pastable prompt that nicely shows what this skill does."
---
# Your Skill
Body is free-form Markdown describing the workflow the agent should follow…
```
The full grammar — typed inputs, slider parameters, capability gating — lives in [`docs/skills-protocol.md`](docs/skills-protocol.md).
### Bar for merging a new skill
We're picky about skills because they're the user-facing surface. A new skill must:
1. **Ship a real `example.html`.** Hand-built, opens straight from disk, looks like something a designer would actually deliver. No lorem ipsum, no `<svg><rect/></svg>` placeholder hero. If you can't build the example yourself, the skill probably isn't ready.
2. **Pass the anti-AI-slop checklist** in the body. No purple gradients, no generic emoji icons, no rounded card with a left-border accent, no Inter as a *display* face, no invented stats. Read the **Anti-AI-slop machinery** section of the README for the full list.
3. **Honest placeholders.** When the agent doesn't have a real number, write `—` or a labelled grey block, not "10× faster".
4. **Have a `references/checklist.md`** with at least P0 gates (the stuff the agent has to pass before emitting `<artifact>`). Lift the format from [`skills/guizang-ppt/references/checklist.md`](skills/guizang-ppt/) or [`skills/dating-web/references/checklist.md`](skills/dating-web/).
5. **Add a screenshot** at `docs/screenshots/skills/<skill>.png` if the skill is featured. PNG, ~1024×640 retina, captured from the real `example.html` at zoomed-out browser scale.
6. **Be a single self-contained folder.** No CDN imports beyond what other skills already use; no fonts you didn't license; no images larger than ~250 KB.
If you fork an existing skill (e.g. start from `dating-web` and remix into a `recruiting-web`), keep the original LICENSE and authorship in `references/` and call it out in your PR description.
### Skills that already ship — pick one to imitate
- Visual showcase, single-screen prototype: [`skills/dating-web/`](skills/dating-web/), [`skills/digital-eguide/`](skills/digital-eguide/)
- Multi-frame mobile flow: [`skills/mobile-onboarding/`](skills/mobile-onboarding/), [`skills/gamified-app/`](skills/gamified-app/)
- Document / template (no design system required): [`skills/pm-spec/`](skills/pm-spec/), [`skills/weekly-update/`](skills/weekly-update/)
- Deck mode: [`skills/guizang-ppt/`](skills/guizang-ppt/) (bundled verbatim from [op7418/guizang-ppt-skill][guizang]) and [`skills/simple-deck/`](skills/simple-deck/)
---
## Adding a new Design System
A design system is a single [`DESIGN.md`](design-systems/README.md) file under `design-systems/<slug>/`. **One file, no code.** Drop it in, restart the daemon, the picker shows it grouped by category.
### Design system folder layout
```text
design-systems/your-brand/
└── DESIGN.md
```
### `DESIGN.md` shape
```markdown
# Design System Inspired by YourBrand
> Category: Developer Tools
> One-line summary that shows in the picker preview.
## 1. Visual Theme & Atmosphere
## 2. Color
- Primary: `#hex` / `oklch(...)`
- …
## 3. Typography
## 4. Spacing & Grid
## 5. Layout & Composition
## 6. Components
## 7. Motion & Interaction
## 8. Voice & Brand
## 9. Anti-patterns
```
The 9-section schema is fixed — that's what skill bodies grep for. The first H1 becomes the picker label (the `Design System Inspired by` prefix is stripped automatically), and the `> Category: …` line decides which group it lands in. Existing categories are listed in [`design-systems/README.md`](design-systems/README.md); if your brand truly doesn't fit, you can introduce a new one, but **try existing categories first**.
### Bar for merging a new design system
1. **All 9 sections present.** Empty section bodies are fine for hard-to-find data (e.g. motion tokens), but the headings have to be there or the prompt grep breaks.
2. **Hex codes are real.** Sample directly from the brand's site or product, not from memory or AI guesses. The README's "brand-spec extraction" 5-step protocol applies to maintainers too.
3. **OKLch values for accent colors** are nice-to-have. They make palettes lerp predictably across light/dark.
4. **No marketing fluff.** The brand's tagline is not a design token. Cut it.
5. **Slug uses ASCII**`linear.app` becomes `linear-app`, `x.ai` becomes `x-ai`. The 69 imported systems already follow this convention; mirror it.
The 69 product systems we ship are imported from [`VoltAgent/awesome-design-md`][acd2] via [`scripts/sync-design-systems.mjs`](scripts/sync-design-systems.mjs). If your brand belongs upstream, **send the PR there first** — we'll pick it up automatically on the next sync. The `design-systems/` folder is for systems that don't fit upstream, plus our two hand-authored starters.
---
## Adding a new coding-agent CLI
Hooking up a new agent (e.g. some new shop's `foo-coder` CLI) is one entry in [`daemon/agents.js`](daemon/agents.js):
```javascript
{
id: 'foo',
name: 'Foo Coder',
bin: 'foo',
versionArgs: ['--version'],
buildArgs: (prompt) => ['exec', '-p', prompt],
streamFormat: 'plain', // or 'claude-stream-json' if it speaks that
}
```
That's it — daemon will detect it on `PATH`, the picker shows it, the chat path works. If the CLI emits **typed events** (like Claude Code's `--output-format stream-json`), wire a parser in [`daemon/claude-stream.js`](daemon/claude-stream.js) and set `streamFormat: 'claude-stream-json'`.
Bar for merging:
1. **A real session works end-to-end** with the new agent — paste the daemon log into the PR description showing it streamed an artifact through.
2. **`docs/agent-adapters.md`** is updated with the CLI's quirks (does it require a key file? does it support image input? what's its non-interactive flag?).
3. **The README's "Supported coding agents" table** gets one row.
---
## Code style
We're not pedantic about formatting (Prettier on save is fine), but two rules are non-negotiable because they show up in the prompt stack and the user-facing API:
1. **Single quotes in JS/TS.** Strings are single-quoted unless escaping makes them ugly. The codebase is already consistent — please match.
2. **Comments in English.** Even if the PR is translating something into 中文, code comments stay in English so we can keep one set of greppable references.
Beyond that:
- **Don't narrate.** No `// import the module`, no `// loop through items`. If the code reads obviously, the comment is noise. Save comments for non-obvious intent or constraints the code can't express.
- **TypeScript** for `src/`. The daemon (`daemon/`) is plain ESM JavaScript with JSDoc when types matter — keep it that way.
- **No new top-level dependencies** without a paragraph in the PR description on what we get vs. what bytes we ship. The dep list in [`package.json`](package.json) is small on purpose.
- **Run `pnpm typecheck`** before pushing. CI runs it; failing it earns a "please fix" comment.
---
## Commits & pull requests
- **One concern per PR.** Adding a skill + refactoring the parser + bumping a dep is three PRs.
- **Title is imperative + scope.** `add dating-web skill`, `fix daemon SSE backpressure when CLI hangs`, `docs: clarify .od layout`.
- **Body explains the why.** "What does this do" is usually obvious from the diff; "why does this need to exist" rarely is.
- **Reference an issue** if there is one. If there isn't and the PR is non-trivial, open one first so we can agree the change is wanted before you spend the time.
- **No squash-during-review.** Push fixups; we'll squash on merge.
- **No force-push to a shared branch** unless the reviewer asked.
We don't enforce a CLA. Apache-2.0 covers us; your contribution is licensed under the same.
---
## Reporting bugs
Open an issue with:
- What you ran (the exact `pnpm dev:all` / `npm start` invocation).
- Which agent CLI was selected (or whether you were on the BYOK path).
- The skill + design system pair that triggered it.
- The relevant **daemon stderr tail** — most "the artifact never rendered" reports get diagnosed in 30 seconds when we can see `spawn ENOENT` or the CLI's actual error.
- A screenshot if it's UI.
For prompt-stack bugs ("the agent emitted a purple gradient hero, the slop blacklist was supposed to forbid that"), include the **full assistant message** so we can see whether the violation was the model or the prompt.
---
## Asking questions
- Architecture question, design question, "is this a bug or a misuse" → [GitHub Discussions](https://github.com/nexu-io/open-design/discussions) (preferred — searchable for the next person).
- "How do I write a skill that does X" → Open a discussion. We'll answer it and turn the answer into [`docs/skills-protocol.md`](docs/skills-protocol.md) if it's a missing pattern.
---
## What we don't accept
To keep the project focused, please don't open PRs that:
- **Vendor a model runtime.** OD's whole bet is "your existing CLI is enough". We don't ship `pi-ai`, OpenAI keys, or model loaders.
- **Add a new framework to the frontend.** Vite + React 18 + TS is the line. No Next.js, Astro, Solid, Svelte rewrites.
- **Replace the daemon with a serverless function.** The daemon's whole point is owning a real `cwd` and spawning a real CLI. Vercel deployment of the SPA is fine; the daemon stays a daemon.
- **Add telemetry / analytics / phone-home.** OD is local-first. The only outbound calls are to providers the user explicitly configured.
- **Bundle a binary** without a license file and authorship attribution next to it.
If you're not sure whether your idea fits, open a discussion before writing the code.
---
## License
By contributing, you agree your contribution is licensed under the [Apache-2.0 License](LICENSE) of this repository, with the exception of files inside [`skills/guizang-ppt/`](skills/guizang-ppt/), which retain their original MIT license and authorship attribution to [op7418](https://github.com/op7418).
[skill]: https://docs.anthropic.com/en/docs/claude-code/skills
[guizang]: https://github.com/op7418/guizang-ppt-skill
[acd2]: https://github.com/VoltAgent/awesome-design-md
[ocod]: https://github.com/OpenCoworkAI/open-codesign

265
CONTRIBUTING.zh-CN.md Normal file
View file

@ -0,0 +1,265 @@
# 贡献指南 · Contributing to Open Design
谢谢你愿意参与。OD 是有意做小的 —— 大部分价值在 **文件**skill、design system、提示词片段而不是框架代码。这意味着收益最高的贡献往往就是一个文件夹、一份 Markdown或者一个 PR 大小的 adapter。
这份指南会告诉你:每种贡献该往哪里看、合并之前 PR 需要过哪些线。
<p align="center"><a href="CONTRIBUTING.md">English</a> · <b>简体中文</b></p>
---
## 一个下午就能交付的三件事
| 你想要…… | 你其实在加的是 | 它住在哪 | 体量 |
|---|---|---|---|
| 让 OD 渲染一种新的 artifact一份发票、一个 iOS 设置页、一张 one-pager…… | 一个 **Skill** | [`skills/<your-skill>/`](skills/) | 一个文件夹,约 2 个文件 |
| 让 OD 说一种新品牌的视觉语言 | 一套 **Design System** | [`design-systems/<brand>/DESIGN.md`](design-systems/) | 一个 Markdown 文件 |
| 接入一个新的 coding-agent CLI | 一个 **Agent adapter** | [`daemon/agents.js`](daemon/agents.js) | 一个数组里 ~10 行 |
| 加功能、修 bug、从 [`open-codesign`][ocod] 移植一个 UX 模式 | 代码 | `src/`、`daemon/` | 普通 PR |
| 改文档、补中文翻译、修错别字 | 文档 | `README.md`、`README.zh-CN.md`、`docs/`、`QUICKSTART.md` | 一个 PR |
不确定自己想做的属于哪一桶?[先开 issue / discussion](https://github.com/nexu-io/open-design/issues/new),我们告诉你该改哪个面。
---
## 本地起跑
完整的一页式 setup 在 [`QUICKSTART.md`](QUICKSTART.md)。给贡献者的 TL;DR
```bash
git clone https://github.com/nexu-io/open-design.git
cd open-design
pnpm install # 或 npm install
pnpm dev:all # daemon (:7456) + Vite (:5173)
pnpm typecheck # tsc -b --noEmit
pnpm build # 生产构建
```
要求 Node 18+。macOS、Linux、WSL2 每天都在跑。Windows 原生应该能跑但不是主要目标 —— 跑不起来请开 issue。
**开发 OD 本身不需要在 `PATH` 上装任何 agent CLI** —— daemon 会告诉你「找不到 agent」并落到 **Anthropic API · BYOK** 路径,反而是最快的开发循环。
---
## 加一个 Skill
一个 skill 就是 [`skills/`](skills/) 下的一个文件夹,根目录放一个 `SKILL.md`,遵循 Claude Code 的 [`SKILL.md` 规范][skill],再加上我们可选的 `od:` 扩展。**没有注册步骤。** 文件夹丢进来、重启 daemon、picker 里就出现了。
### Skill 文件夹结构
```text
skills/your-skill/
├── SKILL.md # 必须
├── assets/template.html # 可选但强烈推荐 —— seed 模板
├── references/ # 可选 —— agent 在规划阶段会读的知识文件
│ ├── layouts.md
│ ├── components.md
│ └── checklist.md
└── example.html # 强烈推荐 —— 一份手搓的真实样例
```
### `SKILL.md` 的 frontmatter
前三个字段是 Claude Code 的基础规范 —— `name`、`description`、`triggers`。`od:` 下面所有字段都是 OD 特有的、可选的,但 **`od.mode`** 决定 skill 出现在哪一组Prototype / Deck / Template / Design system
```yaml
---
name: your-skill
description: |
一段电梯演讲。Agent 会原样读这段来判断用户的需求是否匹配。
写具体一点surface、受众、artifact 里有什么、没有什么。
triggers:
- "your trigger phrase"
- "another phrase"
- "中文触发词"
od:
mode: prototype # prototype | deck | template | design-system
platform: desktop # desktop | mobile
scenario: marketing # 自由 tag用来分组
featured: 1 # 任何正整数都会让它出现在「Showcase examples」
preview:
type: html # html | jsx | pptx | markdown
entry: index.html
design_system:
requires: true # 这个 skill 是否会读激活的 DESIGN.md
sections: [color, typography, layout, components]
example_prompt: "一段可复制粘贴的提示词,最能体现这个 skill 的能力。"
---
# Your Skill
正文是自由 Markdown描述 agent 应该走的工作流……
```
完整 grammar —— 类型化输入、滑块参数、能力 gating —— 在 [`docs/skills-protocol.md`](docs/skills-protocol.md)。
### 合并新 skill 的硬线
Skill 是用户直接看到的面,所以我们对它挑剔。一个新 skill 必须:
1. **附一份真实的 `example.html`。** 手搓的、本地直接打开就能看、像设计师真的会交付的东西。不要 lorem ipsum不要 `<svg><rect/></svg>` 占位 hero。如果你自己都不能搓出 example这个 skill 大概率还没准备好。
2. **过 anti-AI-slop checklist**(写在 body 里)。不准紫色渐变、不准通用 emoji 图标、不准左 border 圆角卡片、不准把 Inter 当 *display* 字体、不准自编数据。完整黑名单看 README 的「Anti-AI-slop machinery」一节。
3. **诚实占位。** Agent 没真数字时写 `—` 或一个标注的灰块,绝不写「快 10 倍」。
4. **附 `references/checklist.md`**,至少要有 P0 关卡agent emit `<artifact>` 之前必须过的硬线)。格式照搬 [`skills/guizang-ppt/references/checklist.md`](skills/guizang-ppt/) 或 [`skills/dating-web/references/checklist.md`](skills/dating-web/)。
5. **如果是 featured skill加一张截图**`docs/screenshots/skills/<skill>.png`。PNG 格式,约 1024×640 retina从真实 `example.html` 上以缩小后的浏览器倍率截。
6. **是一个自包含文件夹。** CDN 引入不能超过其他 skill 已经引入的;不准用没授权的字体;图片不要超过约 250 KB。
如果你 fork 了一个现有 skill比如从 `dating-web` 改成 `recruiting-web`),保留原 LICENSE 和原作者归属在 `references/` 里,并在 PR 描述里点出来。
### 已有的 skill —— 挑一个像的来抄
- 视觉 showcase、单屏原型[`skills/dating-web/`](skills/dating-web/)、[`skills/digital-eguide/`](skills/digital-eguide/)
- 多屏移动流程:[`skills/mobile-onboarding/`](skills/mobile-onboarding/)、[`skills/gamified-app/`](skills/gamified-app/)
- 文档 / 模板(不需要 design system[`skills/pm-spec/`](skills/pm-spec/)、[`skills/weekly-update/`](skills/weekly-update/)
- Deck 模式:[`skills/guizang-ppt/`](skills/guizang-ppt/)(来自 [op7418/guizang-ppt-skill][guizang],原样捆绑)和 [`skills/simple-deck/`](skills/simple-deck/)
---
## 加一套 Design System
一套 design system 就是 `design-systems/<slug>/` 下的一个 [`DESIGN.md`](design-systems/README.md) 文件。**一个文件,零代码。** 丢进来、重启 daemon、picker 按 category 分组显示出来。
### Design system 文件夹结构
```text
design-systems/your-brand/
└── DESIGN.md
```
### `DESIGN.md` 形态
```markdown
# Design System Inspired by YourBrand
> Category: Developer Tools
> 一行总结,会显示在 picker 的预览里。
## 1. Visual Theme & Atmosphere
## 2. Color
- Primary: `#hex` / `oklch(...)`
- …
## 3. Typography
## 4. Spacing & Grid
## 5. Layout & Composition
## 6. Components
## 7. Motion & Interaction
## 8. Voice & Brand
## 9. Anti-patterns
```
9 段式 schema 是固定的 —— skill body 会按这个结构 grep 内容。第一行 H1 会成为 picker 的标签(`Design System Inspired by` 前缀会被自动剥掉),`> Category: …` 那一行决定它落到哪个组。已有的 category 列表在 [`design-systems/README.md`](design-systems/README.md);如果你的品牌真的塞不进任何一个,可以新增 category但**优先尝试现有 category**。
### 合并新 design system 的硬线
1. **9 个 section 都要在。** Section 内容空着可以(比如真的找不到 motion token但标题必须保留否则提示词的 grep 会断。
2. **Hex 是真的。** 直接从品牌官网或产品里取色,不准从记忆里掏,不准让 AI 猜。README 里那套 5 步「品牌资产协议」对维护者一样适用。
3. **强调色给 OKLch 是加分项。** 让色板在亮 / 暗模式之间能可预测地 lerp。
4. **不要营销废话。** 品牌的 tagline 不是设计 token。删掉。
5. **slug 用 ASCII** —— `linear.app` 写成 `linear-app``x.ai` 写成 `x-ai`。已经导入的 69 套都遵循这个约定,跟着写。
我们内置的 69 套产品系统是通过 [`scripts/sync-design-systems.mjs`](scripts/sync-design-systems.mjs) 从 [`VoltAgent/awesome-design-md`][acd2] 导入的。如果你的品牌应该归属在上游,**请先把 PR 发到那里** —— 我们下一次同步会自动收上来。`design-systems/` 文件夹用来放那些**不适合归到上游**的系统、加上我们手写的两套 starter。
---
## 接入一个新的 coding-agent CLI
接入一个新 agent比如某个新 shop 的 `foo-coder` CLI就是在 [`daemon/agents.js`](daemon/agents.js) 里加一项:
```javascript
{
id: 'foo',
name: 'Foo Coder',
bin: 'foo',
versionArgs: ['--version'],
buildArgs: (prompt) => ['exec', '-p', prompt],
streamFormat: 'plain', // 如果它说 claude-stream-json 就写那个
}
```
完事 —— daemon 会在 `PATH` 上检测到它、picker 显示出来、对话路径就通了。如果这个 CLI 吐 **类型化事件**(像 Claude Code 的 `--output-format stream-json`),在 [`daemon/claude-stream.js`](daemon/claude-stream.js) 里写一个 parser并把 `streamFormat` 设成 `'claude-stream-json'`
合并硬线:
1. **真的跑通一次端到端会话** —— 把 daemon 日志贴在 PR 描述里,证明它流出了一个 artifact。
2. **更新 [`docs/agent-adapters.md`](docs/agent-adapters.md)**,写清楚这个 CLI 的怪癖(要不要 key 文件?支不支持图片输入?非交互模式的 flag 是什么?)。
3. **README 的「Supported coding agents」表里加一行**
---
## 代码风格
格式我们不抠(保存时跑 Prettier 就行),但有两条不能让 —— 因为它们出现在提示词栈和用户可见的 API 里:
1. **JS/TS 用单引号。** 字符串一律单引号,除非转义太丑。代码库已经是一致的,请保持一致。
2. **代码注释用英文。** 即使 PR 是把某段翻译成中文,代码注释也保留英文,这样我们能维护一份可 grep 的引用集。
除此之外:
- **不要写废话注释。** 不要 `// 引入这个模块`、不要 `// 遍历元素`。如果代码本身一眼能读,注释就是噪音。注释只用来说明非显而易见的意图、或者代码本身表达不出来的约束。
- **`src/` 用 TypeScript。** Daemon (`daemon/`) 是纯 ESM JavaScript类型重要的地方用 JSDoc —— 保持这样。
- **不要随便加顶层依赖。** PR 描述里至少要有一段,说明引入它能换到什么、又新增了多少 bundle 字节。[`package.json`](package.json) 的依赖少是有意为之。
- **推之前跑 `pnpm typecheck`。** CI 会跑;挂了会换来一句「请修一下」。
---
## Commit 与 PR
- **一个 PR 只做一件事。** 加 skill + 重构 parser + 升依赖,是三个 PR。
- **标题用动词起头 + 范围。** `add dating-web skill`、`fix daemon SSE backpressure when CLI hangs`、`docs: clarify .od layout`。
- **正文解释 why。** 「这个 PR 改了什么」从 diff 一般能看出来;「为什么要改」很少能。
- **如果有 issue引用它。** 没有、且改动非平凡,请先开 issue 让我们先就「值不值得做」达成一致,再投入时间。
- **Review 期间不要 squash。** 推 fixup commitmerge 时我们会 squash。
- **不要 force-push 共享分支**,除非 reviewer 主动让你这么做。
我们不强制 CLA。Apache-2.0 已经覆盖;你的贡献按同样的 license 授权。
---
## 报 bug
开 issue 时请带上:
- 你跑的命令(精确到 `pnpm dev:all` / `npm start`)。
- 选中的 agent CLI 是哪个(或者你走的是 BYOK 路径)。
- 触发问题时的 skill + design system 组合。
- 相关的 **daemon stderr 末尾几行** —— 大多数「artifact 没渲染出来」的报告,看到 `spawn ENOENT` 或 CLI 实际报错后 30 秒就能定位。
- UI 问题贴一张截图。
提示词栈相关的 bug「agent 吐了一个紫色渐变 heroslop 黑名单不是禁了吗」),请贴 **完整的助手消息**,方便我们判断违规来自模型还是提示词。
---
## 提问
- 架构问题、设计问题、「这是 bug 还是误用」 → 请用 [GitHub Discussions](https://github.com/nexu-io/open-design/discussions)(首选 —— 下一个人能搜到)。
- 「我想写一个干 X 的 skill 怎么写」 → 开一个 discussion。我们会回答且如果是缺失的模式答案会被收进 [`docs/skills-protocol.md`](docs/skills-protocol.md)。
---
## 我们不接收的 PR
为了保持项目聚焦,请不要发以下类型的 PR
- **Vendor 一个模型运行时。** OD 整个赌注就是「你已有的 CLI 就够了」。我们不带 `pi-ai`、不带 OpenAI key、不带模型加载器。
- **给前端加一个新框架。** Vite + React 18 + TS 是底线。不要 Next.js / Astro / Solid / Svelte 改写。
- **把 daemon 换成 serverless function。** Daemon 的存在意义就是拥有真实的 `cwd` 和 spawn 真实的 CLI。SPA 部署 Vercel 没问题daemon 仍然是 daemon。
- **加 telemetry / 分析 / phone-home。** OD 是 local-first。唯一的对外请求是用户明确配置的 provider。
- **打包二进制** 而没有附 license 文件和原作者归属。
不确定自己的想法合不合适?开个 discussion 再写代码。
---
## License
提交贡献即代表你同意你的贡献按本仓库的 [Apache-2.0 License](LICENSE) 授权。例外是 [`skills/guizang-ppt/`](skills/guizang-ppt/) 下的所有文件,保留它们原始的 MIT license 和原作者 [op7418](https://github.com/op7418) 的归属。
[skill]: https://docs.anthropic.com/en/docs/claude-code/skills
[guizang]: https://github.com/op7418/guizang-ppt-skill
[acd2]: https://github.com/VoltAgent/awesome-design-md
[ocod]: https://github.com/OpenCoworkAI/open-codesign

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.

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`.

234
README.md
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**.
> **The open-source alternative to [Claude Design][cd].** Local-first, web-deployable, BYOK at every layer — your existing coding agent (Claude Code, Codex, Cursor Agent, Gemini CLI, OpenCode, Qwen) becomes the design engine, driven by **19 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.png" alt="Open Design — editorial cover: design with the agent on your laptop" width="100%" />
</p>
<p align="center">
@ -20,15 +20,15 @@
## Why this exists
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.
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-source, paid-only, cloud-only, locked to Anthropic's model and Anthropic's skills. There is no checkout, no self-host, no Vercel deploy, no swap-in-your-own-agent.
**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-source alternative.** Same loop, same artifact-first mental model, none of the lock-in. We don't ship 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.
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 — exactly the bar Claude Design set, but open and yours.
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,51 +52,130 @@ 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.
<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.png" alt="01 · Entry view" /><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.png" alt="02 · Turn-1 discovery form" /><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.png" alt="03 · Direction picker" /><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.png" alt="04 · Live todo progress" /><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.png" alt="05 · Sandboxed preview" /><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.png" alt="06 · 71-system library" /><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.png" alt="07 · Magazine deck" /><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.png" alt="08 · Mobile prototype" /><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>
</table>
## 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 `od:` frontmatter (`mode`, `platform`, `scenario`, `preview`, `design_system`).
### Showcase examples
The visually distinctive skills you'll most likely run first. Each ships a real `example.html` you can open straight from the repo to see exactly what the agent will produce — no auth, no setup.
<table>
<tr>
<td width="50%" valign="top">
<a href="skills/dating-web/"><img src="docs/screenshots/skills/dating-web.png" alt="dating-web" /></a><br/>
<sub><b><a href="skills/dating-web/"><code>dating-web</code></a></b> · <i>prototype</i><br/>Consumer dating / matchmaking dashboard — left rail nav, ticker bar, KPIs, 30-day mutual-matches chart, editorial typography.</sub>
</td>
<td width="50%" valign="top">
<a href="skills/digital-eguide/"><img src="docs/screenshots/skills/digital-eguide.png" alt="digital-eguide" /></a><br/>
<sub><b><a href="skills/digital-eguide/"><code>digital-eguide</code></a></b> · <i>template</i><br/>Two-spread digital e-guide — cover (title, author, TOC teaser) + lesson spread with pull-quote and step list. Creator / lifestyle tone.</sub>
</td>
</tr>
<tr>
<td width="50%" valign="top">
<a href="skills/email-marketing/"><img src="docs/screenshots/skills/email-marketing.png" alt="email-marketing" /></a><br/>
<sub><b><a href="skills/email-marketing/"><code>email-marketing</code></a></b> · <i>prototype</i><br/>Brand product-launch HTML email — masthead, hero image, headline lockup, CTA, specs grid. Centered single-column, table-fallback safe.</sub>
</td>
<td width="50%" valign="top">
<a href="skills/gamified-app/"><img src="docs/screenshots/skills/gamified-app.png" alt="gamified-app" /></a><br/>
<sub><b><a href="skills/gamified-app/"><code>gamified-app</code></a></b> · <i>prototype</i><br/>Three-frame gamified mobile-app prototype on a dark showcase stage — cover, today's quests with XP ribbons + level bar, quest detail.</sub>
</td>
</tr>
<tr>
<td width="50%" valign="top">
<a href="skills/mobile-onboarding/"><img src="docs/screenshots/skills/mobile-onboarding.png" alt="mobile-onboarding" /></a><br/>
<sub><b><a href="skills/mobile-onboarding/"><code>mobile-onboarding</code></a></b> · <i>prototype</i><br/>Three-frame mobile onboarding flow — splash, value-prop, sign-in. Status bar, swipe dots, primary CTA.</sub>
</td>
<td width="50%" valign="top">
<a href="skills/motion-frames/"><img src="docs/screenshots/skills/motion-frames.png" alt="motion-frames" /></a><br/>
<sub><b><a href="skills/motion-frames/"><code>motion-frames</code></a></b> · <i>prototype</i><br/>Single-frame motion-design hero with looping CSS animations — rotating type ring, animated globe, ticking timer. Hand-off ready for HyperFrames.</sub>
</td>
</tr>
<tr>
<td width="50%" valign="top">
<a href="skills/social-carousel/"><img src="docs/screenshots/skills/social-carousel.png" alt="social-carousel" /></a><br/>
<sub><b><a href="skills/social-carousel/"><code>social-carousel</code></a></b> · <i>prototype</i><br/>Three-card 1080×1080 social-media carousel — cinematic panels with display headlines that connect across the series, brand mark, loop affordance.</sub>
</td>
<td width="50%" valign="top">
<a href="skills/sprite-animation/"><img src="docs/screenshots/skills/sprite-animation.png" alt="sprite-animation" /></a><br/>
<sub><b><a href="skills/sprite-animation/"><code>sprite-animation</code></a></b> · <i>prototype</i><br/>Pixel / 8-bit animated explainer slide — full-bleed cream stage, animated pixel mascot, kinetic Japanese display type, looping CSS keyframes.</sub>
</td>
</tr>
</table>
### Design surfaces
| Skill | Mode | Default for | What it produces |
|---|---|---|---|
| [`web-prototype`](skills/web-prototype/) | prototype | desktop | Single-page HTML — landings, marketing, hero pages |
| [`saas-landing`](skills/saas-landing/) | prototype | desktop | Hero / features / pricing / CTA marketing layout |
| [`dashboard`](skills/dashboard/) | prototype | desktop | Admin / analytics with sidebar + data dense layout |
| [`pricing-page`](skills/pricing-page/) | prototype | desktop | Standalone pricing + comparison tables |
| [`docs-page`](skills/docs-page/) | prototype | desktop | 3-column documentation layout |
| [`blog-post`](skills/blog-post/) | prototype | desktop | Editorial long-form |
| [`mobile-app`](skills/mobile-app/) | prototype | mobile | iPhone 15 Pro / Pixel framed app screen(s) |
| [`simple-deck`](skills/simple-deck/) | deck | desktop | Minimal horizontal-swipe deck |
| [`guizang-ppt`](skills/guizang-ppt/) | deck | **default** for deck | Magazine-style web PPT — bundled from [op7418/guizang-ppt-skill][guizang] |
### Document / work-product surfaces
| Skill | Mode | What it produces |
|---|---|---|
| [`pm-spec`](skills/pm-spec/) | template | PM specification doc with TOC + decision log |
| [`weekly-update`](skills/weekly-update/) | template | Team weekly with progress / blockers / next |
| [`meeting-notes`](skills/meeting-notes/) | template | Meeting decision log |
| [`eng-runbook`](skills/eng-runbook/) | template | Incident runbook |
| [`finance-report`](skills/finance-report/) | template | Exec finance summary |
| [`hr-onboarding`](skills/hr-onboarding/) | template | Role onboarding plan |
| [`invoice`](skills/invoice/) | template | Single-page invoice |
| [`kanban-board`](skills/kanban-board/) | template | Board snapshot |
| [`team-okrs`](skills/team-okrs/) | template | OKR scoresheet |
Adding a skill takes one folder. Read [`docs/skills-protocol.md`](docs/skills-protocol.md) for the extended frontmatter, fork an existing skill, restart the daemon, it appears in the picker.
## Six load-bearing ideas
### 1 · We don't ship an agent. Yours is good enough.
@ -113,13 +192,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 +237,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 +250,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 +269,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 +385,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,65 +393,16 @@ 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`).
### Showcase examples
The visually distinctive skills you'll most likely run first. Each ships a real `example.html` you can open straight from the repo to see what the agent will produce.
| Skill | Mode | What it produces |
|---|---|---|
| [`dating-web`](skills/dating-web/) | prototype | Consumer dating / matchmaking dashboard — left rail nav, ticker bar, KPIs, 30-day mutual-matches chart, editorial typography |
| [`digital-eguide`](skills/digital-eguide/) | template | Two-spread digital e-guide — cover (title, author, TOC teaser) + lesson spread with pull-quote and step list. Creator / lifestyle tone |
| [`email-marketing`](skills/email-marketing/) | prototype | Brand product-launch HTML email — masthead, hero image, headline lockup, CTA, specs grid. Centered single-column, table-fallback safe |
| [`gamified-app`](skills/gamified-app/) | prototype | Three-frame gamified mobile-app prototype on a dark showcase stage — cover, today's quests with XP ribbons + level bar, quest detail |
| [`mobile-onboarding`](skills/mobile-onboarding/) | prototype | Three-frame mobile onboarding flow — splash, value-prop, sign-in. Status bar, swipe dots, primary CTA |
| [`motion-frames`](skills/motion-frames/) | prototype | Single-frame motion-design hero with looping CSS animations — rotating type ring, animated globe, ticking timer. Hand-off ready for HyperFrames |
| [`social-carousel`](skills/social-carousel/) | prototype | Three-card 1080×1080 social-media carousel — cinematic panels with display headlines that connect across the series, brand mark, loop affordance |
| [`sprite-animation`](skills/sprite-animation/) | prototype | Pixel / 8-bit animated explainer slide — full-bleed cream stage, animated pixel mascot, kinetic Japanese display type, looping CSS keyframes |
### Design surfaces
| Skill | Mode | Default for | What it produces |
|---|---|---|---|
| [`web-prototype`](skills/web-prototype/) | prototype | desktop | Single-page HTML — landings, marketing, hero pages |
| [`saas-landing`](skills/saas-landing/) | prototype | desktop | Hero / features / pricing / CTA marketing layout |
| [`dashboard`](skills/dashboard/) | prototype | desktop | Admin / analytics with sidebar + data dense layout |
| [`pricing-page`](skills/pricing-page/) | prototype | desktop | Standalone pricing + comparison tables |
| [`docs-page`](skills/docs-page/) | prototype | desktop | 3-column documentation layout |
| [`blog-post`](skills/blog-post/) | prototype | desktop | Editorial long-form |
| [`mobile-app`](skills/mobile-app/) | prototype | mobile | iPhone 15 Pro / Pixel framed app screen(s) |
| [`simple-deck`](skills/simple-deck/) | deck | desktop | Minimal horizontal-swipe deck |
| [`guizang-ppt`](skills/guizang-ppt/) | deck | **default** for deck | Magazine-style web PPT — bundled from [op7418/guizang-ppt-skill][guizang] |
### Document / work-product surfaces
| Skill | Mode | What it produces |
|---|---|---|
| [`pm-spec`](skills/pm-spec/) | template | PM specification doc with TOC + decision log |
| [`weekly-update`](skills/weekly-update/) | template | Team weekly with progress / blockers / next |
| [`meeting-notes`](skills/meeting-notes/) | template | Meeting decision log |
| [`eng-runbook`](skills/eng-runbook/) | template | Incident runbook |
| [`finance-report`](skills/finance-report/) | template | Exec finance summary |
| [`hr-onboarding`](skills/hr-onboarding/) | template | Role onboarding plan |
| [`invoice`](skills/invoice/) | template | Single-page invoice |
| [`kanban-board`](skills/kanban-board/) | template | Board snapshot |
| [`team-okrs`](skills/team-okrs/) | template | OKR scoresheet |
Adding a skill takes one folder. Read [`docs/skills-protocol.md`](docs/skills-protocol.md) for the extended frontmatter, fork an existing skill, restart the daemon, it appears in the picker.
## 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.png" alt="The 71 design systems library — style guide spread" width="100%" />
</p>
71 systems out of the box, each as a single [`DESIGN.md`](design-systems/README.md):
@ -386,7 +434,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 +448,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 +459,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** |
@ -432,7 +480,7 @@ The whole machinery below is the [`huashu-design`](https://github.com/alchaincyf
| PPT skill reuse | N/A | Built-in | **[`guizang-ppt-skill`][guizang] drops in** |
| Minimum billing | Pro / Max / Team | BYOK | **BYOK** |
[cd]: https://www.anthropic.com/news/claude-design
[cd]: https://x.com/claudeai/status/2045156267690213649
[ocod]: https://github.com/OpenCoworkAI/open-codesign
[piai]: https://github.com/mariozechner/pi-ai
[acd]: https://github.com/VoltAgent/awesome-claude-design
@ -461,7 +509,7 @@ Every external project this repo borrows from. Each link goes to the source so y
| Project | Role here |
|---|---|
| [`Claude Design`][cd] | The closed product this repo provides an open substrate for. |
| [`Claude Design`][cd] | The closed-source product this repo is the open-source alternative to. |
| [**`alchaincyf/huashu-design`**](https://github.com/alchaincyf/huashu-design) | The design-philosophy core. Junior-Designer workflow, the 5-step brand-asset protocol, anti-AI-slop checklist, 5-dimensional self-critique, and the "5 schools × 20 design philosophies" library behind our direction picker — all distilled into [`src/prompts/discovery.ts`](src/prompts/discovery.ts) and [`src/prompts/directions.ts`](src/prompts/directions.ts). |
| [**`op7418/guizang-ppt-skill`**][guizang] | Magazine-web-PPT skill bundled verbatim under [`skills/guizang-ppt/`](skills/guizang-ppt/) with original LICENSE preserved. Default for deck mode. P0/P1/P2 checklist culture borrowed for every other skill. |
| [**`multica-ai/multica`**](https://github.com/multica-ai/multica) | The daemon + adapter architecture. PATH-scan agent detection, local daemon as the only privileged process, agent-as-teammate worldview. We adopt the model; we do not vendor the code. |
@ -481,8 +529,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).
@ -490,7 +538,15 @@ Phased delivery → [`docs/roadmap.md`](docs/roadmap.md).
This is an early implementation — the closed loop (detect → pick skill + design system → chat → parse `<artifact>` → preview → save) runs end-to-end. The prompt stack and skill library are where most of the value lives, and they're stable. The component-level UI is shipping daily.
Issues, PRs, new skills, and new design systems are all welcome.
## Contributing
Issues, PRs, new skills, and new design systems are all welcome. The highest-leverage contributions are usually one folder, one Markdown file, or one PR-sized adapter:
- **Add a skill** — drop a folder into [`skills/`](skills/) following the [`SKILL.md`][skill] convention.
- **Add a design system** — drop a `DESIGN.md` into [`design-systems/<brand>/`](design-systems/) using the 9-section schema.
- **Wire up a new coding-agent CLI** — one entry in [`daemon/agents.js`](daemon/agents.js).
Full walkthrough, bar-for-merging, code style, and what we don't accept → [`CONTRIBUTING.md`](CONTRIBUTING.md) ([简体中文](CONTRIBUTING.zh-CN.md)).
## License

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** 驱动。
> **[Claude Design][cd] 的开源替代品。** 本地优先、可部署到 Vercel、每一层都 BYOK —— 你机器上已经装好的 coding agentClaude Code、Codex、Cursor Agent、Gemini CLI、OpenCode、Qwen就是设计引擎**19 个可组合 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.png" alt="Open Design 封面:与本地 AI 智能体共同设计" width="100%" />
</p>
<p align="center">
@ -20,15 +20,15 @@
## 为什么要做这个
Anthropic 的 [Claude Design][cd]2026-04-17 发布,基于 Opus 4.7)让大家第一次看到:当一个 LLM 不再写废话、开始直接交付设计成品,会是什么样子。它瞬间出圈 —— 然后保持闭源、付费、只跑在云上、绑定 Anthropic 的模型和 Anthropic 的内部 skill。
Anthropic 的 [Claude Design][cd]2026-04-17 发布,基于 Opus 4.7)让大家第一次看到:当一个 LLM 不再写废话、开始直接交付设计成品,会是什么样子。它瞬间出圈 —— 然后保持**闭源**、付费、只跑在云上、绑定 Anthropic 的模型和 Anthropic 的内部 skill。没有 checkout没有自托管没有 Vercel 部署,也换不了自己的 agent。
**Open Claude DesignOCD是它的开源底座。** 我们不做 agent —— 你笔记本上最强的 coding agent 已经装好了。我们要做的,是把它接进一个 skill 驱动的设计工作流,跑在一个普通的 Web 应用里:本地 `pnpm dev`,云端 `vercel deploy`,每一层都 BYOK自带 Key
**Open DesignOD就是它的开源替代品。** 同一套 loop、同一种「artifact-first」心智模型但没有锁定。我们不做 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 文化。
这不是「AI 试图做点设计」。这是一个被提示词栈训练得像高级设计师一样工作的 AI —— 有可用的文件系统、有确定性的色板库、有 checklist 文化 —— 也就是 Claude Design 立下的那条线,只是这次它开源、归你
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,51 +52,130 @@ OCD 站在四个开源项目的肩膀上:
## 效果展示
> 截图位为占位 —— 真实 UI 就是这些截图要拍的对象,请在 PR 里替换 `docs/screenshots/*.png`
<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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" 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.png" alt="08 · 移动端原型" /><br/>
<sub><b>移动端原型</b> —— 像素级精确的 iPhone 15 Pro chrome灵动岛、状态栏 SVG、Home Indicator。多屏原型直接复用 <code>/frames/</code> 共享资源agent 永远不需要重新画一遍手机。</sub>
</td>
</tr>
</table>
## 内置 Skills
19 个 skill每个一个文件夹都遵循 Claude Code 的 [`SKILL.md`][skill] 规范,并叠加 OD 的 `od:` frontmatter`mode`、`platform`、`scenario`、`preview`、`design_system`)。
### 示例展示Showcase examples
视觉表现最强、最适合上手第一跑的几条 skill。每条都附带可直接打开的 `example.html` —— 不用登录、不用配置,先看产出再下单。
<table>
<tr>
<td width="50%" valign="top">
<a href="skills/dating-web/"><img src="docs/screenshots/skills/dating-web.png" alt="dating-web" /></a><br/>
<sub><b><a href="skills/dating-web/"><code>dating-web</code></a></b> · <i>prototype</i><br/>消费级约会 / 婚恋仪表盘 —— 左侧栏、社区动态 ticker、头部 KPI、30 天双向匹配柱状图editorial 字体,克制点缀色。</sub>
</td>
<td width="50%" valign="top">
<a href="skills/digital-eguide/"><img src="docs/screenshots/skills/digital-eguide.png" alt="digital-eguide" /></a><br/>
<sub><b><a href="skills/digital-eguide/"><code>digital-eguide</code></a></b> · <i>template</i><br/>两页数字 e-guide —— 封面标题、作者、TOC 预告)+ 内文跨页pull-quote + 步骤列表),创作者 / 生活方式风。</sub>
</td>
</tr>
<tr>
<td width="50%" valign="top">
<a href="skills/email-marketing/"><img src="docs/screenshots/skills/email-marketing.png" alt="email-marketing" /></a><br/>
<sub><b><a href="skills/email-marketing/"><code>email-marketing</code></a></b> · <i>prototype</i><br/>品牌新品发布邮件 —— 顶部 wordmark、hero 图、标题锁排、主 CTA、规格网格。居中单列 + 表格降级,邮件客户端安全。</sub>
</td>
<td width="50%" valign="top">
<a href="skills/gamified-app/"><img src="docs/screenshots/skills/gamified-app.png" alt="gamified-app" /></a><br/>
<sub><b><a href="skills/gamified-app/"><code>gamified-app</code></a></b> · <i>prototype</i><br/>三屏游戏化移动 app 原型,黑色舞台 —— 封面 / 今日任务XP 缎带 + 等级条)/ 任务详情。</sub>
</td>
</tr>
<tr>
<td width="50%" valign="top">
<a href="skills/mobile-onboarding/"><img src="docs/screenshots/skills/mobile-onboarding.png" alt="mobile-onboarding" /></a><br/>
<sub><b><a href="skills/mobile-onboarding/"><code>mobile-onboarding</code></a></b> · <i>prototype</i><br/>三屏移动端引导流 —— splash、价值主张、登录。状态栏、滑动点、主 CTA。</sub>
</td>
<td width="50%" valign="top">
<a href="skills/motion-frames/"><img src="docs/screenshots/skills/motion-frames.png" alt="motion-frames" /></a><br/>
<sub><b><a href="skills/motion-frames/"><code>motion-frames</code></a></b> · <i>prototype</i><br/>单帧 motion 设计 heroCSS 循环动画 —— 旋转字环、地球、计时器。可直接交给 HyperFrames 等关键帧导出。</sub>
</td>
</tr>
<tr>
<td width="50%" valign="top">
<a href="skills/social-carousel/"><img src="docs/screenshots/skills/social-carousel.png" alt="social-carousel" /></a><br/>
<sub><b><a href="skills/social-carousel/"><code>social-carousel</code></a></b> · <i>prototype</i><br/>1080×1080 三连社媒轮播图 —— 三张电影感面板标题前后呼应品牌标识、loop 标记。</sub>
</td>
<td width="50%" valign="top">
<a href="skills/sprite-animation/"><img src="docs/screenshots/skills/sprite-animation.png" alt="sprite-animation" /></a><br/>
<sub><b><a href="skills/sprite-animation/"><code>sprite-animation</code></a></b> · <i>prototype</i><br/>像素 / 8-bit 动画解释器单帧 —— 米白通屏、像素吉祥物、动感日文标题、循环 CSS keyframes可直接录屏成竖版视频。</sub>
</td>
</tr>
</table>
### 设计交付类
| Skill | Mode | 默认场景 | 产出 |
|---|---|---|---|
| [`web-prototype`](skills/web-prototype/) | prototype | 桌面 | 单页 HTML —— landing、营销、hero |
| [`saas-landing`](skills/saas-landing/) | prototype | 桌面 | hero / features / pricing / CTA 营销版式 |
| [`dashboard`](skills/dashboard/) | prototype | 桌面 | 带侧栏 + 数据密集型的后台 |
| [`pricing-page`](skills/pricing-page/) | prototype | 桌面 | 独立定价页 + 对比表 |
| [`docs-page`](skills/docs-page/) | prototype | 桌面 | 三栏文档版式 |
| [`blog-post`](skills/blog-post/) | prototype | 桌面 | 长文 editorial |
| [`mobile-app`](skills/mobile-app/) | prototype | 移动 | 带 iPhone 15 Pro / Pixel 外壳的 app 屏 |
| [`simple-deck`](skills/simple-deck/) | deck | 桌面 | 极简横滑 deck |
| [`guizang-ppt`](skills/guizang-ppt/) | deck | **deck 默认** | 杂志风网页 PPT —— 来自 [op7418/guizang-ppt-skill][guizang] |
### 文档与办公产物类
| Skill | Mode | 产出 |
|---|---|---|
| [`pm-spec`](skills/pm-spec/) | template | PM 规范文档 + 目录 + 决策日志 |
| [`weekly-update`](skills/weekly-update/) | template | 团队周报:进度 / 阻塞 / 下一步 |
| [`meeting-notes`](skills/meeting-notes/) | template | 会议决策纪要 |
| [`eng-runbook`](skills/eng-runbook/) | template | 故障 runbook |
| [`finance-report`](skills/finance-report/) | template | 高管财务摘要 |
| [`hr-onboarding`](skills/hr-onboarding/) | template | 岗位入职计划 |
| [`invoice`](skills/invoice/) | template | 单页发票 |
| [`kanban-board`](skills/kanban-board/) | template | 看板快照 |
| [`team-okrs`](skills/team-okrs/) | template | OKR 计分表 |
新增一个 skill 就是新增一个文件夹。读 [`docs/skills-protocol.md`](docs/skills-protocol.md) 了解扩展 frontmatterfork 一个现有 skill重启 daemon 即生效。
## 六个底层设计
### 1 · 我们不带 agent你的就够好
@ -113,13 +192,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 +237,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 +250,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浏览器打印· PPTXskill 自定义)· 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 +269,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 +385,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,65 +393,16 @@ 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`)。
### 示例展示Showcase examples
视觉表现最强、最适合上手第一跑的几条 skill。每条都附带可直接打开的 `example.html`,先看产出再下单。
| Skill | Mode | 产出 |
|---|---|---|
| [`dating-web`](skills/dating-web/) | prototype | 消费级约会 / 婚恋仪表盘 —— 左侧栏、社区动态 ticker、头部 KPI、30 天双向匹配柱状图editorial 字体,克制点缀色 |
| [`digital-eguide`](skills/digital-eguide/) | template | 两页数字 e-guide —— 封面标题、作者、TOC 预告)+ 内文跨页pull-quote + 步骤列表),创作者 / 生活方式风 |
| [`email-marketing`](skills/email-marketing/) | prototype | 品牌新品发布邮件 —— 顶部 wordmark、hero 图、标题锁排、主 CTA、规格网格。居中单列 + 表格降级,邮件客户端安全 |
| [`gamified-app`](skills/gamified-app/) | prototype | 三屏游戏化移动 app 原型,黑色舞台 —— 封面 / 今日任务XP 缎带 + 等级条)/ 任务详情 |
| [`mobile-onboarding`](skills/mobile-onboarding/) | prototype | 三屏移动端引导流 —— splash、价值主张、登录。状态栏、滑动点、主 CTA |
| [`motion-frames`](skills/motion-frames/) | prototype | 单帧 motion 设计 heroCSS 循环动画 —— 旋转字环、地球、计时器。可直接交给 HyperFrames 等关键帧导出 |
| [`social-carousel`](skills/social-carousel/) | prototype | 1080×1080 三连社媒轮播图 —— 三张电影感面板标题前后呼应品牌标识、loop 标记 |
| [`sprite-animation`](skills/sprite-animation/) | prototype | 像素 / 8-bit 动画解释器单帧 —— 米白通屏、像素吉祥物、动感日文标题、循环 CSS keyframes可直接录屏成竖版视频 |
### 设计交付类
| Skill | Mode | 默认场景 | 产出 |
|---|---|---|---|
| [`web-prototype`](skills/web-prototype/) | prototype | 桌面 | 单页 HTML —— landing、营销、hero |
| [`saas-landing`](skills/saas-landing/) | prototype | 桌面 | hero / features / pricing / CTA 营销版式 |
| [`dashboard`](skills/dashboard/) | prototype | 桌面 | 带侧栏 + 数据密集型的后台 |
| [`pricing-page`](skills/pricing-page/) | prototype | 桌面 | 独立定价页 + 对比表 |
| [`docs-page`](skills/docs-page/) | prototype | 桌面 | 三栏文档版式 |
| [`blog-post`](skills/blog-post/) | prototype | 桌面 | 长文 editorial |
| [`mobile-app`](skills/mobile-app/) | prototype | 移动 | 带 iPhone 15 Pro / Pixel 外壳的 app 屏 |
| [`simple-deck`](skills/simple-deck/) | deck | 桌面 | 极简横滑 deck |
| [`guizang-ppt`](skills/guizang-ppt/) | deck | **deck 默认** | 杂志风网页 PPT —— 来自 [op7418/guizang-ppt-skill][guizang] |
### 文档与办公产物类
| Skill | Mode | 产出 |
|---|---|---|
| [`pm-spec`](skills/pm-spec/) | template | PM 规范文档 + 目录 + 决策日志 |
| [`weekly-update`](skills/weekly-update/) | template | 团队周报:进度 / 阻塞 / 下一步 |
| [`meeting-notes`](skills/meeting-notes/) | template | 会议决策纪要 |
| [`eng-runbook`](skills/eng-runbook/) | template | 故障 runbook |
| [`finance-report`](skills/finance-report/) | template | 高管财务摘要 |
| [`hr-onboarding`](skills/hr-onboarding/) | template | 岗位入职计划 |
| [`invoice`](skills/invoice/) | template | 单页发票 |
| [`kanban-board`](skills/kanban-board/) | template | 看板快照 |
| [`team-okrs`](skills/team-okrs/) | template | OKR 计分表 |
新增一个 skill 就是新增一个文件夹。读 [`docs/skills-protocol.md`](docs/skills-protocol.md) 了解扩展 frontmatterfork 一个现有 skill重启 daemon 即生效。
## 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.png" alt="71 套 Design Systems 库 — 编辑版式双页" width="100%" />
</p>
71 套开箱即用,每套一个 [`DESIGN.md`](design-systems/README.md)
@ -386,7 +434,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 +448,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 +459,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** |
@ -432,7 +480,7 @@ open-claude-design/
| PPT skill 复用 | N/A | 内置 | **[`guizang-ppt-skill`][guizang] 直接接入** |
| 计费门槛 | Pro / Max / Team | BYOK | **BYOK** |
[cd]: https://www.anthropic.com/news/claude-design
[cd]: https://x.com/claudeai/status/2045156267690213649
[ocod]: https://github.com/OpenCoworkAI/open-codesign
[piai]: https://github.com/mariozechner/pi-ai
[acd]: https://github.com/VoltAgent/awesome-claude-design
@ -461,7 +509,7 @@ Daemon 启动时从 `PATH` 自动检测,无需配置。
| 项目 | 在这里的角色 |
|---|---|
| [`Claude Design`][cd] | 本仓库为它提供开源底座的闭源产品。 |
| [`Claude Design`][cd] | 本仓库为之提供开源替代的闭源产品。 |
| [**`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) 与 [`src/prompts/directions.ts`](src/prompts/directions.ts)。 |
| [**`op7418/guizang-ppt-skill`**(歸藏)][guizang] | Magazine-web-PPT skill 原样捆绑在 [`skills/guizang-ppt/`](skills/guizang-ppt/) 下,原 LICENSE 保留。Deck 模式默认。P0/P1/P2 checklist 文化也被借给了所有其他 skill。 |
| [**`multica-ai/multica`**](https://github.com/multica-ai/multica) | Daemon + adapter 架构。PATH 扫描式 agent 检测、本地 daemon 作为唯一特权进程、agent-as-teammate 世界观。我们采纳模型,不 vendor 代码。 |
@ -481,8 +529,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)。
@ -490,7 +538,15 @@ Daemon 启动时从 `PATH` 自动检测,无需配置。
这是一个早期实现 —— 闭环(检测 → 选 skill + design system → 对话 → 解析 `<artifact>` → 预览 → 保存)已经端到端跑通。提示词栈和 skill 库是价值最重的部分,目前已稳定。组件级 UI 仍在每天迭代。
欢迎 issue、PR、新 skill、新 design system。
## 贡献
欢迎 issue、PR、新 skill、新 design system。收益最高的贡献往往就是一个文件夹、一份 Markdown或者一个 PR 大小的 adapter
- **加一个 skill** —— 往 [`skills/`](skills/) 丢一个文件夹,遵循 [`SKILL.md`][skill] 规范。
- **加一套 design system** —— 往 [`design-systems/<brand>/`](design-systems/) 丢一份 `DESIGN.md`,用 9 段式 schema。
- **接入一个新的 coding-agent CLI** —— 在 [`daemon/agents.js`](daemon/agents.js) 里加一项。
完整流程、合并硬线、代码风格、我们不接收的 PR 类型 → [`CONTRIBUTING.zh-CN.md`](CONTRIBUTING.zh-CN.md)[English](CONTRIBUTING.md))。
## License

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/

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'

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);

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.',
});
}

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).
//

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).

View file

@ -24,20 +24,27 @@ 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),
// Optional metadata hints used by 'Use this prompt' fast-create so
// the resulting project mirrors the shipped example.html. Each hint
// is only consumed when its kind matches the skill mode; missing
// hints fall back to the same defaults the new-project form uses.
fidelity: normalizeFidelity(data.od?.fidelity),
speakerNotes: normalizeBoolHint(data.od?.speaker_notes),
animations: normalizeBoolHint(data.od?.animations),
examplePrompt: derivePrompt(data),
body: hasAttachments ? withSkillRootPreamble(body, dir) : body,
dir,
@ -85,7 +92,28 @@ function normalizeDefaultFor(value) {
return [String(value)];
}
// Coerce `ocd.featured` into a numeric priority. Lower numbers float to the
// Optional `od.fidelity` hint for prototype skills. Only 'wireframe' and
// 'high-fidelity' are meaningful — anything else collapses to null so the
// caller falls back to the form default ('high-fidelity').
function normalizeFidelity(value) {
if (value === 'wireframe' || value === 'high-fidelity') return value;
return null;
}
// Coerce truthy / falsy strings ("true", "yes", "false", "no") and booleans
// to a real boolean. Returns null for anything we can't interpret so the
// caller knows to fall back to the form default.
function normalizeBoolHint(value) {
if (typeof value === 'boolean') return value;
if (typeof value === 'string') {
const v = value.trim().toLowerCase();
if (v === 'true' || v === 'yes' || v === '1') return true;
if (v === 'false' || v === 'no' || v === '0') return false;
}
return null;
}
// 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 +127,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 '';

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)

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+.

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`.

View file

@ -0,0 +1,381 @@
<!doctype html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>Open Design — cover</title>
<link rel='preconnect' href='https://fonts.googleapis.com'>
<link rel='preconnect' href='https://fonts.gstatic.com' crossorigin>
<link href='https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300;0,9..144,500;0,9..144,700;1,9..144,500;1,9..144,700&family=JetBrains+Mono:wght@400;500&family=Inter:wght@400;500&display=swap' rel='stylesheet'>
<style>
:root {
--bg: #0d0a06;
--bg-2: #14100a;
--ink: #f3ead8;
--muted: #9b8f78;
--rule: #4a3f2c;
--accent: #f0833f;
--accent-2: #e85a2c;
--paper: #f6efdd;
}
* { box-sizing: border-box; }
html, body {
margin: 0;
padding: 0;
width: 1920px;
height: 1080px;
background: var(--bg);
color: var(--ink);
font-family: 'Inter', -apple-system, system-ui, sans-serif;
overflow: hidden;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
background:
radial-gradient(1200px 700px at 78% 22%, rgba(240,131,63,0.12), transparent 70%),
radial-gradient(900px 600px at 12% 80%, rgba(232,90,44,0.06), transparent 70%),
linear-gradient(180deg, #0e0b07 0%, #0a0805 100%);
padding: 56px 72px;
display: flex;
flex-direction: column;
}
.mono {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 12px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--muted);
}
header {
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
padding-bottom: 22px;
border-bottom: 1px solid var(--rule);
}
header .l { text-align: left; }
header .r { text-align: right; }
header .center {
font-family: 'Fraunces', serif;
font-style: italic;
font-weight: 500;
font-size: 22px;
color: var(--ink);
letter-spacing: 0.01em;
}
header .center .dot {
display: inline-block;
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--accent);
margin: 0 8px 4px 0;
vertical-align: middle;
}
main {
flex: 1;
display: grid;
grid-template-columns: 1.05fr 1fr;
column-gap: 64px;
padding-top: 56px;
align-items: stretch;
}
.left {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.eyebrow {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 28px;
}
.eyebrow .pill {
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
letter-spacing: 0.22em;
color: #f6e9d4;
background: rgba(240,131,63,0.16);
border: 1px solid rgba(240,131,63,0.45);
padding: 6px 12px;
border-radius: 999px;
text-transform: uppercase;
}
.eyebrow .pill.alt {
color: var(--muted);
background: transparent;
border-color: var(--rule);
}
h1 {
font-family: 'Fraunces', serif;
font-weight: 500;
font-size: 116px;
line-height: 0.94;
letter-spacing: -0.025em;
color: var(--ink);
margin: 0 0 36px 0;
}
h1 em {
font-style: italic;
color: var(--accent);
font-weight: 500;
}
h1 .small {
font-size: 96px;
}
.lede {
font-family: 'Fraunces', serif;
font-weight: 300;
font-size: 22px;
line-height: 1.5;
color: #d8cdb6;
max-width: 640px;
margin: 0 0 32px 0;
}
.lede b {
font-weight: 500;
color: #f3ead8;
}
.meta {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0;
border-top: 1px solid var(--rule);
padding-top: 22px;
}
.meta .cell {
border-right: 1px solid var(--rule);
padding-right: 18px;
}
.meta .cell:last-child { border-right: none; }
.meta .num {
font-family: 'Fraunces', serif;
font-weight: 500;
font-size: 42px;
line-height: 1;
color: var(--ink);
letter-spacing: -0.01em;
}
.meta .num em {
font-style: italic;
color: var(--accent);
font-weight: 500;
}
.meta .lbl {
margin-top: 10px;
font-family: 'JetBrains Mono', monospace;
font-size: 10.5px;
letter-spacing: 0.18em;
color: var(--muted);
text-transform: uppercase;
line-height: 1.4;
}
/* right artifact collage */
.right {
position: relative;
}
.stage {
position: absolute;
inset: 0;
}
.card {
position: absolute;
border-radius: 18px;
overflow: hidden;
background: #1a140d;
box-shadow:
0 1px 0 rgba(255,255,255,0.04) inset,
0 24px 60px rgba(0,0,0,0.55),
0 6px 18px rgba(0,0,0,0.45);
border: 1px solid rgba(255,255,255,0.06);
}
.card img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.card .tag {
position: absolute;
top: 14px;
left: 14px;
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
letter-spacing: 0.2em;
text-transform: uppercase;
color: #ffd9b6;
background: rgba(20, 14, 8, 0.7);
padding: 6px 10px;
border-radius: 6px;
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
border: 1px solid rgba(255,217,182,0.18);
}
/* arrange three artifacts as an editorial collage */
.card.a { /* gamified-app — back-left */
width: 540px;
height: 320px;
top: 70px;
right: 280px;
transform: rotate(-3.5deg);
}
.card.b { /* digital-eguide — front-right hero */
width: 620px;
height: 360px;
top: 220px;
right: 0;
transform: rotate(2.5deg);
z-index: 3;
}
.card.c { /* dating-web — bottom-left */
width: 520px;
height: 300px;
top: 460px;
right: 230px;
transform: rotate(-1.5deg);
z-index: 2;
}
/* decorative marks */
.mark-circle {
position: absolute;
top: 36px;
right: 24px;
width: 86px;
height: 86px;
border-radius: 50%;
background: radial-gradient(circle at 35% 30%, #ffb37a, var(--accent-2) 80%);
color: #2a1408;
font-family: 'Fraunces', serif;
font-style: italic;
font-weight: 700;
font-size: 14px;
line-height: 1.15;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
transform: rotate(8deg);
box-shadow: 0 14px 30px rgba(232,90,44,0.45);
z-index: 5;
}
.mark-circle span { padding: 0 10px; }
footer {
margin-top: 48px;
padding-top: 22px;
border-top: 1px solid var(--rule);
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
}
footer .l { text-align: left; }
footer .r { text-align: right; }
footer .c {
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
letter-spacing: 0.28em;
color: var(--muted);
text-transform: uppercase;
}
.underline-accent {
position: relative;
display: inline-block;
}
.underline-accent::after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: -6px;
height: 6px;
background: var(--accent);
border-radius: 4px;
opacity: 0.85;
}
</style>
</head>
<body>
<header>
<div class='mono l'>Open Design · Manifesto · 2026 Edition</div>
<div class='center'><span class='dot'></span>open.design</div>
<div class='mono r'>Cover · 01 / 08 · OSS Alternative</div>
</header>
<main>
<section class='left'>
<div>
<div class='eyebrow'>
<span class='pill'>· APACHE 2.0</span>
<span class='pill alt'>Local-first · BYOK</span>
</div>
<h1>
Design with the<br/>
<em>agent</em> already<br/>
<span class='small'>on your <span class='underline-accent'>laptop</span>.</span>
</h1>
<p class='lede'>
Open Design is the open-source alternative to Claude Design.
Your existing coding agent — <b>Claude Code · Codex · Cursor · Gemini · OpenCode · Qwen</b>
becomes the design engine, driven by 19 composable Skills and 71 brand-grade Design Systems.
</p>
</div>
<div class='meta'>
<div class='cell'>
<div class='num'>71</div>
<div class='lbl'>Design<br/>Systems</div>
</div>
<div class='cell'>
<div class='num'>19</div>
<div class='lbl'>Composable<br/>Skills</div>
</div>
<div class='cell'>
<div class='num'>06</div>
<div class='lbl'>Coding<br/>Agents</div>
</div>
<div class='cell'>
<div class='num'><em>0</em></div>
<div class='lbl'>Lock-in /<br/>Vendor Cloud</div>
</div>
</div>
</section>
<section class='right'>
<div class='stage'>
<div class='card a'>
<span class='tag'>· Hi-Fi Prototype · iPhone</span>
<img src='../../screenshots/skills/gamified-app.png' alt=''>
</div>
<div class='card b'>
<span class='tag'>· Digital E-guide · 64pp</span>
<img src='../../screenshots/skills/digital-eguide.png' alt=''>
</div>
<div class='card c'>
<span class='tag'>· Dating App · Web</span>
<img src='../../screenshots/skills/dating-web.png' alt=''>
</div>
<div class='mark-circle'><span>OPEN<br/>SOURCE</span></div>
</div>
</section>
</main>
<footer>
<div class='mono l'>BYOK at every layer · No cloud lock-in</div>
<div class='c'>· pnpm dev · vercel deploy · npm start ·</div>
<div class='mono r'>github.com/open-design</div>
</footer>
</body>
</html>

View file

@ -0,0 +1,520 @@
<!doctype html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>71 Design Systems — cover</title>
<link rel='preconnect' href='https://fonts.googleapis.com'>
<link rel='preconnect' href='https://fonts.gstatic.com' crossorigin>
<link href='https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,400;0,9..144,500;0,9..144,700;1,9..144,500;1,9..144,700&family=JetBrains+Mono:wght@400;500&family=Inter:wght@400;500&display=swap' rel='stylesheet'>
<style>
:root {
--surface: #d9c3bd;
--surface-2: #e6d2cc;
--paper: #f5ecd9;
--paper-edge: #e8dcc4;
--ink: #1c1814;
--ink-soft: #4d4339;
--muted: #8a7e70;
--rule: #c8b9a1;
--accent: #c44a3a;
--accent-2: #d4593f;
}
* { box-sizing: border-box; }
html, body {
margin: 0;
padding: 0;
width: 1920px;
height: 1080px;
background: var(--surface);
color: var(--ink);
font-family: 'Inter', -apple-system, system-ui, sans-serif;
overflow: hidden;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
background:
radial-gradient(1100px 700px at 28% 12%, var(--surface-2), transparent 70%),
radial-gradient(900px 600px at 88% 90%, #cab1aa, transparent 70%),
var(--surface);
padding: 60px 80px;
display: flex;
gap: 56px;
align-items: stretch;
}
.page {
background: var(--paper);
flex: 1;
border-radius: 4px;
padding: 56px 60px;
box-shadow:
0 0 0 1px var(--paper-edge),
0 30px 60px rgba(60, 30, 24, 0.18),
0 8px 22px rgba(60, 30, 24, 0.12);
position: relative;
display: flex;
flex-direction: column;
overflow: hidden;
}
.page::before {
content: '';
position: absolute;
inset: 0;
pointer-events: none;
background:
linear-gradient(180deg, rgba(28,24,20,0.04), transparent 8%, transparent 92%, rgba(28,24,20,0.05));
}
.mono {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 11px;
letter-spacing: 0.22em;
color: var(--muted);
text-transform: uppercase;
}
.pageHead {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 14px;
border-bottom: 1px solid var(--rule);
}
.dot {
display: inline-block;
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--accent);
margin-right: 8px;
vertical-align: middle;
transform: translateY(-1px);
}
/* ---------- LEFT (cover) page ---------- */
.cover h1 {
font-family: 'Fraunces', serif;
font-weight: 500;
font-size: 96px;
line-height: 0.94;
letter-spacing: -0.02em;
color: var(--ink);
margin: 64px 0 32px 0;
}
.cover h1 em {
font-style: italic;
color: var(--accent);
font-weight: 500;
}
.cover .tagline {
font-family: 'Fraunces', serif;
font-style: italic;
font-weight: 400;
font-size: 22px;
line-height: 1.45;
color: var(--ink-soft);
max-width: 480px;
margin: 0 0 36px 0;
}
.byline {
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
letter-spacing: 0.22em;
color: var(--muted);
text-transform: uppercase;
padding: 14px 0;
border-top: 1px solid var(--rule);
border-bottom: 1px solid var(--rule);
margin-bottom: 36px;
}
.stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0;
margin-bottom: 44px;
}
.stats .cell { padding-right: 16px; }
.stats .cell + .cell { border-left: 1px solid var(--rule); padding-left: 24px; }
.stats .num {
font-family: 'Fraunces', serif;
font-weight: 500;
font-size: 64px;
line-height: 1;
color: var(--ink);
letter-spacing: -0.02em;
}
.stats .num em { font-style: italic; color: var(--accent); }
.stats .lbl {
margin-top: 10px;
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
letter-spacing: 0.22em;
color: var(--muted);
text-transform: uppercase;
line-height: 1.4;
}
.toc-title {
font-family: 'Fraunces', serif;
font-weight: 500;
font-size: 32px;
margin: 8px 0 18px 0;
color: var(--ink);
}
.toc-title em { font-style: italic; color: var(--accent); }
.toc {
display: flex;
flex-direction: column;
gap: 10px;
}
.toc-row {
display: flex;
align-items: baseline;
font-family: 'Fraunces', serif;
font-size: 17px;
color: var(--ink);
}
.toc-row .name { flex: 0 0 auto; }
.toc-row .dots {
flex: 1;
border-bottom: 1px dotted #b6a487;
margin: 0 10px;
transform: translateY(-4px);
}
.toc-row .pg {
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
letter-spacing: 0.18em;
color: var(--muted);
}
.cover .footer {
margin-top: auto;
display: flex;
justify-content: space-between;
border-top: 1px solid var(--rule);
padding-top: 14px;
}
/* ---------- RIGHT (index) page ---------- */
.index .h2 {
font-family: 'Fraunces', serif;
font-weight: 500;
font-size: 56px;
line-height: 1;
letter-spacing: -0.02em;
color: var(--ink);
margin: 32px 0 12px 0;
}
.index .h2 em {
font-style: italic;
color: var(--accent);
font-weight: 500;
}
.index .sub {
font-family: 'Fraunces', serif;
font-style: italic;
font-weight: 400;
font-size: 18px;
color: var(--ink-soft);
line-height: 1.5;
max-width: 540px;
margin: 0 0 28px 0;
}
.drop {
float: left;
font-family: 'Fraunces', serif;
font-weight: 500;
font-size: 76px;
line-height: 0.85;
color: var(--accent);
margin: 8px 12px -4px 0;
}
.drop + p {
font-family: 'Fraunces', serif;
font-size: 16px;
line-height: 1.5;
color: var(--ink-soft);
margin: 0 0 18px 0;
}
.columns {
display: grid;
grid-template-columns: 1fr 1fr;
column-gap: 36px;
row-gap: 6px;
margin: 18px 0 12px 0;
border-top: 1px solid var(--rule);
border-bottom: 1px solid var(--rule);
padding: 14px 0;
}
.item {
display: grid;
grid-template-columns: 26px 1fr auto;
align-items: baseline;
gap: 10px;
padding: 6px 0;
font-family: 'Fraunces', serif;
font-size: 16px;
color: var(--ink);
}
.item .n {
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
letter-spacing: 0.12em;
color: var(--muted);
}
.item .swatch {
width: 14px;
height: 14px;
border-radius: 3px;
display: inline-block;
transform: translateY(2px);
margin-right: 6px;
box-shadow: 0 0 0 1px rgba(0,0,0,0.08) inset;
}
.item .name { font-weight: 500; }
.item .tag {
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--muted);
}
.item.featured .name { color: var(--accent); font-style: italic; }
.spotlight {
display: grid;
grid-template-columns: 110px 1fr;
gap: 18px;
align-items: center;
background: #f0e3c8;
border: 1px solid var(--rule);
border-radius: 6px;
padding: 18px 20px;
margin-top: 18px;
}
.spotlight .swatches {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 6px;
}
.spotlight .sw {
height: 28px;
border-radius: 4px;
box-shadow: 0 0 0 1px rgba(0,0,0,0.06) inset;
}
.spotlight .label {
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
letter-spacing: 0.18em;
color: var(--muted);
text-transform: uppercase;
margin-bottom: 4px;
}
.spotlight h3 {
font-family: 'Fraunces', serif;
font-weight: 500;
font-style: italic;
font-size: 22px;
margin: 0 0 6px 0;
color: var(--ink);
}
.spotlight h3 em { color: var(--accent); }
.spotlight p {
font-family: 'Fraunces', serif;
font-size: 14px;
line-height: 1.5;
color: var(--ink-soft);
margin: 0;
}
.index .footer {
margin-top: auto;
display: flex;
justify-content: space-between;
border-top: 1px solid var(--rule);
padding-top: 14px;
}
.stamp {
position: absolute;
top: 56px;
right: 56px;
width: 88px;
height: 88px;
border-radius: 50%;
background: var(--accent);
color: #fff5e9;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
transform: rotate(8deg);
font-family: 'Fraunces', serif;
font-weight: 500;
font-style: italic;
font-size: 13px;
line-height: 1.15;
box-shadow: 0 12px 28px rgba(196,74,58,0.35);
z-index: 2;
}
</style>
</head>
<body>
<!-- LEFT PAGE: cover -->
<article class='page cover'>
<div class='pageHead'>
<div class='mono'><span class='dot'></span>Style &amp; Format Guide for Designers</div>
<div class='mono'>2026 Edition</div>
</div>
<h1>The <em>71</em><br/>Systems<br/>Library.</h1>
<p class='tagline'>
Linear, Stripe, Vercel, Airbnb, Tesla, Notion, Anthropic, Apple, Cursor, Supabase, Figma —
seventy-one brand-grade systems, one open library, zero lock-in.
</p>
<div class='byline'>By Open Design · Maintained on GitHub · 19 / 04 / 2026</div>
<div class='stats'>
<div class='cell'>
<div class='num'>71</div>
<div class='lbl'>Design<br/>Systems</div>
</div>
<div class='cell'>
<div class='num'>19</div>
<div class='lbl'>Composable<br/>Skills</div>
</div>
<div class='cell'>
<div class='num'><em>1</em></div>
<div class='lbl'>Library, zero<br/>vendor cloud</div>
</div>
</div>
<h2 class='toc-title'>What's <em>inside</em>.</h2>
<div class='toc'>
<div class='toc-row'><span class='name'>Tokens, palettes, motion</span><span class='dots'></span><span class='pg'>04</span></div>
<div class='toc-row'><span class='name'>Pick a direction</span><span class='dots'></span><span class='pg'>12</span></div>
<div class='toc-row'><span class='name'>Tone &amp; typography</span><span class='dots'></span><span class='pg'>18</span></div>
<div class='toc-row'><span class='name'>71 systems index</span><span class='dots'></span><span class='pg'>24</span></div>
<div class='toc-row'><span class='name'>Bring-your-own-key</span><span class='dots'></span><span class='pg'>40</span></div>
<div class='toc-row'><span class='name'>The anti-AI-slop checklist</span><span class='dots'></span><span class='pg'>52</span></div>
</div>
<div class='footer'>
<div class='mono'>Tokens, palettes &amp; type</div>
<div class='mono'>01 / 64</div>
</div>
</article>
<!-- RIGHT PAGE: index -->
<article class='page index'>
<div class='pageHead'>
<div class='mono'><span class='dot'></span>Chapter 02 · Index</div>
<div class='mono'>71 entries · A → Z</div>
</div>
<h2 class='h2'>All systems —<br/><em>one library.</em></h2>
<p class='sub'>
Every system ships a deterministic OKLch palette, a font stack, and a tone profile.
Pick one tile and the agent inherits the whole brand.
</p>
<p>
<span class='drop'>S</span>
eventy-one product systems, two hand-authored starters, five visual directions. Imported and curated
from awesome-design-md, hand-tuned for Open Design's discovery loop. Drop one in,
every artifact downstream changes accordingly — no model freestyle.
</p>
<div class='columns'>
<div class='item featured'>
<span class='n'>03</span>
<span><span class='swatch' style='background:#5e6ad2'></span><span class='name'>Linear</span></span>
<span class='tag'>· graphite · violet</span>
</div>
<div class='item'>
<span class='n'>07</span>
<span><span class='swatch' style='background:#635bff'></span><span class='name'>Stripe</span></span>
<span class='tag'>· payments · indigo</span>
</div>
<div class='item'>
<span class='n'>09</span>
<span><span class='swatch' style='background:#000000'></span><span class='name'>Vercel</span></span>
<span class='tag'>· void · grayscale</span>
</div>
<div class='item'>
<span class='n'>14</span>
<span><span class='swatch' style='background:#ff385c'></span><span class='name'>Airbnb</span></span>
<span class='tag'>· rausch · rounded</span>
</div>
<div class='item'>
<span class='n'>18</span>
<span><span class='swatch' style='background:#cc0000'></span><span class='name'>Tesla</span></span>
<span class='tag'>· red · industrial</span>
</div>
<div class='item'>
<span class='n'>22</span>
<span><span class='swatch' style='background:#000000'></span><span class='name'>Notion</span></span>
<span class='tag'>· paper · serif</span>
</div>
<div class='item'>
<span class='n'>27</span>
<span><span class='swatch' style='background:#cc785c'></span><span class='name'>Anthropic</span></span>
<span class='tag'>· clay · serif</span>
</div>
<div class='item'>
<span class='n'>31</span>
<span><span class='swatch' style='background:#a8a8a8'></span><span class='name'>Apple</span></span>
<span class='tag'>· chrome · sf pro</span>
</div>
<div class='item'>
<span class='n'>34</span>
<span><span class='swatch' style='background:#1a1a1a'></span><span class='name'>Cursor</span></span>
<span class='tag'>· terminal · mono</span>
</div>
<div class='item'>
<span class='n'>41</span>
<span><span class='swatch' style='background:#3ecf8e'></span><span class='name'>Supabase</span></span>
<span class='tag'>· emerald · rounded</span>
</div>
<div class='item'>
<span class='n'>48</span>
<span><span class='swatch' style='background:#0acf83'></span><span class='name'>Figma</span></span>
<span class='tag'>· spectrum · canvas</span>
</div>
<div class='item'>
<span class='n'>57</span>
<span><span class='swatch' style='background:#000000'></span><span class='name'>OpenAI</span></span>
<span class='tag'>· void · sober</span>
</div>
</div>
<div class='spotlight'>
<div class='swatches'>
<span class='sw' style='background:#1c1816'></span>
<span class='sw' style='background:#5e6ad2'></span>
<span class='sw' style='background:#9b9bd6'></span>
<span class='sw' style='background:#f3ead8'></span>
</div>
<div>
<div class='label'>Spotlight · Linear · 03 / 71</div>
<h3>Graphite + electric <em>violet.</em></h3>
<p>IBM Plex Sans · Inter Display · 4-step OKLch palette · 16/24 grid · square radius. The agent inherits the full token tree the moment you tap the tile.</p>
</div>
</div>
<div class='footer'>
<div class='mono'>Chapter 02 · Index</div>
<div class='mono'>24 / 64</div>
</div>
<div class='stamp'><span>71<br/>SYSTEMS</span></div>
</article>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 MiB

After

Width:  |  Height:  |  Size: 87 KiB

43
docs/assets/banner.svg Normal file
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 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 MiB

After

Width:  |  Height:  |  Size: 79 KiB

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 KiB

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.

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)

View file

@ -11,7 +11,7 @@ Every external project this spec leans on. Three questions per entry: what is it
### [Anthropic Claude Design][cd]
- **URL:** [claude.ai/design][cd] · [release announcement](https://www.infoq.cn/article/TH0QVHpvVGZ7VP3hAEmm) · [ifanr review](https://www.ifanr.com/1662860)
[cd]: https://www.anthropic.com/news/claude-design
[cd]: https://x.com/claudeai/status/2045156267690213649
- **What it is:** Anthropic's closed-source AI design product. Released 2026-04-17. Powered by Opus 4.7. Web-only (claude.ai). Generates prototypes, wireframes, decks, marketing pages, complex prototypes with voice/video/3D/shaders.
- **Why it matters to us:** Defines the category. Its viral moment (~60M X impressions week 1) proves the market.
- **What we borrow:** The high-level value prop — "natural language → editable visual design." Feature inspiration for modes (prototype, deck, marketing). UI ideas around inline editing and custom sliders.
@ -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.
---

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

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

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.

View file

@ -1,9 +1,9 @@
# 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]).
[cd]: https://www.anthropic.com/news/claude-design
[cd]: https://x.com/claudeai/status/2045156267690213649
[ocod]: https://github.com/OpenCoworkAI/open-codesign
[guizang]: https://github.com/op7418/guizang-ppt-skill
[multica]: https://github.com/multica-ai/multica
@ -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.

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>

6
package-lock.json generated
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",

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",

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

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.

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>

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:

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>

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).

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>

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

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>

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.

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>

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**:

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>

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).

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>

View file

@ -12,7 +12,7 @@ triggers:
- "sre doc"
- "service runbook"
- "运维手册"
ocd:
od:
mode: prototype
platform: desktop
scenario: engineering

View file

@ -13,7 +13,7 @@ triggers:
- "mrr review"
- "财报"
- "财务报告"
ocd:
od:
mode: prototype
platform: desktop
scenario: finance

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.

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>

View file

@ -16,7 +16,7 @@ triggers:
- "网页 PPT"
- "发布会"
- "分享 PPT"
ocd:
od:
mode: deck
scenario: marketing
featured: 9

View file

@ -11,7 +11,7 @@ triggers:
- "first week"
- "入职"
- "新员工"
ocd:
od:
mode: prototype
platform: desktop
scenario: hr

View file

@ -10,7 +10,7 @@ triggers:
- "billing statement"
- "发票"
- "账单"
ocd:
od:
mode: prototype
platform: desktop
scenario: finance

View file

@ -12,7 +12,7 @@ triggers:
- "trello"
- "jira board"
- "看板"
ocd:
od:
mode: prototype
platform: desktop
scenario: operations

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.

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>

View file

@ -11,7 +11,7 @@ triggers:
- "1:1 notes"
- "all-hands recap"
- "会议纪要"
ocd:
od:
mode: prototype
platform: desktop
scenario: operations

View file

@ -14,7 +14,7 @@ triggers:
- "app mockup"
- "移动端"
- "手机 app"
ocd:
od:
mode: prototype
platform: mobile
scenario: design

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

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>

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

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;">

View file

@ -12,7 +12,7 @@ triggers:
- "phone signup"
- "app onboarding"
- "移动端引导"
ocd:
od:
mode: prototype
platform: mobile
scenario: design

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

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>

View file

@ -11,7 +11,7 @@ triggers:
- "feature brief"
- "feature doc"
- "需求文档"
ocd:
od:
mode: prototype
platform: desktop
scenario: product

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**:

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>

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.

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>

View file

@ -13,7 +13,7 @@ triggers:
- "presentation"
- "幻灯"
- "ppt 模板"
ocd:
od:
mode: deck
scenario: product
preview:

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() {

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;

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

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>

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.

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>

View file

@ -11,7 +11,7 @@ triggers:
- "key results"
- "objectives"
- "目标"
ocd:
od:
mode: prototype
platform: desktop
scenario: product

View file

@ -18,7 +18,7 @@ triggers:
- "可调参数面板"
- "side panel"
- "knobs"
ocd:
od:
mode: prototype
platform: desktop
scenario: design

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>

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