The Problem
Design teams that want to experiment with AI‑assisted graphics need a shared canvas where human edits and AI‑generated changes are visible in real time. Existing SaaS tools hide the collaboration layer behind proprietary back‑ends, making self‑hosting, data‑ownership, and custom agent integration difficult.
What This Does
doop delivers a full‑stack, self‑hostable design board that merges a React front‑end with a Node/TypeScript back‑end and an embedded Postgres (PGlite) store. The UI lives in src/ (e.g., src/components/Board.tsx, src/pages/CanvasPage.tsx) and talks to the server via REST endpoints in server/actions.ts and a WebSocket channel opened by src/lib/ws.ts.
The MCP (Multiplayer Collaboration Protocol) server in server/mcp.ts accepts connections from Claude Code or any MCP client, streams frame updates, and updates the activity feed. All persistence (frames, user accounts, agent status) is handled through the Drizzle ORM defined in server/db/ (index.ts, schema.ts, migrations under migrations/).
How It Is Wired
Entry points
- Front‑end:
src/main.tsx→ renders<App/>(src/App.tsx). - Back‑end:
server/index.ts– creates the HTTP server, mounts API routes (server/actions.ts), and upgrades/wsand/mcpto WebSocket connections.
Control flow (typical user edit)
- Browser loads
index.html→ Vite dev server serves the React bundle. Appmounts,src/lib/api.tscreates an Axios instance targeting/api.- When a user creates or moves a frame,
src/lib/api.tsPOSTs to/api/frames→ handled inserver/actions.ts→ writes via Drizzle (server/db/index.ts). - The API handler emits a broadcast through the WebSocket manager instantiated in
server/index.ts. - All connected clients receive the payload via
src/lib/ws.ts, which updates local React state (src/lib/store.ts) causing the canvas to re‑render.
Agent path
- An MCP client (Claude Code) connects to
/mcp→ handshake managed inserver/mcp.ts. - Agent issues
set_status,create_frame,stream_contentcommands → routed through the same WebSocket manager. - Server validates the agent’s JWT using
server/auth.ts, then persists any new frames through the same Drizzle layer.
Database All reads/writes funnel through server/db/index.ts. In dev mode it opens a PGlite file‑based DB (data/pg). Production can override with a real Postgres via the DATABASE_URL env var (referenced in drizzle.config.ts).
Docker Dockerfile builds a multi‑stage image: stage 1 compiles the Vite client, stage 2 bundles the server (server/index.ts). docker-compose.yml wires the app container to a Postgres service and exposes ports 4300 (client) and 4400 (API/WebSocket). No external services are required to start.
How To Use It
# Clone the exact repo
git clone https://github.com/moses-y/doop && cd doop
# Install deps (npm is defined in package.json)
npm ci
# Development mode (client on :4300, API/WebSocket on :4400)
npm run dev
Optional Docker route
# Generate a secret (required for auth) and start everything
BETTER_AUTH_SECRET=$(openssl rand -hex 32) docker compose up -d
Configuration lives in .env.example. At minimum set AUTH_SECRET (or the BETTER_AUTH_SECRET used above) and, for production, DATABASE_URL. The server reads these via process.env in server/index.ts and server/db/index.ts.
Real‑World Use
A product team runs doop on an internal VM, creates a canvas for a new landing page, and invites a Claude Code agent via the CLI command shown in the README:
claude mcp add --transport http doop http://localhost:4300/mcp
The agent receives the canvas ID, iteratively generates frame content, and the designers watch the updates live, comment in the activity feed, and commit the final frames to the repository.
Code Health & Issues
- Low – No test coverage for server routes – only
tests/access.test.tsexists; many API endpoints lack unit tests. - Low – Secrets not in CI –
.github/workflows/ci.ymlruns without injectingAUTH_SECRET; local dev relies on.env.example. - Low – Dockerfile copies entire repo – could be trimmed to
src/andserver/to reduce image size.
Static analysis reported no missing license (LICENSE present), lockfile (package-lock.json) present, and CI workflow exists, so baseline health is acceptable.
The Bottom Line
doop provides a functional, open‑source alternative to proprietary collaborative design tools, with a clear separation between front‑end, API, and MCP agent layers. It is ready for self‑hosting but would benefit from broader test coverage and tighter Docker image hygiene. Teams comfortable with TypeScript/Node and needing full data control should consider it; casual users may prefer the hosted version at doop.design.