Skip to content

OpenPCB-app/OpenPCB

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

322 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
OpenPCB

OpenPCB

Modular, open desktop PCB design suite β€” schematic capture, PCB layout, and a unified component library in one app.

version license electron bun react vite tailwind typescript


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

Highlights

  • 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_mod import, 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 CommandEnvelope with 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

Screenshots are intentionally omitted in this repo β€” open the app to see the schematic editor, PCB canvas, and library palette.

Tech stack

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)

Architecture

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.

Active modules

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

Designer command flow

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.

Module HTTP routing

  • 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) with https://openpcb.dev/problems/* types.

Repository layout

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

Quick start

Requirements: Node 20+, npm 10.9+, Bun β‰₯ 1.3 (backend runtime/tests).

git clone https://github.com/andrejvysny/OpenPCB.git
cd OpenPCB
npm install

Run in the browser (dev backend + Vite)

npm run dev
# backend  β†’ http://127.0.0.1:3000
# frontend β†’ http://127.0.0.1:1420  (proxies /api and /ws β†’ 3000)

Run as a desktop app

npm run dev:electron     # alias: dev:desktop

Run with sibling CoreLibrary sources

Place 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 first

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

Build installers

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 electron

CI builds and publishes artifacts (dmg/zip, Setup.exe/nupkg/RELEASES, deb/rpm/AppImage) on v* tags via .github/workflows/release-electron.yml.

Commands reference

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

Environment variables

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

Creating a new module

npm run module:create        # interactive scaffolder
npm run modules:validate     # validates all manifests
npm run gen                  # regenerate module + sdk indexes

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

TypeScript path aliases

  • @modules/* β†’ src/modules/*
  • @sdks/* β†’ src/sdks/*
  • @shared/* β†’ src/shared/*
  • @/* β†’ src/core/frontend/src/* (frontend only)

Troubleshooting

  • Backend won't boot β€” check OPENPCB_DB_PATH is writable; module SQL migrations run transactionally on startup. See /api/diagnostics.
  • Module not appearing β€” re-run npm run gen; confirm manifest.json apiVersion: 2 and unique id; 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.

License

OpenPCB is dual-licensed:

  • AGPL-3.0-or-later for community / open-source use. See LICENSE for 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 β€” contact licensing@openpcb.app.

Known issues on first launch

  • Binaries in v0.1.x-beta are unsigned. macOS Gatekeeper and Windows SmartScreen will warn β€” see electron/README-BETA-INSTALL.md.
  • Linux AppImage needs chmod +x after download.
  • electron-updater is wired but the update feed is not live yet; install new versions manually.

Contributing

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.

Packages

 
 
 

Contributors

Languages