From 847e38e8a3e8868e93f34dae52509a3d3c120dd0 Mon Sep 17 00:00:00 2001 From: Ryan Malloy Date: Tue, 14 Jul 2026 22:47:59 -0600 Subject: [PATCH] Refresh docs-site from feature/lightning-talk Bring the docs-site tree up to date with the richer version built on the feature/lightning-talk line (guides, expanded reference, landing page) as the base for adding freeroute/routing documentation. Docs-site only; no source code from that branch is merged. --- docs-site/astro.config.mjs | 1 + docs-site/src/content/docs/index.mdx | 6 + docs-site/src/pages/lightning-talk.astro | 176 +++++++++++ docs-site/src/styles/lightning-talk.css | 373 +++++++++++++++++++++++ 4 files changed, 556 insertions(+) create mode 100644 docs-site/src/pages/lightning-talk.astro create mode 100644 docs-site/src/styles/lightning-talk.css diff --git a/docs-site/astro.config.mjs b/docs-site/astro.config.mjs index 9135203..04d2544 100644 --- a/docs-site/astro.config.mjs +++ b/docs-site/astro.config.mjs @@ -59,6 +59,7 @@ export default defineConfig({ { label: "Troubleshooting", slug: "development/troubleshooting" }, ], }, + { label: "Lightning Talk", link: "/lightning-talk/" }, ], head: [ { diff --git a/docs-site/src/content/docs/index.mdx b/docs-site/src/content/docs/index.mdx index e8eb348..2b74abc 100644 --- a/docs-site/src/content/docs/index.mdx +++ b/docs-site/src/content/docs/index.mdx @@ -75,3 +75,9 @@ mckicad just gives them a voice. description="Install mckicad and connect it to your first KiCad project." href="/getting-started/installation/" /> + + diff --git a/docs-site/src/pages/lightning-talk.astro b/docs-site/src/pages/lightning-talk.astro new file mode 100644 index 0000000..8daef3d --- /dev/null +++ b/docs-site/src/pages/lightning-talk.astro @@ -0,0 +1,176 @@ +--- +import "../styles/lightning-talk.css"; + +const title = "Teaching a language model to draw schematics"; +const description = + "A 90-second lightning talk on mckicad: why I replaced kicad-sch-api with an internal SchDocument engine, and what it unlocked."; + +// lucide-style icon paths (stroke, viewBox 24) +const icons = { + problem: '', + engine: '', + wire: '', + check: '', + zap: '', +}; + +const beats = [ + { + n: "01", + icon: icons.problem, + tag: "The problem", + heading: "The library kept lying to me", + body: [ + "mckicad is an MCP server that lets a language model design KiCad schematics on its own. For a long time it stood on kicad-sch-api — and that library kept returning wrong answers.", + "Global labels: dropped silently. Custom library pins: empty lists. When the layer you build on returns confident nonsense, nothing downstream can be trusted. So I did the reckless thing and ripped it out.", + ], + }, + { + n: "02", + icon: icons.engine, + tag: "The engine", + heading: "A parser that round-trips clean", + body: [ + "The heart is sexp_tree — a full S-expression parser and serializer for KiCad's native format. Parse it, mutate it, write it back, byte-for-byte identical.", + "On top sits SchDocument: load a schematic and ask it real questions. Where is every pin. What net is this wire on. Which labels actually connect. Answers from the file itself, not a guess.", + ], + }, + { + n: "03", + icon: icons.wire, + tag: "Autowire", + heading: "It routes around itself", + body: [ + "Place the components; autowire pulls the nets for you — with real collision detection, so wires route around each other instead of bridging into shorts.", + "It clamps stub lengths when they would overlap, offsets labels so they don't collide, and tracks power-wire stubs as obstacles. The messy part of drawing a schematic, done carefully.", + ], + }, + { + n: "04", + icon: icons.check, + tag: "It checks its own work", + heading: "One call, zero ambiguity", + body: [ + "run_schematic_erc runs the full electrical rules check and reports back: zero errors — or exactly what's wrong, and where.", + "The engine grades its own homework, so the model gets a hard signal instead of a hopeful vibe.", + ], + }, + { + n: "05", + icon: icons.zap, + tag: "The proof", + heading: "It drew Timbre", + body: [ + "It generated the phase-1 bench schematic for Timbre, a Cypress PSoC-based synthesizer. Zero ERC errors.", + "A language model, placing parts and pulling nets, for real hardware headed to a bench. That's the whole point.", + ], + }, +]; +--- + + + + + + + {title} · mckicad + + + + + + + + + + + Skip to the talk + +
+
+

Lightning talk · 90 seconds

+

{title}

+

+ I ripped out the library that kept lying to me and built an engine + that tells the truth. +

+ + + + +
+
+ +
+
    + { + beats.map((b) => ( +
  1. + + + {b.tag} + +

    {b.heading}

    + {b.body.map((p) => ( +

    + ))} +

  2. + )) + } +
+
+ +
+
+
+ 1,900 lines + of workaround code, deleted +
+
+ “Replaced by an engine that just tells the truth.” +
+ +
+
+ + diff --git a/docs-site/src/styles/lightning-talk.css b/docs-site/src/styles/lightning-talk.css new file mode 100644 index 0000000..ee70d4a --- /dev/null +++ b/docs-site/src/styles/lightning-talk.css @@ -0,0 +1,373 @@ +/* mckicad lightning talk — standalone phosphor-terminal narrative page. + Palette locked to the docs hero SVG so it reads as part of the product. */ + +:root { + --lt-bg: #0a1410; + --lt-panel: #0f1a14; + --lt-grid: #1a3a2a; + --lt-wire: #2d8659; + --lt-dim: #5a9e78; + --lt-bright: #a8dbbe; + --lt-ink: #d6ece0; + --lt-mute: #7a9d8c; + --lt-mono: "JetBrains Mono", ui-monospace, "Cascadia Code", "Source Code Pro", + Menlo, Consolas, "DejaVu Sans Mono", monospace; + --lt-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, + "Helvetica Neue", Arial, sans-serif; + --lt-maxw: 62rem; +} + +* { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body.lt { + margin: 0; + background: var(--lt-bg); + color: var(--lt-ink); + font-family: var(--lt-sans); + line-height: 1.6; + -webkit-font-smoothing: antialiased; + /* faint engineering-paper grid, echoing the hero schematic */ + background-image: + linear-gradient(var(--lt-grid) 0.5px, transparent 0.5px), + linear-gradient(90deg, var(--lt-grid) 0.5px, transparent 0.5px); + background-size: 28px 28px; + background-position: center top; +} + +/* faint CRT scanlines — decorative, killed for reduced-motion / it's opt-out via media */ +body.lt::before { + content: ""; + position: fixed; + inset: 0; + pointer-events: none; + z-index: 100; + background: repeating-linear-gradient( + 0deg, + rgba(0, 0, 0, 0.15) 0, + rgba(0, 0, 0, 0.15) 1px, + transparent 1px, + transparent 3px + ); + mix-blend-mode: multiply; + opacity: 0.35; +} + +.lt-wrap { + max-width: var(--lt-maxw); + margin: 0 auto; + padding: 0 1.25rem; +} + +a { + color: var(--lt-bright); +} + +/* ── skip link ─────────────────────────────── */ +.lt-skip { + position: absolute; + left: -999px; + top: 0; + background: var(--lt-wire); + color: #04120c; + padding: 0.5rem 0.9rem; + border-radius: 0 0 0.4rem 0; + font-family: var(--lt-mono); + z-index: 200; +} +.lt-skip:focus { + left: 0; +} + +/* ── hero ──────────────────────────────────── */ +.lt-hero { + padding: clamp(3rem, 9vw, 6.5rem) 0 clamp(2rem, 6vw, 4rem); + text-align: center; +} + +.lt-kicker { + font-family: var(--lt-mono); + font-size: 0.8rem; + letter-spacing: 0.28em; + text-transform: uppercase; + color: var(--lt-wire); + margin: 0 0 1.1rem; +} + +.lt-hero h1 { + font-size: clamp(2.1rem, 6.5vw, 4rem); + line-height: 1.05; + letter-spacing: -0.02em; + margin: 0 auto 1.1rem; + max-width: 18ch; + color: #eafff4; + text-shadow: 0 0 24px rgba(45, 134, 89, 0.35); +} + +.lt-lede { + font-size: clamp(1.05rem, 2.4vw, 1.35rem); + color: var(--lt-mute); + max-width: 46ch; + margin: 0 auto 2.25rem; +} + +/* terminal "scope" panel */ +.lt-scope { + max-width: 40rem; + margin: 0 auto 2rem; + text-align: left; + background: var(--lt-panel); + border: 1px solid var(--lt-grid); + border-radius: 0.7rem; + box-shadow: 0 0 0 1px rgba(45, 134, 89, 0.15), + 0 24px 60px -20px rgba(0, 0, 0, 0.8); + overflow: hidden; +} +.lt-scope-bar { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.6rem 0.9rem; + border-bottom: 1px solid var(--lt-grid); + font-family: var(--lt-mono); + font-size: 0.75rem; + color: var(--lt-mute); +} +.lt-dot { + width: 0.7rem; + height: 0.7rem; + border-radius: 50%; + background: var(--lt-grid); +} +.lt-scope-bar span { + margin-left: auto; +} +.lt-scope-body { + padding: 1.1rem 1.2rem 1.3rem; + font-family: var(--lt-mono); + font-size: clamp(0.8rem, 1.9vw, 0.95rem); + line-height: 1.7; +} +.lt-scope-body .cmd { + color: var(--lt-bright); +} +.lt-scope-body .cmd::before { + content: "mckicad › "; + color: var(--lt-wire); +} +.lt-scope-body .out { + color: var(--lt-dim); +} +.lt-scope-body .ok { + color: #7cf0b0; + text-shadow: 0 0 12px rgba(124, 240, 176, 0.5); +} +.lt-cursor { + display: inline-block; + width: 0.6ch; + height: 1.05em; + vertical-align: text-bottom; + background: var(--lt-bright); + margin-left: 0.15rem; + animation: lt-blink 1.1s steps(1) infinite; +} +@keyframes lt-blink { + 50% { + opacity: 0; + } +} + +/* action buttons */ +.lt-actions { + display: flex; + gap: 0.75rem; + justify-content: center; + flex-wrap: wrap; +} +.lt-btn { + font-family: var(--lt-mono); + font-size: 0.9rem; + text-decoration: none; + padding: 0.7rem 1.25rem; + border-radius: 0.45rem; + border: 1px solid var(--lt-wire); + display: inline-flex; + align-items: center; + gap: 0.5rem; + transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease; +} +.lt-btn svg { + width: 1.05em; + height: 1.05em; +} +.lt-btn.primary { + background: var(--lt-wire); + color: #04120c; + font-weight: 600; +} +.lt-btn.ghost { + color: var(--lt-bright); + background: transparent; +} +.lt-btn:hover { + transform: translateY(-1px); +} +.lt-btn.ghost:hover { + background: rgba(45, 134, 89, 0.12); +} + +/* ── beats ─────────────────────────────────── */ +.lt-beats { + list-style: none; + margin: 0; + padding: clamp(1rem, 4vw, 2.5rem) 0; + display: grid; + gap: clamp(1.25rem, 3vw, 2rem); +} +.lt-beat { + position: relative; + background: linear-gradient( + 180deg, + rgba(15, 26, 20, 0.9), + rgba(10, 20, 16, 0.9) + ); + border: 1px solid var(--lt-grid); + border-left: 3px solid var(--lt-wire); + border-radius: 0 0.7rem 0.7rem 0; + padding: clamp(1.4rem, 3.5vw, 2rem) clamp(1.3rem, 4vw, 2.4rem); + overflow: hidden; +} +/* ghosted giant numeral, SpiceBook-style */ +.lt-beat::after { + content: attr(data-n); + position: absolute; + top: -0.35em; + right: 0.1em; + font-family: var(--lt-mono); + font-weight: 700; + font-size: clamp(5rem, 16vw, 9rem); + line-height: 1; + color: var(--lt-wire); + opacity: 0.07; + pointer-events: none; +} +.lt-beat-tag { + display: inline-flex; + align-items: center; + gap: 0.5rem; + font-family: var(--lt-mono); + font-size: 0.72rem; + letter-spacing: 0.22em; + text-transform: uppercase; + color: var(--lt-wire); + margin-bottom: 0.7rem; +} +.lt-beat-tag svg { + width: 1.05rem; + height: 1.05rem; + stroke: var(--lt-wire); +} +.lt-beat h2 { + font-size: clamp(1.35rem, 3.4vw, 1.9rem); + line-height: 1.15; + letter-spacing: -0.01em; + margin: 0 0 0.6rem; + color: #eafff4; + max-width: 24ch; +} +.lt-beat p { + margin: 0; + color: var(--lt-mute); + max-width: 62ch; +} +.lt-beat p + p { + margin-top: 0.7rem; +} +.lt-beat code { + font-family: var(--lt-mono); + font-size: 0.9em; + color: var(--lt-bright); + background: rgba(45, 134, 89, 0.12); + padding: 0.1rem 0.4rem; + border-radius: 0.3rem; +} + +/* ── proof / closer ────────────────────────── */ +.lt-closer { + text-align: center; + padding: clamp(3rem, 8vw, 5.5rem) 0 clamp(4rem, 9vw, 6rem); + border-top: 1px solid var(--lt-grid); + margin-top: clamp(1rem, 4vw, 2rem); +} +.lt-stat { + font-family: var(--lt-mono); + font-weight: 700; + font-size: clamp(3rem, 12vw, 6.5rem); + line-height: 1; + color: #eafff4; + letter-spacing: -0.03em; + text-shadow: 0 0 30px rgba(45, 134, 89, 0.4); +} +.lt-stat small { + display: block; + font-family: var(--lt-mono); + font-weight: 400; + font-size: clamp(0.85rem, 2.2vw, 1.05rem); + letter-spacing: 0.24em; + text-transform: uppercase; + color: var(--lt-wire); + margin-top: 0.6rem; +} +.lt-closer blockquote { + margin: 2rem auto 0; + max-width: 34ch; + font-size: clamp(1.15rem, 3vw, 1.6rem); + line-height: 1.35; + color: var(--lt-ink); + font-style: italic; +} +.lt-closer footer { + margin-top: 2.75rem; + font-family: var(--lt-mono); + font-size: 0.82rem; + color: var(--lt-mute); +} +.lt-closer footer a { + color: var(--lt-bright); +} + +/* ── responsive niceties ───────────────────── */ +@media (min-width: 46rem) { + .lt-beat { + padding-right: clamp(4rem, 14vw, 8rem); + } +} + +/* ── accessibility: honour reduced motion ──── */ +@media (prefers-reduced-motion: reduce) { + html { + scroll-behavior: auto; + } + .lt-cursor { + animation: none; + } + body.lt::before { + display: none; + } + .lt-btn { + transition: none; + } +} + +/* clear focus rings everywhere */ +a:focus-visible, +.lt-btn:focus-visible { + outline: 2px solid var(--lt-bright); + outline-offset: 3px; + border-radius: 0.3rem; +}