Logic Gate Studio is a local-first logic circuit workspace for human study and AI-assisted reasoning.
The visual canvas is for building and reading circuits quickly. The saved .logic.json document is for preserving exact circuit meaning. Both point to the same circuit model, so the GUI, CLI, validation, and simulation layers stay aligned.
- Build college-level logic circuits visually without losing semantic precision.
- Save circuits in a canonical JSON format that is easy for both humans and AI tools to inspect.
- Keep layout metadata separate from circuit meaning.
- Support deterministic combinational and sequential behavior for teaching, debugging, and sharing.
- Three-pane local web app with a palette, canvas, contextual inspector, analysis panel, and JSON editor.
- Canonical
.logic.jsondocuments with stable component IDs, explicit ports, layout metadata, and persisted simulation state. - Live synchronization between the canvas, inspector edits, and the JSON view.
- Structural validation for schema issues, duplicate IDs, broken references, invalid ports, multiple drivers, unwired inputs, and combinational cycles.
- Combinational evaluation plus sequential
step,clock tick, andresetactions. - Truth-table generation for combinational circuits, with markdown copy support in the UI and CLI.
- Local file workspace browsing and save/save-as support for
circuits/**/*.logic.json. - CLI commands for validation, evaluation, truth-table generation, and circuit summaries.
- Example circuits for common study cases, including XOR, half adder, SR latch, and flip-flops.
- Inputs and outputs:
INPUT,OUTPUT - Constants and routing:
CONST_0,CONST_1,SPLITTER,MUX,DEMUX - Logic gates:
NOT,AND,OR,XOR,NAND,NOR,XNOR - Sequential components:
CLOCK,SR_LATCH,D_FLIP_FLOP,JK_FLIP_FLOP,T_FLIP_FLOP
AND,OR,XOR,NAND,NOR, andXNORnormalizeinputCountinto the supported2-4range.SPLITTERnormalizesoutputsinto the supported2-6range.MUXandDEMUXnormalizeselectBitsinto the supported1-4range, covering2:1through16:1and1:2through1:16.- Sequential components normalize
initialQto0or1.
- Current Node.js LTS
npm
npm install
npm run devOpen:
- App:
http://localhost:5173 - File server:
http://localhost:4387
By default, the app proxies /api/* requests to the local file server and attempts to open circuits/examples/simple-xor.logic.json on startup if it exists.
FILE_SERVER_ROOT: root directory for the file API. Defaults to the current working directory.FILE_SERVER_PORT: file server port. Defaults to4387.VITE_API_TARGET: override the Vite dev proxy target for/api.
- Saved circuits must stay inside the repo's
circuits/directory tree. - The server rejects path traversal and rejects documents with validation errors.
circuits/examples/simple-xor.logic.json: basic semantic XOR example with stable IDs and labels.circuits/examples/half-adder.logic.json: combinational circuit with a truth-table-friendly output pair.circuits/examples/nand-only-xor.logic.json: alternate XOR implementation using only NAND gates.circuits/examples/sr-latch.logic.json: sequential latch behavior with state retention.circuits/examples/d-flip-flop.logic.json: rising-edge D flip-flop driven by a clock component.circuits/examples/jk-flip-flop.logic.json: JK flip-flop transitions.circuits/examples/t-flip-flop.logic.json: T flip-flop toggling.
- Start the app with
npm run dev. - Open one of the example circuits from the workspace list, or create a new one.
- Add components from the palette by clicking or dragging onto the canvas.
- Click input nodes to toggle them. Hover nodes to inspect live port signals. Click a hover card or node to open the contextual inspector.
- Wire ports on the canvas, then use
Evaluate,Step,Clock ↑, orResetfrom the toolbar. - Open the
JSONtab to inspect or edit the canonical document directly, then apply or discard the draft. - Use the
Analysistab to review outputs, validation messages, and the truth table. - Save the circuit back into
circuits/so the web app, CLI, and tests can all use the same file.
| Command | What it does |
|---|---|
npm run dev |
Starts Vite and the local file server together. |
npm run file-server |
Runs only the Express file API. |
npm run build |
Runs TypeScript checks and creates a production build in dist/. |
npm run preview |
Serves the built app with Vite preview. |
npm run typecheck |
Runs tsc --noEmit. |
npm run lint |
Runs eslint src/. |
| Command | What it does |
|---|---|
npm run test |
Alias for the fast unit suite. |
npm run test:watch |
Watches unit tests under src/test/unit. |
npm run test:unit |
Runs the unit suite. |
npm run test:integration |
Runs jsdom and file-server integration tests. |
npm run test:e2e |
Runs Playwright browser tests. |
npm run test:all |
Runs unit, integration, and e2e suites in sequence. |
The CLI reads saved circuit files directly and uses the same circuit model and engine as the app.
npm run circuit -- validate <file>
npm run circuit -- eval <file> [--set inputId=1] [--format json]
npm run circuit -- truth-table <file> [--inputs a,b] [--outputs y] [--format json|markdown]
npm run circuit -- summarize <file> [--format json|markdown]Examples:
npm run circuit -- summarize circuits/examples/simple-xor.logic.json --format markdown
npm run circuit -- validate circuits/examples/half-adder.logic.json
npm run circuit -- eval circuits/examples/simple-xor.logic.json --set in_a=1 --set in_b=0
npm run circuit -- truth-table circuits/examples/half-adder.logic.json --format markdownThe saved circuit file is the semantic source of truth. Coordinates are presentation metadata only.
{
"version": 1,
"meta": {
"title": "Simple XOR",
"notes": "Two-input XOR gate with semantic IDs for discussion."
},
"components": [
{
"id": "in_a",
"type": "INPUT",
"label": "A",
"ports": { "inputs": [], "outputs": ["out"] },
"params": {}
},
{
"id": "xor_1",
"type": "XOR",
"label": "Main XOR",
"ports": { "inputs": ["in1", "in2"], "outputs": ["out"] },
"params": { "inputCount": 2 }
}
],
"connections": [
{
"id": "wire_a_xor",
"from": { "componentId": "in_a", "port": "out" },
"to": { "componentId": "xor_1", "port": "in1" }
}
],
"layout": {
"positions": {
"in_a": { "x": 120, "y": 120 },
"xor_1": { "x": 360, "y": 190 }
}
},
"simulation": {
"inputs": { "in_a": 0 },
"clocks": {},
"sequential": {},
"tickCount": 0
}
}- Circuit meaning comes from
components,connections, and named ports. layout.positionsis only for rendering on the canvas.simulationstores current inputs, clocks, sequential state, and tick count.- Normalization keeps documents in a consistent shape before save, evaluation, or rendering.
The web app uses a small local file API.
| Endpoint | Method | Purpose |
|---|---|---|
/api/circuits |
GET |
Lists saved .logic.json files and titles under circuits/. |
/api/circuit?path=... |
GET |
Loads a specific circuit document. |
/api/circuit |
POST |
Validates and saves a circuit document. |
The circuit model is the single source of truth. UI state and CLI output adapt to it; they do not redefine it.
src/circuit/model: shared types, component registry, defaults, and document normalization.src/circuit/schema: runtime parsing with Zod.src/circuit/validation: structural and semantic checks.src/circuit/simulation: combinational evaluation and sequential stepping.src/circuit/truth-table: combinational truth-table generation.src/circuit/io: JSON formatting, markdown formatting, and browser file client helpers.src/circuit/adapters: adapters from the semantic model into UI-specific structures such as React Flow nodes and edges.src/state: Zustand store creation and action wiring for the app.src/appandsrc/components: application shell, canvas, palette, inspector, and analysis UI.src/server: local Express file API forcircuits/**/*.logic.json.src/cli: terminal interface for validation and analysis.src/test: unit and integration coverage for the shared engine and app wiring.e2e: Playwright flows against the running app and a temporary circuits workspace.
- Input nodes toggle directly on click.
- Hover cards expose live port signals and open the contextual inspector.
- MUX and DEMUX nodes expand on hover or selection to show labeled ports.
- The right panel provides
AnalysisandJSONviews, while the contextual inspector stays near the selected node.
Verified during documentation work:
npm run typechecknpm run buildnpm run test:unitnpm run test:integrationnpm run circuit -- summarize circuits/examples/simple-xor.logic.json --format markdown
Current test notes:
- Unit coverage focuses on the pure circuit engine, registry helpers, validation, simulation, and formatters.
- Integration coverage exercises the app store, JSON editing flow, save behavior, and in-process file server.
- Playwright e2e coverage exists and is configured to run the real app against a temporary copied
circuits/workspace. - In this environment,
npm run test:e2edid not complete because the Playwright config launches the Chrome channel and headless Chrome aborted before tests executed. The e2e suite is still part of the project, but it depends on a compatible local browser environment.
- Truth-table generation is intentionally limited to combinational circuits in v1.
- Combinational cycles are rejected; use sequential elements to model stateful feedback.
- The file server only allows paths inside
circuits/. - There is no waveform viewer, HDL import/export, or multi-user collaboration layer in the current codebase.
Logisim/
├── circuits/ # Saved canonical `.logic.json` circuit documents
│ └── examples/ # Committed teaching fixtures used by the app and tests
├── docs/
│ └── superpowers/ # Claude Code Superpowers design specs and implementation plans
├── e2e/
│ └── logic-gate-studio.spec.ts # Playwright browser flows against the real app
├── public/
│ └── favicon.svg # Static asset served by Vite
├── src/
│ ├── app/ # Top-level app shell and toolbar wiring
│ ├── circuit/ # Shared semantic circuit engine
│ │ ├── adapters/ # Adapters from circuit documents into UI-specific shapes
│ │ ├── io/ # JSON/client/markdown formatting helpers
│ │ ├── model/ # Core types, component registry, normalization helpers
│ │ ├── schema/ # Zod runtime schema for circuit documents
│ │ ├── simulation/ # Combinational evaluation and sequential stepping
│ │ ├── truth-table/ # Truth-table generation for combinational circuits
│ │ └── validation/ # Structural and semantic validation rules
│ ├── cli/ # Terminal entry points for validate/eval/summarize flows
│ ├── components/ # React UI panels and canvas components
│ │ ├── analysis/ # Outputs, truth table, and validation UI
│ │ ├── canvas/ # React Flow nodes, hover cards, and contextual inspector
│ │ ├── inspector/ # Right-side inspector tabs and Monaco JSON editor
│ │ ├── palette/ # Workspace file list and component palette
│ │ └── ui/ # Small shared UI pieces such as the Save As modal
│ ├── server/ # Local Express file API for `circuits/**/*.logic.json`
│ ├── state/ # Zustand store creation and provider wiring
│ ├── styles/ # Global application styling
│ ├── test/ # Unit and integration test suites
│ │ ├── helpers/ # Shared fixture-loading helpers for tests
│ │ ├── integration/ # App-store and file-server integration tests
│ │ ├── unit/ # Pure circuit-engine and formatter tests
│ │ └── setup.ts # Shared Vitest setup
│ └── main.tsx # React entry point
├── AGENTS.md # Repo guidance for coding agents
├── CLAUDE.md # Repo guidance for Claude Code
├── eslint.config.js # ESLint configuration
├── index.html # Vite HTML entry
├── package-lock.json # Locked npm dependency graph
├── package.json # Project scripts and Node dependencies
├── playwright.config.ts # E2E config with a temporary circuits workspace
├── tsconfig.json # TypeScript compiler configuration
├── vite.config.ts # Vite config and `/api` proxy setup
└── vitest.config.ts # Vitest configuration for unit and integration suites
- Use
npmfor local workflows. - Prefer keeping domain semantics inside
src/circuitinstead of duplicating logic in React components. - Optimize for correctness, readability, and semantic clarity over visual cleverness.
- Add tests at the lowest layer that proves the behavior cleanly, then broaden only when the interaction boundary matters.
- Follow the surrounding TypeScript style. The repo does not currently enforce a formatter.
- Use Conventional Commits for commit messages, such as
feat: ...andtest: ....
- Planning and design history lives in
docs/superpowers/. - Saved circuits in
circuits/examples/double as fixtures for the app, CLI, and tests. - If product docs and code ever disagree, treat the shipped code and verified behavior as the source of truth.