pcbjam/web
Repository files (latest commit first)
Filename Latest commit message Latest commit date
AI_Assistant bf1e7a512e
Some checks failed
wasm-build.yml / cmms-embed: kicad AI chat editor-buffer bridge (PCBJam Part 2) (push) Failing after 0s
wasm-build.yml / cmms-embed: kicad AI chat editor-buffer bridge (PCBJam Part 2) (release) Failing after 0s
release / meta (push) Has been cancelled
release / build (push) Has been cancelled
release / publish-wasm (push) Has been cancelled
release / deploy-demo (push) Has been cancelled
release / deploy-editor (push) Has been cancelled
release / Build all tools + KiCad e2e (Ubicloud) (push) Has been cancelled
cmms-embed: kicad AI chat editor-buffer bridge (PCBJam Part 2)
web/standalone only, no C++/wasm/shared changes:

- lib/cmms-config.ts (new): fetch /api/cmms-config once on boot
  (dark, aiEnabled, aiEditorKind, csrfToken, entityType, entityId).
  Absent route / non-2xx / malformed JSON all mean "no widget" - never
  throws, never blocks boot. Same API base + credentials:"include" as
  the existing /api/me call.
- components/CmmsAiWidget.tsx (new): floating launcher + panel, inert
  unless aiEnabled. Mounted once in App.tsx alongside VersionBadge.
  Mirrors render_ai_assistant_editor_embed()'s markup/CSS shape
  (position, colors) but fixed-position - the draggable/resizable
  geometry system is CMMS-side static JS this bundle can't import.
  Follows `dark` from the config fetch, belt-and-braces alongside the
  existing `?theme=` hand-off (which already wins whenever set).
- wasm/collab/ai-bridge.ts (new): the cmms-ai-editor-* postMessage
  protocol (same shape as the cad-editor / pcb-retrace bridges).
  get-buffer: yToDoc + docToFile on the active sheet's live Y.Doc
  (read-only, reflects in-progress edits including a peer's - not
  last-saved-to-MEMFS). apply: docDelta + applyDeltaToY, treating the
  AI's proposed file as though a peer had made the edit, through the
  same item-observer path every real co-edit already takes - NOT a
  reuse of KicadBinding.seed(), which is a boot-time/reconnect-only
  function (three branches, each with its own empty/hollow-doc edge
  cases) that doesn't have a branch for "live populated doc gets
  replaced with unrelated content", and this subsystem's git history
  (sibling-restage, paste-collision, ysync 0001-0008) is almost
  entirely bugfixes in exactly that state-transition space.
- WasmTool.tsx: registerActiveCollabDoc(doc, filePath) mirrored onto
  each of the three existing setPanelDoc(...) call sites (single-room
  collabHandle, multi-sheet onActiveChange, teardown) - reuses the
  existing "which doc does the SheetPanel show right now" signal
  rather than adding new state.

Known gaps, flagged not silently skipped:
- docDelta only diffs items, not layout/preamble (page size, title
  block) - matches its own doc comment; an AI edit to those won't
  apply. Items (symbols/footprints/wires) are the expected AI edit
  surface for now.
- No client-side read-only-viewer gate on apply - a tab opened as a
  read-only viewer has no local-edit path, but this pushes the AI's
  delta into the Y.Doc the same as a remote peer would, which a
  viewer's binding was never checked against. Write authorization is
  expected to live server-side (the AI tool implementation deciding
  whether to call write_editor_buffer at all, matching the
  cad_generation_enabled gate on the cad-editor bridge) - worth an
  explicit look before this ships broadly.

Verified: tsc --noEmit clean, vitest run 469/469 passing, vite build
succeeds. No kicad/wxwidgets changes - the existing wasm/ build
(vendor-766e2f4-20260904-r4-debug) is unaffected; this is a dist-only
release.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 20:21:17 +10:00
..
backend comments-ux: figma bubble pins, floating panel, seen/reactions/mentions UI, theme follow (0001 A–E + 0002) 2026-07-24 13:21:22 +02:00
pcbjam-shared@a4984c626d collab: paste-collision sync-delete fix — lenient sibling restage, forced removals for deleted dirty roots, eeschema child-blob lifting 2026-08-31 12:50:12 +02:00
standalone cmms-embed: kicad AI chat editor-buffer bridge (PCBJam Part 2) 2026-09-05 20:21:17 +10:00
.env.example feat(editor): report uncaught errors to Better Stack 2026-08-03 12:24:30 +02:00
.gitignore feat(libs): eeschema symbol-chooser footprint selector + preview via publish-time fp-index 2026-07-07 21:09:21 +02:00
package.json chore: add dev:demo script (web) + refresh site lockfile 2026-06-30 09:54:49 +02:00
pnpm-lock.yaml feat: load-path §5 client — gateway transport behind the YjsProvider seam 2026-08-18 14:02:40 +02:00
pnpm-workspace.yaml feat(libs): r2-idb-sync bridge — sync-wire protocol, FE/BE packages, apps/server resolve+origin serving, GPL adapter 2026-06-17 09:59:59 +02:00
README.md feat: GPL backend self-provisions example libs + standalone port override 2026-06-16 16:28:21 +02:00
tsconfig.base.json feat(web): checkpoint web app init 2026-06-02 20:32:19 +02:00
turbo.json feat(editor): report uncaught errors to Better Stack 2026-08-03 12:24:30 +02:00

PCBJam Web — standalone editor (GPL)

A self-contained, GPL web app that opens KiCad projects in the WASM tools (pcbnew / eeschema / pl_editor / …) — from a local folder, or from any backend that implements the MIT @pcbjam/shared contract. It opens a tool by URL:

/p/<project>/<tool>/<file-path>      e.g. /p/demo/pcbnew/nyak.kicad_pcb

This workspace contains only the generic editor and a thin reference backend. All project-specific concerns (accounts, project management, uploads, auth) live in the separate closed application, which reuses this editor by hosting it standalone and redirecting to it (it must not link the GPL editor).

Layout

web/
├── standalone/      # @pcbjam/standalone — the GPL editor (Vite + React)
├── backend/         # @pcbjam/backend-example — thin reference @pcbjam/shared impl
└── pcbjam-shared/   # @pcbjam/shared — the FE↔BE contract (git submodule, MIT)
  • Editor: Vite + React + TypeScript. Boots a tool directly in the document (no iframe), syncs the project tree into MEMFS, drives File→Open, and runs same-tab collaboration over BroadcastChannel.
  • Example backend: Fastify + ts-rest serving a single project off the local filesystem (PROJECT_DIR). No DB, no auth, no uploads — the minimum the editor needs, and a worked example of the contract. Listens on :3060. On dev/start it self-provisions example libraries — a curated slice of upstream KiCad symbol + footprint libs is cloned + extracted into .libs (served as read-only origins), so a bare clone has libraries to browse with no closed repo present. See backend/src/extract/.

Quick start

cd web
pnpm install
git submodule update --init web/pcbjam-shared   # if not already populated

cp standalone/.env.example standalone/.env
cp backend/.env.example backend/.env            # PROJECT_DIR=../../tests/fixtures/demo

pnpm dev                                         # turbo: backend :3060 + editor :3048

Open http://localhost:3048 — either open a local folder (no backend needed) or open the backend's project. The editor can point at any conforming backend via VITE_API_BASE_URL.

WASM artifacts

The runtime artifacts (<tool>.js/.wasm, wx.js, images.tar.gz, <tool>.html) are build outputs, not committed. They are synced into tests/apps/kicad/ by tests/scripts/setup-kicad-wasm.sh (from repo-root output/).

They must be served same-origin as the app. Under the document's COEP / cross-origin-isolation (set by the Vite dev server), KiCad WASM refuses to load its glue/wasm from a different origin. pnpm dev runs scripts/link-wasm.mjs, which symlinks standalone/public/wasm → tests/apps/kicad; Vite serves them at /wasm. VITE_WASM_ASSET_BASE_URL defaults to /wasm.

  • Point the symlink elsewhere with WASM_SRC_DIR=/path pnpm --filter @pcbjam/standalone link-wasm.
  • If a tool won't load, the target dir is probably empty — run tests/scripts/setup-kicad-wasm.sh to populate tests/apps/kicad/.
  • prod: point VITE_WASM_ASSET_BASE_URL at a URL whose origin also satisfies the same-origin / COEP constraints.

Scripts

Command What
pnpm dev editor + example backend (turbo)
pnpm build build all packages
pnpm typecheck typecheck all packages

Contract (@pcbjam/shared, MIT)

The editor reads from a backend over the shared contract: GET /api/projects, GET /api/projects/:project, GET /api/projects/:project/files, and the streamed GET /api/projects/:project/files/* (raw bytes). Management/write operations and ownership are not part of this contract — they belong to the closed app.