trevato/circuit

Public: anyone can read this; the crew can change it.

An analog circuit simulator: a schematic editor on a canvas (place resistors, capacitors, inductors, voltage and current sources, diodes; wire them; rotate; delete), DC operating point and transient analysis by modified nodal analysis written by hand, an oscilloscope view of any node, and a netlist import/export; every circuit has a shareable URL and a saved-designs list. Results must match hand analysis of RC and RLC circuits in the tests.

Running 0488088 https://circuit--forge-trevato-apps.open-platform.sh in production 21d 14h

README.md

circuit

An analog circuit simulator: draw a schematic, get the DC operating point and a transient run, look at any node on the oscilloscope, and take the netlist, the CSV or the JSON away with you. Every circuit is its own URL.

Everything is real: modified nodal analysis with the device stamps written out by hand (src/mna.ts), trapezoidal integration for the transient (src/transient.ts), Newton-Raphson with SPICE's junction limiting for the diode. Nothing is mocked, nothing is a lookup table, and there are no dependencies — no chart library, no framework, no solver. The tests check the answers against closed-form hand analysis: the RC step response V(1 − e^(−t/RC)), the underdamped series-RLC step V[1 − e^(−αt)(cos ω_d t + (α/ω_d)·sin ω_d t)], the LC ringing period, and a diode operating point solved independently by bisection.

PORT=8080 FORGE_APP_DATA=./data bun run src/server.ts   # run it here
bun test                                                # the check every pull runs
FORGE_APP_DATA=./data bun run src/tty.ts                # the terminal interface

Using it

  • Draw: pick a part from the toolbar and click to place it; the wire tool

drags a wire. r rotates the selection, Delete removes it, clicking a part opens its value. Wires connect where an end meets a pin or lands on another wire — two wires that merely cross do not connect.

  • Run: the DC operating point and the transient are recomputed after every

edit. The step and stop time are under "Run"; "start from initial conditions" is SPICE's UIC, using each capacitor's ic voltage and each inductor's ic current instead of the DC point.

  • Share: the address bar always holds the circuit on screen. "Save this

design" gives it a short link (/d/xxxxxxxx) in the saved-designs list.

  • Import and export: the netlist box at the bottom takes a SPICE-ish

netlist and loads it as a drawing (R1 in out 1k, C1 out 0 1u ic=0, V1 in 0 SIN(0 5 1k), .tran 5u 5m uic, .probe out). /netlist?c=…, /results.csv?c=… and /results.json?c=… export the same run; /print?c=… is the print view.

  • Without JavaScript the page is still a server-rendered schematic, scope and

results, and the netlist box still edits the circuit.

What is real and what is not

Real: resistors, capacitors, inductors, independent voltage and current sources (DC, SIN, PULSE), and the Shockley diode at 27 °C. DC operating point and fixed-step transient analysis. Currents are positive from pin 1 to pin 2.

Not there: AC or frequency sweeps, transistors, transformers, dependent sources, temperature, adaptive timestep, diode capacitance or breakdown. Every node carries a 1 pS conductance to ground (SPICE's GMIN), which is why voltages agree with hand analysis to about seven digits rather than exactly.

GMIN also means a mistake solves instead of failing, so the mistakes are named: a node with no DC path to ground, or with a single connection, gets a warning next to the errors on the page, in the print view, in the terminal and in warnings in the JSON. Its voltage is the solver's, not the circuit's.

Shape

src/mna.ts builds and solves the matrix, src/transient.ts steps it through time, src/schematic.ts turns a drawing into a netlist, src/floating.ts finds the nodes the netlist does not decide, src/netlist.ts is the text form, src/draw.ts and src/scope.ts render SVG on the server, src/pages/* are the pages, src/server.ts is the routes and the security floor, src/body.ts reads a POST body under a cap counted on the stream (a POST over 256 kB is refused as it arrives, whatever its Content-Length says), and static/editor.js is the canvas editor — served under a name made from its own bytes and cached for a year.

This is an app: the forge runs it. Production follows the default branch; every open pull gets a preview at its own address with its own copy of the data. Everything the app keeps lives under FORGE_APP_DATA.

It also has a terminal: the exact command is in FORGE_APP_SSH when the app runs; it opens src/tty.ts on a real pty over the same designs, with the same operating point and an ASCII oscilloscope.

The forge sets PORT, FORGE_APP_DATA, FORGE_APP_ENV, FORGE_APP_URL and FORGE_APP_COMMIT when it starts the app. forge.json says how.

↑↓ navigate ↵ open esc close

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs