Starlight site at docs-site/ following warehack.ing cookie-cutter pattern
(3-compose split, Caddy prod stage, Makefile targets). 15 content pages
covering simulation engines, waveform viewer, schematics, embedding with
postMessage theme sync, and full REST API reference adapted from llms.txt.
Blue accent theme matching SpiceBook's application palette. Adds docs link
to homepage reference section.
WaveformViewer, SchematicViewer, and SimulationLog now use CSS
variable-backed utility classes (bg-sb-surface, text-sb-muted,
border-sb-border, etc.) instead of hardcoded Tailwind slate colors.
Light mode embed theme now works through the variable system rather
than brute-force class overrides in embed-theme.css.
frame-ancestors * for /embed/* routes so any site can iframe notebooks.
Remove postMessage origin allowlist (theme toggle is cosmetic-only).
Add EmbedDialog popover with copy-paste iframe snippet and theme picker.
Enable ltspice in the engine dropdown now that the backend supports it.
Repurpose the Maximize2 button in SchematicViewer as a fullscreen
toggle (was reset-zoom; percentage label is now clickable for that).
Add matching fullscreen toggle to WaveformViewer alongside the scope
button. Both use a shared useFullscreen hook for Escape-to-exit and
body scroll lock. In fullscreen mode, the SVG canvas and plot areas
fill the viewport with proper dimension tracking via ResizeObserver.
Extract shared rendering (chat-render.ts) and streaming hook
(use-chat-stream.ts) from ChatWidget so both the floating panel
and the new page share identical markdown/KaTeX/SSE logic.
New page features:
- Responsive sidebar (inline desktop, Sheet drawer mobile)
- Conversation search/filter
- Notebook picker via cmdk command palette
- Auto-growing multi-line textarea input
- Pop-out button on widget header to open /chat
ChatLayout.astro omits the floating widget to avoid duplicate UI.
Chat store gains selectedNotebookId for page-level notebook context.
shadcn-ui primitives (ScrollArea, Sheet, Command, Popover, etc.)
wired to existing SpiceBook dark theme tokens.
scrollIntoView walks up the DOM and scrolls every ancestor, including
the panel with overflow:hidden — this pushed the header and messages
area off-screen after long LLM responses. Using container.scrollTo
limits scrolling to only the messages div.
- Add comprehensive CSS for markdown elements in chat bubbles (headers,
lists, tables, blockquotes, links, code blocks, horizontal rules)
- Integrate KaTeX via marked-katex-extension for inline ($) and display
($$) math rendering with DOMPurify whitelist for MathML/SVG elements
- Add normalizeDisplayMath() pre-processor to handle LLM output where $$
delimiters appear inline rather than on their own lines
- Add dark theme KaTeX styles matching the SpiceBook color palette
- Fix asyncio.to_thread usage in chat SSE endpoint for streaming
- Mount FastMCP at /mcp with tools for notebook CRUD, simulation,
and cell execution. Includes status resource and circuit_assistant
prompt.
- Add SSE streaming chat endpoint at /api/chat/stream backed by
GPU LLM gateway (qwen3). Chat widget sends notebook context
(SPICE cells, markdown notes) so the assistant can reference the
user's circuit.
- React floating chat panel with zustand-persisted conversation
history, streaming token display, reasoning collapse, and
keyboard shortcuts.
- Refactor main.py from deprecated on_event("startup") to lifespan
context manager with combine_lifespans for MCP integration.
- Add notebook_id path traversal validation, decouple get_engine()
from HTTPException for MCP compatibility, fix HTTP client init
race condition with asyncio.Lock.
- Update Caddy labels for /mcp/* routing and SSE streaming on
backend reverse proxy.
- Cards (featured + gallery): hover adds -translate-y-1 + shadow-lg for
subtle lift-off-surface effect
- Homepage sections: replace hard border-b with gradient-fade dividers
that taper to transparent at edges
- Resistor button section: tighten vertical padding (py-10 → py-6)
- Notebook editor: cell spacing increased (space-y-0 → space-y-3),
add-cell button slides up on hover instead of abrupt opacity flash,
status bar gets more breathing room and lighter text
Promotes the full ResistorColorGuide component to a dedicated reference
page and replaces the homepage section with a compact inline SVG link
showing Green-Black-Black-Gold (50Ω ±5%) band colors.
Notebook cards now show schematic SVG thumbnails (on Mims green background)
and description snippets extracted from the first markdown cell. The backend
extracts both from already-loaded notebook data at zero additional I/O cost.
New ResistorColorGuide section between the pipeline strip and featured
notebooks explains the 4-band color code with an annotated zigzag diagram
and reference table using the same BAND_HEX colors from the schematic renderer.
Also switches docker-compose.dev.yml from direct port mapping to Caddy labels,
matching the production routing pattern and avoiding port conflicts.
Add ofst=0.15 to vertical resistor label calls preventing overlap with
color-coded zigzag bands. Add Schematic step 03 to homepage pipeline
with inline SVG voltage divider on Mims graph paper. Pipeline now
4-step with responsive 1col/2x2/4col layout.
Map physical resistor color bands onto the IEEE zigzag schematic symbol.
Each sub-segment is colored to match its band (digit, multiplier, tolerance),
with wire-colored entry/exit and a gap before tolerance mimicking real spacing.
Parseable values 0.01–1GΩ get color; parametric/out-of-range fall back to mono.
Astro scopes <style> block imports to the authoring component.
Since OscilloscopeDisplay.astro is a child of index.astro, the
scoped selectors didn't match. Move the CSS import into the
component itself with is:global.
Port the OscilloscopeDisplay from mcltspice docs — Web Audio API
renders stereo audio as Lissajous patterns on a canvas with teal
phosphor persistence. 6 tracks from Jerobeam Fenderson, volume
knob, skin switcher (465/545A), and the Outer Limits easter egg.
Audio: CC BY-NC-SA 4.0, oscilloscopemusic.com
Visual: Nick Watton (codepen.io/2Mogs), rsp2k
- Pin formatDate to timeZone: 'UTC' so server and client produce
identical date strings (fixes React error #418)
- Add one-shot service worker unregistration since SpiceBook doesn't
use one — clears phantom registrations from browser cache
astro-icon requires explicit icon registration — these two were used
in PipelineStrip.astro but missing from the include list, causing
SSR render failures in production.
Restructure the homepage to lead with visuals instead of text:
- Hero: split layout with animated Tektronix 465 oscilloscope showing
RC step response (CSS+SVG, zero JS) that links to the notebook
- Pipeline strip: 3-step Write → Simulate → Visualize with code/terminal
previews and inline waveform SVG
- Featured notebooks: 3 curated circuits (RC, 555, common emitter) with
pre-rendered waveform thumbnails
- Gallery cards: decorative graticule header strip, color-coded by engine
- Footer: updated copy with clearer call to action
All new sections are server-rendered Astro components. Total new client
JavaScript: zero bytes.
xDiv/yDiv were initialized as null and excluded from the main uPlot
effect's dependency array, causing the effect to bail on its null guard
and never re-run when the init effect set them to computed values.
Port 465/545A visual chrome from mcltspice docs into SpiceBook as a
toggleable waveform viewer skin. uPlot chart renders inside a CRT
screen with teal phosphor traces, graticule overlay, and scanlines.
Functional knobs control trace visibility (setSeries), X/Y zoom
(setScale) in standard 1-2-5 div steps. Digital readout bar shows
current trace, div values, and analysis type. Two switchable hardware
skins — 465 tan and 545A hammertone — persisted in localStorage.
New files: ScopeWaveformViewer.tsx, scope-skin.css
Modified: WaveformViewer.tsx (toggle), waveform-utils.ts (scope
palette, 1-2-5 sequence, stack-safe min/max), globals.css (scope vars)
SPICE cells now auto-trigger schematic generation when they mount
without an existing diagram, so the schematic leads the UI. Template
and empty cells are skipped.
Grid fallback layout replaced with wire-connected rendering: BFS-based
node tier classification places components vertically between supply
and ground rails, then routes wires by node type (power/ground bus
rails, L-shaped signal wires, star topology for 3+ connections).
SSR the notebook list in Astro frontmatter (eliminating the client-side
loading spinner). Add hero section with oscilloscope graticule background,
4-column feature highlights, and a React island gallery with category
filter pills, tag search, and grouped/flat view modes.
Machine-readable API docs at /llms.txt for LLM collaboration on circuit
design notebooks linked from Mims Electronics Reference Library.
Compose endpoint creates fully-populated notebooks in one call with
optional SPICE simulation. Per-cell try/except ensures partial simulation
failures don't lose the notebook.
Also extracts get_engine to spicebook.engine and makes
generate_notebook_id a public API.
The Inter SemiBold TTF from GitHub was an HTML error page. Switch to
loading inter-latin-600-normal.woff from @fontsource/inter in
node_modules — always available, always valid, and Satori supports
woff natively.
Node.js Buffer pool shares an ArrayBuffer — slice to give Satori's
OpenType parser a standalone copy starting at byte 0. Use process.env
instead of import.meta.env for BACKEND_INTERNAL_URL since Vite only
exposes PUBLIC_* prefixed vars via import.meta.env.
Wire astro-seo-meta for OG, Twitter Card, and canonical tags on all
pages. Add Satori + resvg dynamic OG image endpoints at /og/[id].png
with branded dark-theme cards. Replace inline SVGs with zero-JS
astro-icon rendering. SSR fetches use 5s AbortController timeout and
shared ID validation across all dynamic routes.
SchematicViewer now supports inline editing of component values
directly on the SVG. Clicking an editable value opens an overlay
input that updates the SPICE netlist on commit, triggering an
auto-redraw after 800ms debounce.
Added DOMPurify for SVG sanitization, netlist-utils for safe
value substitution in netlists, and wired schematic generation
through the notebook store with generation counters to discard
stale responses.
Parse netlists into component graphs and render circuit diagrams via
SchemDraw. Two layout strategies: loop layout for simple 2-terminal
circuits (RC, RL, voltage divider) and labeled grid for complex
circuits with active devices (BJT amplifiers, MOSFET).
Backend: netlist parser, schematic engine, POST API endpoint.
Frontend: SchematicViewer with zoom/download, stacked cell layout
showing schematic + SPICE editor + waveform simultaneously.
Vite inlines import.meta.env.PUBLIC_* at build time, not runtime.
Without this, the frontend falls back to localhost:8099 which doesn't
exist from the browser. Empty string means same-origin requests,
letting Caddy route /api/* to the backend.
Update frontend Dockerfile prod stage from Caddy static to Node.js
running Astro SSR server. Configure caddy-docker-proxy labels to
route /api/* to backend and everything else to frontend on the same
domain. Support empty PUBLIC_API_URL for same-origin API calls.
Switch from query-param routing (/notebook/?id=X) to Astro dynamic
routes (/notebook/rc-lowpass-filter). Add @astrojs/node adapter with
output: 'server' for on-demand route handling.
Fix formatEng/formatAxisValue crash on null values passed by uPlot
axis tick formatters. Add CORS origin for port 4322.