Modular, open desktop PCB design suite β schematic capture, PCB layout, and a unified component library in one app.
OpenPCB is a desktop application that lets electronics designers go from idea β schematic β PCB β fabrication-ready output in a single, modular workspace. It is built on a module-runtime architecture: each vertical slice (library, designer, tasks, assistant) ships its own backend routes, frontend Space, DB schema, and migrations, and is loaded dynamically at boot through a typed SDK registry.
Status: pre-1.0, active development. Phases 1β3 of the rewrite are complete; PCB layout (Phase 4) is partially shipped (trace routing, vias, layer switching, live DRC, ratsnest).
- Schematic capture β symbol placement, Manhattan wire routing, net labels, junctions, net extraction, ERC scaffolding, full undo/redo.
- PCB layout β trace routing (Manhattan + 45Β°), via placement with layer switch, pad rendering, MST ratsnest, board outline, component placement, live DRC, IPC-2221B-aware net classes.
- Component library β symbols, footprints (IPC-7351B preset generator + drawn editor), variants, KiCad
.kicad_sym/.kicad_modimport, built-in seeded components. - R3F-based canvas β single React Three Fiber orthographic renderer with demand rendering, shared by all editors; nm β mm β px coordinate pipeline.
- Command + ECS core β every mutation is a
CommandEnvelopewith idempotency, base-revision check, inverse patches, persisted per-session history. - Module runtime β kebab-case manifest, topological boot, per-module SQLite prefix, auto-applied SQL migrations, codegenerated SDK + module registry.
- AI Assistant module (dev) β OpenAI / Ollama / LM Studio providers, read-only tools today, write-tool scaffolding behind confirm/reject.
- Cross-platform desktop β Electron 41 shell, embedded backend in main process, auto-update via
electron-updater, signed/notarized builds in CI for macOS arm64/x64, Windows x64, Linux x64.
Screenshots are intentionally omitted in this repo β open the app to see the schematic editor, PCB canvas, and library palette.
| Layer | Choice |
|---|---|
| Desktop | Electron 41 (embedded backend in main process) |
| Backend | Bun HTTP server, RFC 7807 problem-details, JSON structured logging |
| Database | SQLite via better-sqlite3 + Drizzle ORM, per-module table prefixes |
| Frontend | React 19, Vite 7, Tailwind 4, Zustand 5, Radix UI, Lucide icons |
| Rendering | React Three Fiber + three.js, orthographic + demand rendering |
| Geometry | polygon-clipping, custom Manhattan / 45Β° routers, MST ratsnest |
| 3D import | occt-import-js (STEP), background ZIP+STEP conversion |
| Tests | Bun Test (backend), Vitest 4 (frontend), Playwright (e2e) |
| Observability | Sentry (@sentry/electron, @sentry/react, @sentry/node) |
| Packaging | electron-builder β dmg/zip (mac), Setup.exe + nupkg (win), deb/rpm/AppImage (linux) |
OpenPCB enforces strict one-way layer dependencies:
electron/ ββspawnsβββΊ core/backend (in-process)
β
modules/* ββββββββββΊ sdks/* ββββββββββΊ shared/* ββββββββββΊ core/*
| Layer | Responsibility |
|---|---|
core/ |
Pure infrastructure: HTTP server, router, module loader, DB factory, errors. Zero business logic. |
shared/ |
ECS world, command/patch infrastructure, canvas engine, geometry, UI primitives. |
sdks/ |
Pure inter-module contracts (@sdks/library, @sdks/designer, β¦) β types only. |
modules/* |
Self-contained vertical slices: manifest + backend + frontend + migrations + domain. |
electron/ |
Thin OS shell: windows, IPC, updater, lifecycle. |
| Module | Kind | Depends on | Status |
|---|---|---|---|
library |
space | β | symbols, footprints, KiCad import, seeding |
designer |
space | library |
schematic β , PCB layout π§ (phase 4) |
tasks |
tool | β | persisted runtime, SSE, hidden sidebar |
assistant |
space | tasks |
dev-only, OpenAI/Ollama/LM Studio |
CommandEnvelope
β idempotency check (command log)
β load DesignWorld (ECS)
β validate baseRevision
β command-bus dispatch
β handler plans patches
β apply + persist
β publish invalidation
β CommandResult (with inverse patch for undo)
Reads go through SchematicProjection (projection-read.ts, projection-world.ts). PCB placements are auto-synced from schematic changes. See docs/COMMAND_PATTERN.md, docs/DATA_MODEL.md, docs/PROPOSED_ARCHITECTURE.md.
- Public URL:
/api/modules/{moduleId}/{subpath} - Core routes:
GET /api/health,GET /api/diagnostics,GET /api/modules/registry - Errors use
application/problem+json(RFC 7807) withhttps://openpcb.dev/problems/*types.
src/
βββ core/
β βββ backend/ Bun HTTP runtime, module loader, router, DB (own workspace)
β βββ frontend/ React 19 + Vite 7 + Tailwind 4 (own workspace)
β βββ contracts/ app/* + modules/* type contracts
βββ modules/
β βββ library/ components, symbols, footprints, KiCad import
β βββ designer/ schematic + PCB editor (commands, history, projection, pcb/)
β βββ tasks/ task tracking + SSE
β βββ assistant/ AI assistant (dev)
βββ sdks/ public inter-module contracts
βββ shared/ ECS, commands, canvas engine, rendering, UI primitives
electron/ Electron main + preload + embedded backend manager
scripts/ module CLI, codegen, sourcemap upload
docs/ architecture + command-pattern + data-model
tests/e2e/ Playwright
Requirements: Node 20+, npm 10.9+, Bun β₯ 1.3 (backend runtime/tests).
git clone https://github.com/andrejvysny/OpenPCB.git
cd OpenPCB
npm installnpm run dev
# backend β http://127.0.0.1:3000
# frontend β http://127.0.0.1:1420 (proxies /api and /ws β 3000)npm run dev:electron # alias: dev:desktopPlace CoreLibrary beside this checkout, install its Bun deps once, then use
the dev CoreLibrary scripts:
cd ../CoreLibrary && bun install && bun run validate
cd ../OpenPCB
npm run dev:corelib # browser dev, packs ../CoreLibrary first
npm run dev:electron:corelib # desktop dev, packs ../CoreLibrary firstThe local package is built as 999.0.0-dev in ../CoreLibrary/dist and is
preferred only in development. Release/package builds still use fetched/bundled
.opclib resources.
npm run build # frontend bundle + electron-builder make for current OS
# Per-OS in electron workspace:
npm run make:mac --workspace electron
npm run make:win --workspace electron
npm run make:linux --workspace electronCI builds and publishes artifacts (dmg/zip, Setup.exe/nupkg/RELEASES, deb/rpm/AppImage) on v* tags via .github/workflows/release-electron.yml.
| Command | What it does |
|---|---|
npm run dev |
Backend + Vite (browser mode) |
npm run dev:electron |
Vite + Electron shell with embedded backend |
npm run dev:corelib |
Pack ../CoreLibrary, then run browser dev |
npm run dev:electron:corelib |
Pack ../CoreLibrary, then run Electron dev |
npm run dev:backend |
Bun backend only (--watch, port 3000) |
npm run dev:frontend |
Vite dev server only (port 1420) |
npm run dev:browser |
Backend + Playwright UI runner |
npm run build |
Frontend bundle + electron-builder make |
npm run typecheck |
Composite tsc -b over backend/frontend/modules |
npm run test:backend |
Bun test suite (src/core/backend) |
npm run test:react |
Vitest (src/core/frontend) |
npm run test:e2e |
Playwright e2e |
npm run module |
Interactive module CLI |
npm run module:create |
Scaffold a new module |
npm run module:validate |
Validate all module manifests |
npm run modules:generate |
Codegen module registry β frontend/src/generated/modules.ts |
npm run sdk:generate |
Codegen SDK barrels β frontend/src/generated/sdk/ |
npm run gen / gen:check |
Run codegen / fail if generated files are dirty |
npm run db:generate |
drizzle-kit generate |
npm run db:studio |
drizzle-kit studio |
npm run release:sourcemaps |
Upload sourcemaps post-release |
Single-file test runs:
cd src/core/backend && bun test tests/<file>.test.ts
cd src/core/frontend && npx vitest run path/to/file.test.tsx| Variable | Default | Purpose |
|---|---|---|
PORT |
3000 |
Backend port |
HOST |
127.0.0.1 |
Backend bind address |
OPENPCB_DB_PATH |
dev-data/openpcb.sqlite (dev) |
SQLite path (prod: ~/.openpcb/data.sqlite) |
OPENPCB_WORKSPACE_ROOT |
derived | Module discovery root (defaults to repo src/) |
OPENPCB_ALLOWED_ORIGINS |
localhost:1420, :3000, tauri | Comma-separated CORS origins |
OPENPCB_DEBUG_DIAGNOSTICS |
false |
Enables /api/diagnostics/debug/modules |
NODE_ENV |
β | development / test |
npm run module:create # interactive scaffolder
npm run modules:validate # validates all manifests
npm run gen # regenerate module + sdk indexesEach module needs:
src/modules/<id>/
βββ manifest.json # id, namespace, apiVersion: 2, sidebar, dependsOn
βββ module.backend.ts # exports ModuleDefinition (default|definition|backendModule)
βββ module.frontend.ts # exports { manifest, Space }
βββ backend/
β βββ migrations/0000_*.sql # auto-applied on boot, transactional, tracked in openpcb_migrations
β βββ routes.ts
βββ frontend/Space.tsx
Module routes are mounted under /api/modules/{id}/.... SDKs are registered against tokens in src/sdks/index.ts and consumed via the RuntimeSdkRegistry.
@modules/*βsrc/modules/*@sdks/*βsrc/sdks/*@shared/*βsrc/shared/*@/*βsrc/core/frontend/src/*(frontend only)
- Backend won't boot β check
OPENPCB_DB_PATHis writable; module SQL migrations run transactionally on startup. See/api/diagnostics. - Module not appearing β re-run
npm run gen; confirmmanifest.jsonapiVersion: 2and uniqueid; check topological order in logs. - Stuck STEP/3D conversion β import commits first, conversion runs in background; use the Library 3D preview retry control.
- macOS "developer cannot be verified" beta β see
electron/README-BETA-INSTALL.md.
OpenPCB is dual-licensed:
- AGPL-3.0-or-later for community / open-source use. See
LICENSEfor the full text. - Commercial license available for organizations that cannot meet AGPL's source-disclosure obligations or who want a license without copyleft requirements. See
LICENSE-COMMERCIAL.mdβ contactlicensing@openpcb.app.
- Binaries in
v0.1.x-betaare unsigned. macOS Gatekeeper and Windows SmartScreen will warn β seeelectron/README-BETA-INSTALL.md. - Linux AppImage needs
chmod +xafter download. electron-updateris wired but the update feed is not live yet; install new versions manually.
See CONTRIBUTING.md for setup, conventions, and the pre-PR checklist. By contributing you agree to license your contributions under AGPL-3.0-or-later.
For architecture-shaping changes, open an issue first.