OpenDiagram — open-source AI workspace for software architecture. Design systems with natural language, generate diagrams, document decisions, iterate with AI.
This is NOT the Next.js you know. Next.js 16 has breaking changes — APIs, conventions, and file structure may differ from older versions. Read guides in node_modules/next/dist/docs/ before writing code. Heed deprecation notices.
- Runtime/PM: Bun 1.3
- Frontend: Next.js 16 + React 19 + TypeScript
- Backend: Hono (Bun)
- Database: PostgreSQL (supabase) (via packages/db)
- Auth: Better Auth
- AI: Provider agnostic (OpenRouter, Anthropic, OpenAI, etc.)
- Type checking: tsgo (Go-native TS compiler,
@typescript/native-preview) - Linting: oxlint + oxfmt
- Task runner: Turbo (orchestration) + Just (dev shortcuts)
apps/
web/ # Next.js 16 frontend (port 3001)
server/ # Hono API server (port 3000, bun --hot)
fumadocs/ # Documentation site (port 4000)
packages/
auth/ # Better Auth config
config/ # Shared config
db/ # Database schema + migrations
env/ # Environment variable validation
harness/ # Diagram engine: schema, layout, renderer
# Dev
bun run dev # All services via turbo
bun run dev:web # Web only
bun run dev:server # Server only
# Build
bun run build # All packages via turbo
# Type check (tsgo)
bun run check-types # All packages via turbo
just types # Same, via justfile
# Lint + format
just check # oxlint + oxfmt --write
# Database
just db-generate <name> # Generate a migration from schema changes
just db-migrate # Apply pending migrations
just db-seed # Apply plan limits from packages/db/src/seed.ts
just db-seed --dry-run # Preview what db-seed would change
just db-setup # migrate + seed, in that order (a fresh DB needs both)
# Cleanup
just clean # Nuke node_modules, .turbo, .next, dist
just reinstall # clean + bun install- Use
@/path alias forapps/web/src/. catalog:is for deps used by two or more workspace packages: version goes in the rootpackage.jsoncatalog, every consumer writescatalog:.- Always install packages with
bun add— never manually add to package.json. - Workspace deps use
workspace:*. - Follow existing patterns in adjacent files.
- oxlint enforces style — don't duplicate lint rules in instructions.
- Interactive controls must visibly behave as interactive: buttons, clickable links, role-button elements, and enabled form controls should show
cursor: pointeron hover/focusable pointer use. Prefer the global stylesheet default; only override for disabled/loading states such ascursor-waitorcursor-not-allowed. - Organize components by scope:
components/— shared, reusable (button, card, input, etc.)components/<feature>/— page-specific (e.g.,components/dashboard/,components/auth/)
The diagram engine. Full docs: packages/harness/README.md. Non-negotiables:
- LLM never chooses pixels/colors/fonts. It emits a semantic
DiagramSpec; layout (ELK / sequence grid) + themed renderer own all geometry and styling. Don't add visual fields to the spec. - Sizing and rendering must agree:
measure.ts#nodeSizereserves the box the renderer draws into — change both branches together. - Edge routes are drawn verbatim. Labels are measured against ELK's exact polyline; never reroute after layout. Excalidraw
elbowedarrows don't work via programmatic insert. - No
@excalidraw/excalidrawimports inside the harness (browser-only package). Skeleton→element conversion lives inapps/web/src/lib/excalidraw-utils.ts, which must pass fresh elements throughrestoreElements(paint-skip bug otherwise). bun --hotdoes NOT reload harness edits — restartdev:serveror you verify stale code.- Zod spec schema stays Gemini-safe: no
.refine()/.default()/.transform(). Gemini reliably typosfrom1forfromin edges —experimental_repairToolCallinroutes/diagram.tsfixes it deterministically; don't remove it. - Measured negative result:
elk.layered.nodePlacement.strategy: NETWORK_SIMPLEXmakes routing worse — don't re-add. Seefuture.mdfor the improvement roadmap. - After ANY harness change run
bun testinpackages/harness(test/harness.test.ts— geometry smoke suite: sequence fragments, ERD crow-feet, orthogonal routes, column alignment). Extend it when you add pipeline features.
apps/webis the primary frontend with shadcn components insrc/components/.apps/serveris the API layer using Hono with evlog middleware.packages/envprovides typed env vars — import from@OpenDiagram/env/webor@OpenDiagram/env/server.packages/dbhas the database schema — never acquire nested DB connections.
- Never modify files in
node_modules/,.turbo/, or.next/. - Read docs and get latest context about libraries before coding.
- Run
just check&just typesafter finishing a coding session & fix those. - Keep changes surgical — don't refactor adjacent code.
- New dependencies: justify additions. Catalog them only once a second package needs them.
- Always use
bun addto add packages.
Don't assume. Don't hide confusion. Surface tradeoffs.
Before implementing:
- State your assumptions explicitly. If uncertain, ask.
- If multiple interpretations exist, present them — don't pick silently.
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.
- Never guess APIs, method signatures, types, or behavior. Verify first.
- context7 MCP — for well-known libraries (React, Next.js, Hono, etc.)
- Exa MCP (
exa:search/exa:web_fetch_exa) — for obscure packages, platform APIs, blog posts, JS-rendered docs, or specific URLs - Ask the user — if neither source gives a definitive answer
Always use the caveman skill (/caveman) at the start of every conversations to save context tokens.
| Skill | When to use |
|---|---|
/hono |
Hono routes, middleware, validation, streaming |
/shadcn |
Adding/fixing/composing shadcn components |
/better-auth-best-practices |
Auth setup, sessions, plugins, OAuth config |
/supabase-postgres-best-practices |
Postgres queries, schema design, optimization |
/vercel-react-best-practices |
React/Next.js performance, data fetching, bundle optimization |
/vercel-composition-patterns |
React component composition that scales |
/turborepo |
Monorepo task orchestration, pipeline config |
/web-design-guidelines |
UI review, accessibility, UX best practices |
/review-logging-patterns |
Audit evlog adoption, detect console.log spam |
/analyze-logs |
Debug from .evlog/logs/ structured NDJSON events |
/caveman |
Compress output ~75% for long sessions |
- Use Exa MCP (
exa:search/exa:web_fetch_exa) for web research and reading docs. - Use Chrome DevTools MCP (
/chrome-devtools-mcp:chrome-devtools) to interact with the live app for testing and verification. - Use GitHub MCP for all GitHub-related tasks. Fall back to
gh cliif more efficient.
Minimum code that solves the problem. Nothing speculative.
- No features beyond what was asked.
- No abstractions for single-use code.
- No "flexibility" or "configurability" that wasn't requested.
- No error handling for impossible scenarios.
- If you write 200 lines and it could be 50, rewrite it.
Touch only what you must. Clean up only your own mess.
When editing existing code:
- Don't "improve" adjacent code, comments, or formatting.
- Don't refactor things that aren't broken.
- Match existing style, even if you'd do it differently.
- If you notice unrelated dead code, mention it — don't delete it.
When your changes create orphans:
- Remove imports/variables/functions that YOUR changes made unused.
- Don't remove pre-existing dead code unless asked.
The test: Every changed line should trace directly to the user's request.
Define success criteria. Loop until verified.
For multi-step tasks, state a brief plan:
- [Step] → verify: [check]
- [Step] → verify: [check]
- [Step] → verify: [check]
Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.