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.
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
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.
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.
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.