# SpiceBook **A notebook interface for SPICE circuit simulation.** Write the narrative. Run the simulation. See the waveform. All in one document.
--- ![SpiceBook notebook showing RC lowpass filter with Bode plot and step response waveforms](docs/screenshots/both-sims-complete.png) ## What is this? SpiceBook is a notebook for circuit engineers. Markdown cells for explanation, SPICE cells for simulation, waveform plots for results -- interleaved in a single document you can re-run, share, and version control. Think "Jupyter for circuits" except it actually understands SPICE. The editor highlights your `.tran` and `.ac` commands. The waveform viewer knows about dB and degrees. Engineering notation on the axes reads `1.59 kHz`, not `1591.549`. Nothing else does this. PySpice needs you to write Python. CircuitLab is closed-source and schematic-only. Multisim Live is shutting down. The browser-based ngspice wrappers give you one netlist and one plot -- no narrative, no interleaving, no notebook. SpiceBook lets you write a document that says: "here's why this filter works, here's the AC analysis proving it, here's the step response confirming the time constant" -- and every claim is backed by a live, re-runnable simulation. ## Features - **Markdown cells** with rendered preview -- headings, bold, lists, inline math notation - **SPICE cells** with CodeMirror 6 and custom syntax highlighting: - Dot commands (`.tran`, `.ac`, `.dc`, `.model`, `.param`, `.subckt`, ...) - Component prefixes (`R`, `C`, `L`, `V`, `I`, `M`, `Q`, `D`, `X`) - Engineering notation (`1k`, `10u`, `3.3meg`, `100p`) - Comments (`*` and `;`), brace expressions (`{10k*(1-x)}`) - **Waveform viewer** built on uPlot (~50KB, fast): - Multi-trace overlay with color-coded legend - Stacked Bode plots (magnitude dB + phase degrees) for AC analysis - Time-domain plots for transient analysis - Log-scale frequency axis, engineering-notation labels - Click-drag zoom, scroll to pan - **ngspice backend** -- subprocess execution with binary `.raw` file parsing - **Notebook operations** -- create, open, edit, save, delete, reorder cells, run individually or all at once - **Keyboard shortcuts** -- `Ctrl+S` save, `Shift+Enter` run cell - **Clean URLs** -- `/notebook/rc-lowpass-filter` via Astro dynamic routes - **15 example notebooks** included: **Fundamentals:** - RC Lowpass Filter Analysis (AC + transient) - Voltage Divider (DC operating point + sweep) - Common Emitter Amplifier (AC + transient with BJT model) - RC Step Response, RLC Bandpass Filter, Diode Rectifier, LED I-V Curve, Inverting Op-Amp, CMOS Inverter **Advanced (multi-cell, real-world circuits):** - Synchronous Buck Converter -- 12V-to-3.3V switching regulator with startup and steady-state detail - Class AB Push-Pull Audio Amplifier -- frequency response, clean output, and overdrive clipping - AM Radio Receiver -- envelope detection with carrier and audio waveforms - Dickson Charge Pump -- voltage multiplication under light and heavy loads - Transmission Line Signal Integrity -- unterminated ringing vs series-terminated clean signals - 4th-Order Sallen-Key Butterworth Filter -- active filter vs passive RC comparison - Colpitts RF Oscillator -- ~1 MHz oscillation startup and steady-state ## Quick Start ### Prerequisites - **ngspice** -- the simulation engine - Arch: `sudo pacman -S ngspice` - Debian/Ubuntu: `sudo apt install ngspice` - macOS: `brew install ngspice` - **Python 3.12+** with [uv](https://docs.astral.sh/uv/) - **Node.js 20+** ### Local Development (no Docker) ```bash # Clone cd spicebook # Backend cd backend uv sync uv run uvicorn spicebook.main:app --host 0.0.0.0 --port 8099 --reload # Frontend (separate terminal) cd frontend npm install npx astro dev --host 0.0.0.0 --port 4322 ``` Open [http://localhost:4322](http://localhost:4322) ### Docker (Development) ```bash make dev ``` Frontend at `http://localhost:4321`, backend at `http://localhost:8099`, API docs at `http://localhost:8099/docs`. ### Docker (Production) ```bash make prod ``` Production mode runs behind Caddy with TLS via `caddy-docker-proxy`. Set `SPICEBOOK_DOMAIN` in `.env`. ### Makefile Targets | Target | What it does | |--------|-------------| | `make dev` | Build and start dev containers with hot-reload | | `make prod` | Build and start production containers | | `make down` | Stop all containers | | `make logs` | Tail container logs | | `make clean` | Remove containers, volumes, and build artifacts | | `make backend-shell` | Shell into the backend container | | `make help` | List all targets | ## Project Structure ``` spicebook/ ├── frontend/ # Astro 5 + React 19 │ ├── src/ │ │ ├── pages/ # Astro routes (index, /notebook/[id]) │ │ ├── components/ │ │ │ ├── notebook/ # Editor, cells, output viewers, toolbar │ │ │ └── ui/ # Button, Badge, Dropdown (shadcn/ui) │ │ ├── lib/ │ │ │ ├── spice-language.ts # CodeMirror SPICE mode │ │ │ ├── waveform-utils.ts # Engineering notation formatter │ │ │ ├── notebook-store.ts # Zustand state │ │ │ ├── api.ts # Backend client │ │ │ └── types.ts # TypeScript types │ │ └── styles/globals.css │ └── astro.config.mjs ├── backend/ # FastAPI + ngspice │ ├── src/spicebook/ │ │ ├── main.py # App factory, health check │ │ ├── config.py # Settings from environment │ │ ├── engine/ # SPICE engine abstraction │ │ │ ├── base.py # Abstract base class │ │ │ └── ngspice.py # ngspice subprocess + .raw parser │ │ ├── models/ # Pydantic schemas │ │ │ ├── notebook.py # Notebook, Cell, CellOutput │ │ │ └── simulation.py │ │ ├── routers/ # API endpoints │ │ │ ├── notebooks.py # CRUD │ │ │ ├── simulation.py # Run cells │ │ │ └── waveforms.py # Waveform data │ │ └── storage/ │ │ └── filesystem.py # .spicebook file I/O │ ├── tests/ │ └── pyproject.toml ├── notebooks/ │ ├── examples/ # Shipped example notebooks │ └── user/ # User-created (gitignored) ├── docker-compose.yml # Base services ├── docker-compose.dev.yml # Dev overrides (hot-reload, port mapping) ├── docker-compose.prod.yml # Prod overrides (Caddy, no ports exposed) ├── Makefile └── .env ``` ## `.spicebook` File Format Notebooks are JSON files with a `.spicebook` extension. Git-friendly, outputs persisted inline. ```json { "spicebook_version": "2026-02-13", "metadata": { "title": "RC Lowpass Filter Analysis", "engine": "ngspice", "tags": ["filter", "passive"] }, "cells": [ { "id": "cell-001", "type": "markdown", "source": "# My Circuit\nExplanation goes here.", "outputs": [] }, { "id": "cell-002", "type": "spice", "source": "V1 in 0 AC 1\nR1 in out 1k\nC1 out 0 100n\n.ac dec 100 1 10meg\n.end", "outputs": [ { "output_type": "simulation_result", "data": { "success": true, "waveform": { "..." : "..." } }, "timestamp": "2026-02-13T12:00:00Z" } ] } ] } ``` ## Tech Stack | Layer | Technology | |-------|-----------| | Frontend framework | Astro 5 (SSR, Node adapter) | | Interactive islands | React 19 | | Code editor | CodeMirror 6 (custom SPICE language mode) | | Waveform charts | uPlot | | State management | Zustand | | Styling | Tailwind CSS 4 | | UI components | shadcn/ui | | Icons | Lucide | | Backend | FastAPI | | SPICE engine | ngspice (subprocess) | | Data validation | Pydantic | | Containerization | Docker Compose | | Reverse proxy | Caddy (via caddy-docker-proxy) | ## API The backend exposes a REST API. When running in dev mode, interactive docs are at `http://localhost:8099/docs`. Key endpoints: | Method | Path | Description | |--------|------|-------------| | `GET` | `/api/notebooks` | List all notebooks | | `GET` | `/api/notebooks/{id}` | Get a notebook | | `POST` | `/api/notebooks` | Create a notebook | | `PUT` | `/api/notebooks/{id}` | Update a notebook | | `DELETE` | `/api/notebooks/{id}` | Delete a notebook | | `POST` | `/api/notebooks/{id}/cells/{cell_id}/run` | Run a SPICE cell | | `POST` | `/api/simulate` | Run a standalone simulation | | `GET` | `/health` | Health check | ## Configuration All configuration is via environment variables (`.env` file). See `.env` for the full list. | Variable | Default | Description | |----------|---------|-------------| | `ENVIRONMENT` | `dev` | `dev` or `prod` | | `BACKEND_PORT` | `8099` | Backend port (dev only) | | `FRONTEND_PORT` | `4321` | Frontend port (dev only) | | `NGSPICE_PATH` | `/usr/bin/ngspice` | Path to ngspice binary | | `NOTEBOOK_DIR` | `/app/notebooks` | Notebook storage path | | `SPICEBOOK_DOMAIN` | -- | Domain for production (Caddy TLS) | | `VITE_HMR_HOST` | -- | Set when behind reverse proxy | ## Roadmap ### Phase 2 -- Core Features - Python cells with sandboxed execution and cross-cell data access - LTspice engine integration (via mcltspice library) - Measurement cursors in waveform viewer - SVG/CSV export for waveforms - Signal analysis: FFT, THD, RMS, bandwidth - KaTeX math rendering in markdown cells ### Phase 3 -- Advanced - Schematic cells (SchemDraw backend rendering) - Auto-schematic generation from netlist - WebSocket progress for long simulations - LTspice `.asc` file import ### Phase 4 -- Polish - Interactive schematic editor (tscircuit integration) - Parameter sweeps with overlay plots - Monte Carlo analysis visualization - Template gallery ## Contributing 1. Fork the repository 2. Create a feature branch: `git checkout -b my-feature` 3. Make changes and add tests 4. Run the linter: `cd backend && uv run ruff check .` 5. Run tests: `cd backend && uv run pytest` 6. Submit a pull request ## Versioning SpiceBook uses date-based versioning (`YYYY.MM.DD`). The current version is `2026.02.13`. --- Built by [Ryan Malloy](mailto:ryan@supported.systems)