Logic Circuit Lab is a browser-based playground for sketching, simulating, and exporting small digital circuits. The UI is built on the Bespoke generalized components so it can be embedded anywhere, while a lightweight Node.js server serves the app, handles VHDL exports, and exposes a simple messaging API.
client/index.html– the full Bespoke application (header, palette, canvas, inspector, help trigger).client/logic-sim.js– canvas rendering, drag/drop, wiring, evaluation, auto-save, export helpers.client/logic-sim.css– circuit-specific styling layered on top ofclient/bespoke.css.client/gate-registry.js&client/gates/*.svg– built-in gate definitions, icons, and logic.client/help-modal.js&client/help-content-template.html– Help modal framework and copy.client/initial_state.json– starter circuit loaded on first launch or after reset.client/gate-config.json– palette ordering, default zoom, and export-report options.server.js– static file server,/vhdl/exporthandler,/messagerelay, optional WebSocket hub.circuit-report.js– pretty printer that summarizes each export to the console.
- Drag gates from the palette or click to drop them at the center of the viewport.
- Wire outputs to inputs with a click/tap workflow; wires snap to ports and redraw as you move gates.
- Real-time simulation with deterministic propagation and cached inputs to avoid oscillations.
- Selection panel with gate metadata, label editing, and context actions (toggle inputs, delete, etc.).
- Infinite workspace with smooth pan (drag on empty canvas) and wheel-based zoom (Ctrl+wheel for precision).
- Auto-save to
localStoragewith standardized Bespoke status messaging (Ready,Saving..., etc.). - Reset button reloads
initial_state.jsonand re-primes auto-save. - Help modal content streamed from
help-content-template.htmland triggered by the header Help button. - One-click (or scripted) VHDL export that posts the circuit snapshot to the Node server.
- Install prerequisites – Node.js 18+ and npm.
- Install dependencies – Run
npm installif you need to add/refresh modules. - Start the dev server
The server listens on
npm start
http://localhost:3000and serves the contents ofclient/. - Open the app – visit
http://localhost:3000to launch Logic Circuit Lab. - Optional: broadcast a message
Requires the
curl -X POST http://localhost:3000/message \ -H "Content-Type: application/json" \ -d '{"message":"Hello lab!"}'
wsdependency to be installed; all connected clients will display the alert.
- Palette (left sidebar) – click a gate to drop it at the center, or drag it directly into the canvas. Available gates include Input, Output, Buffer, NOT, AND, NAND, OR, NOR, and XOR; extend the list via
gate-registry.js. - Canvas – drag on empty space to pan, use the mouse wheel (or pinch gesture) to zoom, and click a gate to select it. Press Delete/Backspace to remove the active gate. Selection outlines show connection points; ports highlight when valid wiring targets are available.
- Wiring workflow – click an output port, then click a compatible input port. A ghost wire follows your cursor until you pick a destination. Clicking an occupied input rewires it to the new source.
- Inputs and outputs – input gates act as toggles; click them (or use the inspector action) to switch between 0/1. Output gates display the live signal coming into their single input.
- Inspector (Selection card) – shows the currently selected gate’s properties, allows renaming labels, exposes gate-specific actions, and lists every connected port.
- Reset – the “Reset” button above the canvas replaces the board with
initial_state.jsonand reinitializes auto-save. - Help – the
Helpbutton in the header opens the modal populated fromhelp-content-template.html. Update that file to document your specific lab instructions, keyboard shortcuts, or grading rubric.
- Custom gates are described through
.jsonsnapshots that match thestate.jsonschema (the object returned bywindow.logicSim.snapshot()). - Build a circuit with the standard palette, export it via
window.logicSim.snapshot()(or copystate.json), and drop that JSON file intoclient/custom-gates/to turn it into a reusable gate without duplicating its contents. - Input and output pins for the custom gate are inferred from the
inputandoutputgates inside the JSON snapshot (their labels become the exposed port names). Simulation treats the custom gate as a black box by running the nested snapshot with the same propagation engine. - Snapshots embedded in saved circuits (or discovered under
client/custom-gates/) automatically appear in the main palette alongside the built-in gates. - VHDL exports automatically flatten any custom gates, so you can keep them in your design and still obtain a complete netlist (the written
state.jsonmirrors that flattened export).
- On first load,
logic-sim.jsfetchesinitial_state.json, applies it to the canvas, and caches it locally. - Once the app confirms that
localStorageworks, every mutation is debounced (500 ms) and saved under the keylogic-circuit-lab-state-v1. - Status changes are limited to the mandated Bespoke messages;
setStatus()is exposed globally for future integrations. - If persistence fails (quota exceeded, private mode, etc.), the app logs the error, shows
Failed to load data, and keeps the in-memory circuit running. - Resetting the canvas writes the starter snapshot back to storage, ensuring the pool stays in sync across reloads.
- Trigger an export by running one of the following in DevTools or from a parent frame:
window.logicSim.exportToVhdl(); // or window.dispatchEvent(new Event('logic-sim:export-vhdl')); // or window.postMessage({ type: 'logic-sim:export-vhdl' }, '*');
- The client serializes the current snapshot to VHDL, then POSTs:
to
{ "vhdl": "<generated code>", "state": { ...current circuit snapshot... } }POST /vhdl/export. - The server writes
user.vhdlandstate.jsonat the repo root, then runscircuit-report.printCircuitReport()to log counts, positions, connection issues, and (optionally) a truth table. Report sections are toggled viagate-config.json > exportReport. - If the request fails, the client shows
Save failed (will retry)and automatically retries after 3 s.
client/gate-config.jsondefaultZoom– initial canvas scale (clamped between 0.5 and 2.75).paletteOrder– ordered list of gate type keys fromgate-registry.js.exportReport– toggles for each console report section plus truth-table limits.
client/initial_state.json- Defines the starter circuit (
gates,connections,nextId). Edit coordinates, labels, or states to showcase a different demo when the app loads.
- Defines the starter circuit (
client/gate-registry.js- Extend
registerGate()calls to add new gate types. Provide an SVG icon,inputs,outputs, port layout, and a pure logic function that returns output bits.
- Extend
client/logic-sim.css- Customize colors, gate chrome, canvas grid, inspector layout, etc. Keep theme tokens (
--bespoke-*) to remain compatible with host pages.
- Customize colors, gate chrome, canvas grid, inspector layout, etc. Keep theme tokens (
client/help-content-template.html- Replace placeholders with real instructions. The file is fetched as text, so inline images should use relative paths inside
client/.
- Replace placeholders with real instructions. The file is fetched as text, so inline images should use relative paths inside
GET /(and static assets) – serves files fromclient/.POST /vhdl/export– accepts{ vhdl: string, state: object }, writes artifacts, prints reports, responds with{ success: true }on success.POST /message– accepts{ message: string }, broadcasts it to every connected WebSocket client (wspackage required). Clients show an alert with the message body.- WebSockets – automatically enabled when the
wsdependency is installed. Connections are logged, and messages flow only from/messageto the clients; there is no inbound command channel yet.
- The canvas exposes
window.logicSimwith:exportToVhdl()– triggers the export flow described above.snapshot()– returns the current normalized circuit state.resetToStarter()– programmatically mirrors the Reset button.
- Custom exporters can listen for
messageevents (event.data.type === 'logic-sim:export-vhdl') or dispatch thelogic-sim:export-vhdlDOM event. - The app uses standard Bespoke status messaging and
.bespokescoping, so you can embedclient/index.htmlinsidetest-integration.htmlor another host without style collisions.