Self-hosted emergence-engineering/pcbjam (browser KiCad WASM) — CMMS embed fork. Upstream tracked as remote "upstream".
  • TypeScript 49.1%
  • C++ 36%
  • Shell 4.2%
  • C 2.9%
  • JavaScript 2.6%
  • Other 5.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Gergő Törcsvári aa26125f61
tests: findings-p1 keyboard rotate — explicit canvas focus, retried hotkey, skip (not fail) when the hotkey cannot reach the tool on the runner
CI web legs (both engines, run 33212413159) selected the footprint but 'r'
never rotated it; the keyboard chain is gated on the kicad harness variant
(green on CI), so an unexercisable precondition here is a skip with a PROBE
line, not a P-1 failure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvvARNMxQrq17vogn3REMU
2026-08-28 23:46:13 +02:00
.claude screenshots: R2-hosted manifest becomes the baseline source of truth (morelli cutover) 2026-08-19 14:35:08 +02:00
.github/workflows findings X-1: pin every dependency tarball fetch to a SHA256 and enforce it 2026-08-28 20:34:16 +02:00
deploy ci: deploy isolated GPL staging stack 2026-08-07 11:52:25 +02:00
docker jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose 2026-08-14 09:25:32 +02:00
docs ysync bug 07 UP side: superseded sheet switch never adopts onto the new screen + apply envelope sheet tag/guard (subsheet self-reference fix) 2026-08-28 18:19:29 +02:00
features feat(site): 🫙 PCBJam landing revisions — branding, accuracy, positioning graphic 2026-06-07 17:14:19 +02:00
kicad@d0afbc4bd3 staging CI green-up: P-1 apply-slot wedge under JSPI, popup P-4 regression, ysync double-seed header, spec fixes 2026-08-28 22:25:21 +02:00
logs Added logs .gitignore. 2026-01-03 13:52:34 +01:00
scripts findings X-1: pin every dependency tarball fetch to a SHA256 and enforce it 2026-08-28 20:34:16 +02:00
site jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose 2026-08-14 09:25:32 +02:00
sourcetrail tooling(sourcetrail): code-graph setup + asyncify allocator-suspend plan 2026-08-11 13:53:01 +02:00
tests tests: findings-p1 keyboard rotate — explicit canvas focus, retried hotkey, skip (not fail) when the hotkey cannot reach the tool on the runner 2026-08-28 23:46:13 +02:00
wasm staging CI green-up: P-1 apply-slot wedge under JSPI, popup P-4 regression, ysync double-seed header, spec fixes 2026-08-28 22:25:21 +02:00
web staging CI green-up: P-1 apply-slot wedge under JSPI, popup P-4 regression, ysync double-seed header, spec fixes 2026-08-28 22:25:21 +02:00
workers/cdn findings R: coverage for the demo-ledger fixes (R-2, R-3, R-4, R-9) — tests only 2026-08-28 13:56:53 +02:00
wxwidgets@a7436d1052 staging CI green-up: P-1 apply-slot wedge under JSPI, popup P-4 regression, ysync double-seed header, spec fixes 2026-08-28 22:25:21 +02:00
.ci-cache-epoch Phase F: restore the doc-19 bounce (footprint chooser dead-app) + regression spec 2026-08-10 10:14:21 +02:00
.dockerignore Add Docker build environment for KiCad WASM 2025-12-08 12:07:01 +01:00
.gitignore findings R: coverage for the demo-ledger fixes (R-2, R-3, R-4, R-9) — tests only 2026-08-28 13:56:53 +02:00
.gitmodules jspi cleanup: remove the asyncify-era residue — dead code, conditionals, pipeline scaffolding, stale prose 2026-08-14 09:25:32 +02:00
CLAUDE.md screenshots: R2-hosted manifest becomes the baseline source of truth (morelli cutover) 2026-08-19 14:35:08 +02:00
LICENSE Add GNU General Public License v3 2026-06-11 12:54:52 +02:00
README.md screenshots: R2-hosted manifest becomes the baseline source of truth (morelli cutover) 2026-08-19 14:35:08 +02:00

KiCad WebAssembly Port

Run KiCad PCBnew in the browser using WebAssembly.

Quick Start

Full Build (KiCad + All Tests)

# 1. Initialize submodules
git submodule update --init --recursive

# 2. Build KiCad WASM (Docker, ~10 min incremental, ~1-2 hours full)
./docker/build.sh

# 3. Build wxWidgets for local testing
./scripts/build-wx-wasm.sh

# 4. Build wxWidgets test apps
./scripts/build-wasm-test.sh

# 5. Run all tests
cd tests && npm install
npm test              # wxWidgets tests (256 tests)
npm run test:kicad    # KiCad tests (2 tests)

wxWidgets Only (No Docker)

# Requires: Node.js 18+ (Emscripten SDK auto-installed on first build)
./scripts/build-wx-wasm.sh
./scripts/build-wasm-test.sh
cd tests && npm install && npm test

Project Structure

kicad-wasm/
├── kicad/                  # KiCad source (git submodule)
├── wxwidgets/              # wxWidgets source (git submodule)
├── wasm/                   # WASM compatibility layer
│   ├── bindings/           # Embind bindings for JavaScript
│   ├── cmake/              # CMake find modules
│   ├── kiplatform/         # Platform abstraction (app, UI, printing)
│   ├── libcontext/         # Coroutine/fiber implementation
│   ├── shims/              # Runtime JavaScript shims
│   └── stubs/              # Stub implementations (libgit2, curl)
├── scripts/                # Build scripts
│   ├── build-wx-wasm.sh   # Build wxWidgets for WASM
│   ├── build-wasm-test.sh          # Build wxWidgets test apps
│   ├── deps/               # Dependency build scripts
│   ├── kicad/              # KiCad build scripts
│   ├── common/             # Shared utilities
│   └── config/             # Build config wrappers
├── docker/                 # Docker build environment
├── tests/                  # Playwright E2E tests
│   ├── e2e/                # Test specs
│   └── apps/               # WASM test applications
├── tools/                  # External tools (local emsdk install)
└── output/                 # Build output (pcbnew.js, pcbnew.wasm)

Feature Branches

Curated design docs and research notes for each feature live in docs/features/<branch-name>/ (committed).

./scripts/create-feature-patches.sh [branch-name] generates per-branch patches (root.patch, kicad.patch, wxwidgets.patch) into a local features/<branch-name>/ scratch dir. That dir is gitignored — the patches are local history, not committed.

Two Build Workflows

1. KiCad Build (Docker)

Full KiCad PCBnew build using Docker:

# Build KiCad WASM
./docker/build.sh

# Copy output to test directory
./tests/scripts/setup-kicad-wasm.sh

# Run KiCad tests
cd tests && npm install && npm run test:kicad

Output: output/pcbnew.js, output/pcbnew.wasm

See docs/build.md for detailed build documentation.

Creating an isolated worktree (with submodule branches)

For an experiment or feature you can work in a disposable git worktree so the main checkout stays pristine. This repo has three submodules (kicad, wxwidgets, web/pcbjam-shared); a new worktree starts with them empty, so initialize and branch each one:

# 1. Create the worktree on a new branch (off main), at a sibling path
git worktree add -b experiment/my-thing ../kicad-wasm-my-thing main

# 2. Check out the submodules INSIDE the worktree (working trees only;
#    git objects are shared with the main checkout)
cd ../kicad-wasm-my-thing
git submodule update --init kicad wxwidgets web/pcbjam-shared

# 3. Create a matching branch in each submodule (they start at detached HEAD)
git checkout -b experiment/my-thing                 # root already on it via -b above
for sm in kicad wxwidgets web/pcbjam-shared; do
  git -C "$sm" checkout -b experiment/my-thing
done

Then build from inside the worktree. Use an isolated Docker project — do NOT set COMPOSE_PROJECT_NAME to another branch's project (e.g. kicad-wasm-main), which can collide with other workflows; docker/build.sh auto-derives an isolated project name from the worktree branch. The first build provisions deps (wxWidgets + OCC) from scratch. To keep the machine responsive, cap parallelism:

KICAD_DOCKER_CPUS=4 ./docker/build.sh pcbnew -j 4

Tear down afterward with git worktree remove ../kicad-wasm-my-thing (and docker compose -p <project> down -v to drop the isolated volumes).

Fresh worktree provisioning

Some test artifacts are gitignored and are NOT produced by the build pipeline, so they don't carry into a newly-created git worktree — without them the gal-webgl tests 404 ("Loading WASM...") and the collab specs fail with Could not resolve "@pcbjam/shared". After building (docker/build.sh + scripts/build-wx-wasm.sh) and cd tests && npm i, run once per worktree:

./scripts/setup-worktree.sh   # idempotent: sysroot headers, gal-webgl harness, web/ pnpm install, collab bundle

2. wxWidgets Test Apps (Local)

Build standalone wxWidgets test apps for feature testing:

# Build wxWidgets for WASM
./scripts/build-wx-wasm.sh

# Build test apps
./scripts/build-wasm-test.sh

# Run wxWidgets tests
cd tests && npm install && npm test

Output: tests/apps/standalone/

Prerequisites

For KiCad Build (Docker)

  • Docker Desktop with 16GB+ RAM allocated
  • 10+ GB disk space for build cache

For wxWidgets Build (Local)

  • Node.js 18+ (for tests)
  • Emscripten SDK (auto-installed on first build)
# Initialize submodules
git submodule update --init --recursive

# Install Emscripten SDK (auto-runs on first build, or run manually)
./scripts/setup-emsdk.sh

Testing

cd tests
npm install

# Run all tests
npm test

# Run specific tests
npm run test:kicad          # KiCad tests only
npx playwright test menu    # Menu tests only

See tests/README.md for test documentation.

Screenshots

CI's Linux render is the source of truth for baseline screenshots. On each main push, CI compares its render against the baselines (pinned by the R2-hosted manifest — nothing screenshot-related is committed) and posts the diff (plus the runtime-perf numbers) to Discord. To update baselines after an intended render change, promote the CI run's screenshots in the morelli review app (https://pcbjam-morelli-staging.pcbjam-staging.workers.dev) — pick the run, review the diffs, bulk-select, Promote. CI uploads every run's renders to R2 for that purpose (30-day retention).

cd tests
npm run screenshots:fetch-manifest && npm run screenshots:fetch   # materialize baselines
npm run screenshots:check                                         # local gate: current vs baselines

See tests/tools/screenshots/README.md.

Current Status

  • wxWidgets WASM: Core widgets working (menus, dialogs, grids, trees, OpenGL)
  • KiCad PCBnew: Builds and loads in browser, canvas rendering working
  • In Progress: Testing wxWidgets features used by KiCad

Documentation

See docs/README.md for the full documentation map. Highlights:

Landing page / website

The marketing site and landing page live in site/ (Astro), deployed as static assets to Cloudflare R2.

On every release, bump the build SHA. site/src/components/Footer.astro has a hardcoded BUILD_SHA constant that is shown in the footer and links to the corresponding commit. Because the main-repo commit pins the KiCad and wxWidgets submodule revisions implicitly, this is our GPLv3 corresponding-source pointer (surfaced on /licenses). The site is static, so nothing sets it automatically — update BUILD_SHA by hand to the deployed pcbjam commit each time you release.

License

KiCad is GPL-3.0. This project follows the same license.

The site combines KiCad (GPLv3) with the wxWidgets fork; the wxWidgets WebAssembly port files are LGPL v2 (without the wxWindows binary exception). See the /licenses page (site/src/content/legal/licenses.md) for the full breakdown and the corresponding-source offer.