mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
docs: refresh environment setup guidance (#104)
This commit is contained in:
@@ -222,8 +222,8 @@ The user explicitly opts in to fallback — we don't silently switch, because a
|
||||
First run:
|
||||
|
||||
```
|
||||
$ pnpm dev
|
||||
[od] daemon starting on :7431
|
||||
$ pnpm dev:all
|
||||
[od] daemon starting on :7456
|
||||
[od] detecting agents…
|
||||
[od] ✓ claude-code v0.6.3 (auth: ok, skills dir linked)
|
||||
[od] ✓ codex v0.8.1 (auth: ok)
|
||||
@@ -248,7 +248,7 @@ The daemon never grants more authority to an agent than it had on its own. We do
|
||||
## 11. Adapter source layout
|
||||
|
||||
```
|
||||
apps/daemon/src/adapters/
|
||||
apps/daemon/
|
||||
├── base.ts # shared interface + utility helpers
|
||||
├── claude-code/
|
||||
│ ├── adapter.ts
|
||||
|
||||
+24
-27
@@ -22,7 +22,7 @@ OD is a web app plus a local daemon. The split means the same UI can run in thre
|
||||
│ │
|
||||
│ browser ──► Next.js dev server (localhost:3000) │
|
||||
│ │ │
|
||||
│ │ ws://localhost:7431 │
|
||||
│ │ http://localhost:7456 │
|
||||
│ ▼ │
|
||||
│ od daemon (Node, long-running) │
|
||||
│ │ │
|
||||
@@ -31,7 +31,7 @@ OD is a web app plus a local daemon. The split means the same UI can run in thre
|
||||
└────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
One `pnpm dev` starts both the Next.js app and the daemon (via a predev script). Zero config. No accounts.
|
||||
One `pnpm dev:all` starts both the Next.js app and the daemon. Zero config. No accounts.
|
||||
|
||||
### Topology B — Web on Vercel + daemon on user's machine
|
||||
|
||||
@@ -74,7 +74,7 @@ The three topologies share the same web bundle; the difference is which transpor
|
||||
│ └─────────── session bus (in-memory) ──────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ Transport layer (ws-rpc | http-direct | indexeddb) │
|
||||
│ Transport layer (daemon SSE | api-direct | browser) │
|
||||
└─────────────────────────┬───────────────────────────────────────────┘
|
||||
│
|
||||
┌───────────────────────┴────────────────────────────────┐
|
||||
@@ -96,16 +96,16 @@ The three topologies share the same web bundle; the difference is which transpor
|
||||
│ cursor-agent │ │ skills/ │
|
||||
│ gemini │ │ DESIGN.md │
|
||||
│ opencode │ └──────────────┘
|
||||
│ openclaw │
|
||||
│ qwen │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
## 3. Key components
|
||||
|
||||
### 3.1 Web app (Next.js 15, App Router)
|
||||
### 3.1 Web app (Next.js 16, App Router)
|
||||
|
||||
- **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.
|
||||
- **State:** React/browser state for UI config, with projects/conversations/files hydrated from the daemon APIs.
|
||||
- **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-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.
|
||||
@@ -114,13 +114,13 @@ The three topologies share the same web bundle; the difference is which transpor
|
||||
|
||||
Single binary via `pkg` or a thin Node script distributed over npm. Responsibilities:
|
||||
|
||||
- Listen on `ws://localhost:7431` (configurable). Accept JSON-RPC-over-WebSocket.
|
||||
- Listen on `http://localhost:7456` by default. Accept REST/SSE routes under `/api/*`.
|
||||
- Maintain a **session** per web tab. Sessions hold: active agent, active skill, active artifact, in-flight tool calls, design-system reference.
|
||||
- Operate the **agent adapter pool**: one detected CLI = one adapter instance, reused across sessions.
|
||||
- Scan and index **skills** from `~/.claude/skills/`, `./skills/`, `./.claude/skills/` on startup and on FS-watch events.
|
||||
- Own the **artifact store** — writes files to disk, never in memory.
|
||||
- Run the **preview compile pipeline** (Babel transform for JSX, CSS inliner for HTML exports).
|
||||
- Spawn headless Chromium via Puppeteer for **PDF export**. PPTX via `pptxgenjs`.
|
||||
- Provide export hooks for HTML/PDF/ZIP and skill-defined deck outputs.
|
||||
|
||||
### 3.3 Agent adapter pool
|
||||
|
||||
@@ -252,24 +252,21 @@ All config is plain text / TOML / JSON — no binary formats, no sqlite. Reviewa
|
||||
|
||||
## 7. Protocol between web and daemon
|
||||
|
||||
JSON-RPC 2.0 over WebSocket. Why not REST? Because we need streaming. Why not gRPC? Over-engineering for a single-origin local app.
|
||||
The shipped daemon uses HTTP routes plus Server-Sent Events for streaming chat output. This keeps the browser on the same `/api/*` surface in dev and production while still allowing incremental agent output.
|
||||
|
||||
Methods (MVP):
|
||||
Representative API surface:
|
||||
|
||||
```
|
||||
session.open(params) -> { sessionId }
|
||||
session.generate(params) -> streams: tool_call | text_delta | artifact_update | done
|
||||
session.refine(params) -> streams: same
|
||||
session.cancel(params) -> { ok }
|
||||
agents.list() -> [{ id, name, version, capabilities }]
|
||||
agents.setActive({ agentId }) -> { ok }
|
||||
skills.list() -> [{ id, name, mode, manifest }]
|
||||
skills.setActive({ sessionId, skillId }) -> { ok }
|
||||
skills.install({ source }) -> streams: progress
|
||||
design.setActive({ path }) -> { designSystem }
|
||||
artifacts.list({ projectRoot }) -> [Artifact]
|
||||
artifacts.get({ id }) -> Artifact
|
||||
artifacts.export({ id, format }) -> streams: progress | { url | path }
|
||||
GET /api/health
|
||||
GET /api/agents
|
||||
GET /api/skills
|
||||
GET /api/design-systems
|
||||
GET /api/projects
|
||||
POST /api/projects
|
||||
GET /api/projects/:id/files
|
||||
POST /api/projects/:id/upload
|
||||
POST /api/chat -> text/event-stream
|
||||
POST /api/artifacts/save
|
||||
```
|
||||
|
||||
Full schema in [`schemas/protocol.md`](schemas/protocol.md) (TODO: write).
|
||||
@@ -279,7 +276,7 @@ Full schema in [`schemas/protocol.md`](schemas/protocol.md) (TODO: write).
|
||||
### Local
|
||||
```sh
|
||||
pnpm install
|
||||
pnpm dev # starts daemon on :7431, next on :3000
|
||||
pnpm dev:all # starts daemon on :7456, next on :3000
|
||||
```
|
||||
|
||||
### Docker
|
||||
@@ -289,11 +286,11 @@ services:
|
||||
daemon:
|
||||
image: openclaudedesign/daemon
|
||||
volumes: [ "~/.open-design:/root/.open-design", "./:/workspace" ]
|
||||
ports: ["7431:7431"]
|
||||
ports: ["7456:7456"]
|
||||
web:
|
||||
image: openclaudedesign/web
|
||||
ports: ["3000:3000"]
|
||||
environment: [ "OD_DAEMON_URL=ws://daemon:7431" ]
|
||||
environment: [ "OD_DAEMON_URL=http://daemon:7456" ]
|
||||
```
|
||||
|
||||
### Vercel + local daemon (Topology B)
|
||||
@@ -313,7 +310,7 @@ vercel deploy # same bundle
|
||||
|
||||
| Surface | Threat | Mitigation |
|
||||
|---|---|---|
|
||||
| Daemon WebSocket | Arbitrary local process talks to daemon | Token handshake; token printed on `od daemon` start, required in WS URL |
|
||||
| Daemon HTTP/SSE API | Arbitrary local process talks to daemon | Bind to localhost by default; add auth/tunnel hardening before exposing beyond the machine |
|
||||
| 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 OD's own servers (we don't have any) |
|
||||
|
||||
+7
-7
@@ -14,7 +14,7 @@ Phased plan from "spec-only today" to "usable MVP" to "published v1." All estima
|
||||
- [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 `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/protocol.md` — HTTP/SSE API schemas
|
||||
- [ ] `docs/schemas/adapter.md` — adapter interface in TypeScript, printed out
|
||||
- [ ] `docs/examples/DESIGN.sample.md` — a working example design system
|
||||
- [ ] `docs/examples/saas-landing-skill/` — a working example skill (the one sketched in `skills-protocol.md` §8)
|
||||
@@ -31,12 +31,12 @@ Phased plan from "spec-only today" to "usable MVP" to "published v1." All estima
|
||||
### Scope
|
||||
|
||||
**Included:**
|
||||
- Web app (Next.js 15, App Router)
|
||||
- Web app (Next.js 16, App Router)
|
||||
- chat pane · artifact tree · sandboxed iframe preview · export menu
|
||||
- skill picker · mode picker · design-system picker
|
||||
- **no** comment mode yet · **no** sliders yet · **no** template gallery UI yet
|
||||
- Local daemon (Node)
|
||||
- JSON-RPC over WebSocket on `:7431`
|
||||
- HTTP/SSE API on `:7456`
|
||||
- agent detection + cached results
|
||||
- skill registry (scan three dirs, hot-reload)
|
||||
- artifact store (plain files + `history.jsonl`)
|
||||
@@ -72,18 +72,18 @@ Phased plan from "spec-only today" to "usable MVP" to "published v1." All estima
|
||||
|
||||
| Week | Theme | Concrete deliverables |
|
||||
|---|---|---|
|
||||
| 1 | Scaffolding | monorepo (pnpm workspaces: `apps/web`, `apps/daemon`, `packages/shared`); Next.js 15 base; daemon CLI skeleton; CI green |
|
||||
| 2 | Daemon core | JSON-RPC over WS; session manager; skill registry scanning; artifact store (write files + `history.jsonl`); design-system resolver loading `./DESIGN.md` |
|
||||
| 1 | Scaffolding | pnpm workspaces (`apps/web`, `apps/daemon`, `e2e`); Next.js 16 base; daemon CLI skeleton; CI green |
|
||||
| 2 | Daemon core | HTTP/SSE API; project/conversation store; skill registry scanning; artifact store; design-system resolver loading `DESIGN.md` |
|
||||
| 3 | Claude Code adapter | detection (PATH + `~/.claude/` probe); spawn with `--output-format stream-json`; parser from JSON-lines → `AgentEvent`; streaming to daemon's session; cancel via SIGTERM |
|
||||
| 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 |
|
||||
| 5 | Web UI — chat + file workspace | React state + daemon-backed project store; SSE client; chat pane; file workspace reflects project files; 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 `od:` extension block); write `saas-landing` skill; write 1–2 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
|
||||
|
||||
1. `pnpm install && pnpm dev` works on clean macOS and Linux.
|
||||
1. `corepack enable && pnpm install && pnpm dev:all` works on clean macOS and Linux with Node 24.
|
||||
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.
|
||||
|
||||
+4
-4
@@ -29,7 +29,7 @@ Other docs:
|
||||
|
||||
| # | 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` |
|
||||
| 1 | Where the product runs | claude.ai only | Local Electron app | **Next.js web app + local daemon** — `pnpm dev:all`, Vercel web deploy, or single-process daemon serving the built web app |
|
||||
| 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 |
|
||||
| 3 | What "design skills" are | Proprietary internal tools | TypeScript modules baked into the app | **File-based skills** that follow Claude Code's `SKILL.md` spec — forkable, versionable, shareable, installable by symlink |
|
||||
| 4 | How design systems are authored | Implicit in prompt | N/A | **`DESIGN.md` files** following the [awesome-claude-design][acd] 9-section schema |
|
||||
@@ -67,7 +67,7 @@ These four scenarios map 1:1 to the four modes in [`modes.md`](modes.md).
|
||||
│ Web App (Next.js) │
|
||||
│ chat · artifact tree · iframe preview · comment mode · exports │
|
||||
└────────────┬─────────────────────────────────┬───────────────────┘
|
||||
│ WebSocket (JSON-RPC) │ HTTPS (BYOK direct)
|
||||
│ HTTP + SSE (/api/chat) │ HTTPS (BYOK direct)
|
||||
┌────────────▼──────────────────┐ ┌────────▼─────────────────┐
|
||||
│ Local Daemon (od daemon) │ │ Anthropic Messages API │
|
||||
│ · agent detection │ │ (fallback when no CLI) │
|
||||
@@ -85,7 +85,7 @@ These four scenarios map 1:1 to the four modes in [`modes.md`](modes.md).
|
||||
Module responsibilities:
|
||||
|
||||
- **Web app** — chat UI, artifact tree, sandboxed iframe preview, comment mode, slider controls, export UI. Stateless; all state lives in the daemon or in the browser's IndexedDB for cloud deploys.
|
||||
- **Daemon** — long-running local process. Detects agents, registers skills, manages artifacts on disk, resolves the active design system, and brokers WebSocket sessions.
|
||||
- **Daemon** — long-running local process. Detects agents, registers skills, manages artifacts on disk, resolves the active design system, and brokers REST/SSE requests.
|
||||
- **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 `./.od/`) holding generated files, version snapshots (git-friendly), and per-artifact metadata.
|
||||
@@ -126,7 +126,7 @@ 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.
|
||||
- One developer can `git clone && corepack enable && pnpm install && pnpm dev:all`, 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 `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).
|
||||
|
||||
Reference in New Issue
Block a user