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