spicebook/frontend/src/pages/index.astro
Ryan Malloy 4b2ce896b5 Replace static hero scope with interactive XY-mode oscilloscope
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
2026-02-20 16:25:13 -07:00

114 lines
4.2 KiB
Plaintext

---
import { Icon } from 'astro-icon/components';
import NotebookLayout from '../layouts/NotebookLayout.astro';
import NotebookGallery from '../components/NotebookGallery';
import PipelineStrip from '../components/PipelineStrip.astro';
import FeaturedNotebooks from '../components/FeaturedNotebooks.astro';
import OscilloscopeDisplay from '../components/OscilloscopeDisplay.astro';
import { fetchNotebookList } from '../lib/server-api';
import type { NotebookSummary } from '../lib/types';
let notebooks: NotebookSummary[] = [];
let fetchError: string | null = null;
try {
notebooks = await fetchNotebookList();
} catch (err) {
fetchError = err instanceof Error ? err.message : 'Backend unavailable';
}
---
<NotebookLayout
title="SpiceBook"
description="Write SPICE netlists, run ngspice simulations, and visualize waveforms in a single document."
canonicalPath="/"
>
<style>
@import '../styles/homepage.css';
@import '../styles/oscilloscope.css';
</style>
<!-- Hero: Split layout — text left, animated scope visual right -->
<section class="hero-graticule border-b border-slate-800/60">
<div class="relative max-w-6xl mx-auto px-6 pt-16 pb-20">
<div class="grid md:grid-cols-2 gap-12 items-center">
<!-- Left: Copy + CTAs -->
<div>
<p class="text-sm font-semibold tracking-widest text-blue-400 uppercase mb-4">SpiceBook</p>
<h1 class="text-4xl md:text-5xl font-bold text-slate-100 tracking-tight">
Circuit Simulation Notebooks
</h1>
<p class="mt-4 text-lg text-slate-400 max-w-xl leading-relaxed">
Write SPICE netlists, run ngspice simulations, and visualize waveforms in a single document.
</p>
<div class="flex items-center gap-3 mt-8">
<a
href="/notebook/new"
class="inline-flex items-center gap-2 px-5 py-2.5 rounded-lg bg-blue-600 hover:bg-blue-500 text-white font-medium transition-colors text-sm"
>
<Icon name="lucide:plus" class="w-4 h-4" />
New Notebook
</a>
<a
href="#notebooks"
class="inline-flex items-center gap-2 px-5 py-2.5 rounded-lg border border-slate-700 text-slate-300 hover:border-slate-500 hover:text-slate-100 font-medium transition-colors text-sm"
>
Browse Notebooks
<Icon name="lucide:chevron-down" class="w-4 h-4" />
</a>
</div>
</div>
<!-- Right: Interactive XY-mode oscilloscope -->
<div class="flex justify-center md:justify-end">
<OscilloscopeDisplay />
</div>
</div>
</div>
</section>
<!-- Pipeline: Write → Simulate → Visualize -->
<section class="border-b border-slate-800/60">
<PipelineStrip />
</section>
<!-- Featured Notebooks -->
<section class="border-b border-slate-800/60">
<FeaturedNotebooks />
</section>
<!-- Notebook Gallery -->
<section id="notebooks" class="max-w-6xl mx-auto px-6 py-20 scroll-mt-8">
<div class="mb-8">
<h2 class="text-2xl font-bold text-slate-100">Explore Notebooks</h2>
{notebooks.length > 0 && (
<p class="text-sm text-slate-500 mt-1">{notebooks.length} notebooks available</p>
)}
</div>
<NotebookGallery
client:load
initialNotebooks={notebooks}
error={fetchError}
/>
</section>
<!-- Footer CTA -->
<footer class="border-t border-slate-800/60">
<div class="max-w-6xl mx-auto px-6 py-16 text-center">
<h2 class="text-2xl font-bold text-slate-100 mb-2">Start with a blank notebook</h2>
<p class="text-sm text-slate-400 mb-6">Write a SPICE netlist, run it, see results in seconds.</p>
<a
href="/notebook/new"
class="inline-flex items-center gap-2 px-5 py-2.5 rounded-lg bg-blue-600 hover:bg-blue-500 text-white font-medium transition-colors text-sm"
>
<Icon name="lucide:plus" class="w-4 h-4" />
New Notebook
</a>
<p class="text-sm text-slate-500 mt-6">
Built on ngspice · Part of <a href="https://warehack.ing" class="text-slate-400 hover:text-slate-300 underline underline-offset-2">warehack.ing</a>
</p>
</div>
</footer>
</NotebookLayout>