diff --git a/README.md b/README.md new file mode 100644 index 0000000..8934a17 --- /dev/null +++ b/README.md @@ -0,0 +1,273 @@ +
+ +# 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 +- **3 example notebooks** included: + - RC Lowpass Filter Analysis (AC + transient) + - Voltage Divider (DC operating point + sweep) + - Common Emitter Amplifier (AC + transient with BJT model) + +## 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) diff --git a/docs/screenshots/both-sims-complete.png b/docs/screenshots/both-sims-complete.png new file mode 100644 index 0000000..2455d7c Binary files /dev/null and b/docs/screenshots/both-sims-complete.png differ diff --git a/docs/screenshots/notebook-with-bode-plot.png b/docs/screenshots/notebook-with-bode-plot.png new file mode 100644 index 0000000..f0e3a72 Binary files /dev/null and b/docs/screenshots/notebook-with-bode-plot.png differ