Created
April 6, 2026 10:29
-
-
Save kasperpeulen/d6149e4cea17207f35b77b92dff69859 to your computer and use it in GitHub Desktop.
Building with AI Agents — Lessons from react-component-meta (Reveal.js presentation)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!doctype html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Building with AI Agents — Lessons from react-component-meta</title> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.css"> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/theme/black.css"> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/plugin/highlight/monokai.css"> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap'); | |
| @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&display=swap'); | |
| :root { | |
| --r-background-color: #0a0a0f; | |
| --r-main-color: #e6edf3; | |
| --r-heading-color: #ffffff; | |
| --r-link-color: #7c6aef; | |
| --accent: #7c6aef; | |
| --accent2: #f97316; | |
| --accent3: #22d3ee; | |
| --green: #3fb950; | |
| --red: #f85149; | |
| --yellow: #d29922; | |
| --dim: #6b7280; | |
| --card-bg: #12121a; | |
| --card-border: #1e1e2e; | |
| } | |
| .reveal { | |
| font-family: 'Inter', -apple-system, sans-serif; | |
| font-size: 28px; | |
| } | |
| .reveal h1, .reveal h2, .reveal h3 { text-transform: none; font-weight: 700; } | |
| .reveal h1 { font-size: 2em; line-height: 1.15; } | |
| .reveal h2 { font-size: 1.4em; line-height: 1.2; } | |
| .reveal h3 { font-size: 1em; color: var(--dim); font-weight: 500; } | |
| .reveal pre { width: 100%; font-size: 0.48em; box-shadow: none; } | |
| .reveal pre code { | |
| max-height: 520px; | |
| padding: 20px; | |
| border-radius: 12px; | |
| background: #12121a; | |
| border: 1px solid var(--card-border); | |
| font-family: 'JetBrains Mono', monospace; | |
| } | |
| .reveal ul, .reveal ol { font-size: 0.8em; } | |
| .reveal li { margin-bottom: 0.5em; line-height: 1.5; } | |
| .reveal table { font-size: 0.6em; margin: 0 auto; border-collapse: collapse; } | |
| .reveal table th { background: var(--card-bg); color: var(--accent); font-weight: 600; } | |
| .reveal table td, .reveal table th { padding: 10px 18px; border: 1px solid var(--card-border); } | |
| .reveal table tr:nth-child(even) { background: rgba(124, 106, 239, 0.03); } | |
| .reveal table tr:nth-child(odd) { background: var(--card-bg); } | |
| .reveal blockquote { | |
| background: var(--card-bg); | |
| border-left: 4px solid var(--accent); | |
| padding: 20px 28px; | |
| font-style: italic; | |
| width: 85%; | |
| border-radius: 0 12px 12px 0; | |
| font-size: 0.85em; | |
| line-height: 1.6; | |
| } | |
| .reveal blockquote footer { font-style: normal; color: var(--dim); margin-top: 8px; font-size: 0.85em; } | |
| .accent { color: var(--accent); } | |
| .accent2 { color: var(--accent2); } | |
| .accent3 { color: var(--accent3); } | |
| .green { color: var(--green); } | |
| .red { color: var(--red); } | |
| .yellow { color: var(--yellow); } | |
| .dim { color: var(--dim); } | |
| .bold { font-weight: 700; } | |
| .big-number { font-size: 4em; font-weight: 800; line-height: 1; } | |
| .medium-number { font-size: 2.5em; font-weight: 800; line-height: 1; } | |
| .card { | |
| background: var(--card-bg); | |
| border: 1px solid var(--card-border); | |
| border-radius: 16px; | |
| padding: 24px 28px; | |
| margin: 12px 0; | |
| text-align: left; | |
| } | |
| .card-row { | |
| display: flex; | |
| gap: 16px; | |
| justify-content: center; | |
| } | |
| .card-row .card { flex: 1; } | |
| .tweet { | |
| background: var(--card-bg); | |
| border: 1px solid var(--card-border); | |
| border-radius: 16px; | |
| padding: 24px 28px; | |
| max-width: 680px; | |
| margin: 16px auto; | |
| text-align: left; | |
| font-size: 0.78em; | |
| line-height: 1.55; | |
| } | |
| .tweet .tweet-author { | |
| font-weight: 700; | |
| color: #fff; | |
| margin-bottom: 4px; | |
| } | |
| .tweet .tweet-handle { color: var(--dim); font-weight: 400; } | |
| .tweet .tweet-body { margin-top: 12px; } | |
| .tweet .tweet-body em { color: var(--accent); font-style: normal; font-weight: 600; } | |
| .diagram-box { | |
| display: inline-block; | |
| background: var(--card-bg); | |
| border: 2px solid var(--card-border); | |
| border-radius: 12px; | |
| padding: 12px 20px; | |
| margin: 6px; | |
| font-size: 0.75em; | |
| font-weight: 500; | |
| } | |
| .diagram-box.active { border-color: var(--accent); color: var(--accent); } | |
| .diagram-box.green-border { border-color: var(--green); color: var(--green); } | |
| .diagram-box.orange-border { border-color: var(--accent2); color: var(--accent2); } | |
| .diagram-box.cyan-border { border-color: var(--accent3); color: var(--accent3); } | |
| .diagram-arrow { | |
| display: inline-block; | |
| color: var(--dim); | |
| font-size: 1.2em; | |
| margin: 0 4px; | |
| vertical-align: middle; | |
| } | |
| .flow-vertical { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 4px; | |
| } | |
| .flow-vertical .diagram-arrow { transform: rotate(90deg); } | |
| .tag { | |
| display: inline-block; | |
| padding: 4px 14px; | |
| border-radius: 20px; | |
| font-size: 0.65em; | |
| font-weight: 600; | |
| text-transform: uppercase; | |
| letter-spacing: 0.05em; | |
| } | |
| .tag-purple { background: rgba(124, 106, 239, 0.15); color: var(--accent); } | |
| .tag-orange { background: rgba(249, 115, 22, 0.15); color: var(--accent2); } | |
| .tag-green { background: rgba(63, 185, 80, 0.15); color: var(--green); } | |
| .tag-red { background: rgba(248, 81, 73, 0.15); color: var(--red); } | |
| .slide-number { font-size: 12px !important; } | |
| .reveal .slides section { overflow-y: auto; } | |
| .versus { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 24px; | |
| margin: 20px 0; | |
| } | |
| .versus .vs-label { | |
| font-size: 1.5em; | |
| font-weight: 800; | |
| color: var(--dim); | |
| } | |
| .timeline-item { | |
| display: flex; | |
| align-items: flex-start; | |
| gap: 16px; | |
| margin: 12px 0; | |
| font-size: 0.75em; | |
| } | |
| .timeline-dot { | |
| width: 12px; | |
| height: 12px; | |
| border-radius: 50%; | |
| margin-top: 6px; | |
| flex-shrink: 0; | |
| } | |
| .strikethrough { text-decoration: line-through; color: var(--dim); } | |
| .reveal .progress { color: var(--accent); height: 3px; } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="reveal"> | |
| <div class="slides"> | |
| <!-- ==================== TITLE ==================== --> | |
| <section> | |
| <p class="dim" style="margin-bottom: 8px; font-size: 0.7em;">Chromatic Engineering Talk</p> | |
| <h1 style="font-size: 1.7em;">How I Built a Competitor to<br><span class="accent">react-docgen-typescript</span><br>in Two Weeks</h1> | |
| <p style="margin-top: 24px; font-size: 0.85em;">And what I learned about working with AI agents</p> | |
| <p class="dim" style="margin-top: 40px; font-size: 0.7em;">Kasper Peulen · 2026</p> | |
| </section> | |
| <!-- ==================== THE CHALLENGE ==================== --> | |
| <section> | |
| <h2>The Challenge</h2> | |
| <div class="versus"> | |
| <div class="card" style="max-width: 280px; text-align: center;"> | |
| <p class="bold">react-docgen</p> | |
| <p class="dim" style="font-size: 0.7em;">Fast but inaccurate<br>AST-only, no type checking</p> | |
| </div> | |
| <div class="vs-label">vs</div> | |
| <div class="card" style="max-width: 280px; text-align: center;"> | |
| <p class="bold">react-docgen-typescript</p> | |
| <p class="dim" style="font-size: 0.7em;">Accurate but painfully slow<br>Full TS program per file</p> | |
| </div> | |
| </div> | |
| <div class="fragment" style="margin-top: 24px;"> | |
| <p style="font-size: 0.85em;">Can we build a <span class="accent bold">new competitor</span> that is both fast AND accurate?</p> | |
| <p class="dim" style="font-size: 0.7em;">Using Volar's battle-tested TS LanguageService architecture</p> | |
| </div> | |
| </section> | |
| <!-- ==================== THE BET ==================== --> | |
| <section> | |
| <h2>The Bet</h2> | |
| <p class="medium-number accent" style="margin: 20px 0;">2 weeks</p> | |
| <p style="font-size: 0.85em;">to build a production-ready, <span class="accent2 bold">battle-tested</span> tool<br>that works on <span class="green bold">real-world projects</span></p> | |
| <div class="card-row fragment" style="margin-top: 24px; font-size: 0.7em;"> | |
| <div class="card" style="text-align: center; padding: 14px;">Mantine<br><span class="dim">154 components</span></div> | |
| <div class="card" style="text-align: center; padding: 14px;">Primer<br><span class="dim">218 components</span></div> | |
| <div class="card" style="text-align: center; padding: 14px;">Flowbite<br><span class="dim">44 components</span></div> | |
| <div class="card" style="text-align: center; padding: 14px;">Park UI<br><span class="dim">54 components</span></div> | |
| <div class="card" style="text-align: center; padding: 14px;">Reshaped<br><span class="dim">63 components</span></div> | |
| </div> | |
| <p class="fragment dim" style="font-size: 0.7em; margin-top: 16px;">This talk is not about the results. It's about <span class="accent">how I used AI</span> to get there.</p> | |
| </section> | |
| <!-- ==================== PLAN MODE: THE PROBLEM ==================== --> | |
| <section> | |
| <h2>Why <span class="red">Plan Mode</span> Doesn't Work<br>for Big Projects</h2> | |
| </section> | |
| <section> | |
| <h2>Plan Mode: The Promise</h2> | |
| <div class="tweet"> | |
| <p class="tweet-author">Matt Pocock <span class="tweet-handle">@mattpocockuk</span></p> | |
| <div class="tweet-body"> | |
| Claude Code with and without plan mode is <em>night and day</em><br><br> | |
| No plan mode: code is so bad it's basically a liability to keep it<br><br> | |
| Plan mode: basically as good as I could write it, with occasional bugs which I catch on review<br><br> | |
| <em>Indispensable</em> | |
| </div> | |
| <p style="margin-top: 12px;"><a href="https://x.com/mattpocockuk/status/1977369846162534555" style="color: var(--dim); font-size: 0.75em;">View tweet →</a></p> | |
| </div> | |
| </section> | |
| <section> | |
| <h2>Plan Mode: The Reality</h2> | |
| <div class="tweet"> | |
| <p class="tweet-author">Matt Pocock <span class="tweet-handle">@mattpocockuk</span></p> | |
| <div class="tweet-body"> | |
| I have also <em>stopped using plan mode</em><br><br> | |
| It creates a plan <em>FAR too eagerly</em> and usually asks you <em>zero questions</em> en route<br><br> | |
| The whole point of planning is to get on the same wavelength with the LLM, not to generate an asset you don't read<br><br> | |
| <em>/grill-me all the way</em> | |
| </div> | |
| <p style="margin-top: 12px;"><a href="https://x.com/mattpocockuk/status/2039806494435074555" style="color: var(--dim); font-size: 0.75em;">View tweet →</a></p> | |
| </div> | |
| </section> | |
| <section> | |
| <h2>The Problem with Plan Mode</h2> | |
| <div style="text-align: left; max-width: 700px; margin: 0 auto;"> | |
| <div class="timeline-item fragment"> | |
| <div class="timeline-dot" style="background: var(--red);"></div> | |
| <div><span class="bold">Assumes too fast</span><br><span class="dim">Turns into a plan before understanding YOUR context</span></div> | |
| </div> | |
| <div class="timeline-item fragment"> | |
| <div class="timeline-dot" style="background: var(--red);"></div> | |
| <div><span class="bold">Asks zero questions</span><br><span class="dim">Jumps straight to implementation details</span></div> | |
| </div> | |
| <div class="timeline-item fragment"> | |
| <div class="timeline-dot" style="background: var(--red);"></div> | |
| <div><span class="bold">Generates an artifact you don't read</span><br><span class="dim">Plans are too long, too rigid, and hard to change</span></div> | |
| </div> | |
| <div class="timeline-item fragment"> | |
| <div class="timeline-dot" style="background: var(--red);"></div> | |
| <div><span class="bold">Kills the conversation</span><br><span class="dim">Planning should be a dialogue, not a document</span></div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- ==================== GRILL ME ==================== --> | |
| <section> | |
| <h2>The Alternative: <span class="accent">/grill-me</span></h2> | |
| </section> | |
| <section> | |
| <h2>The Grill-Me Skill</h2> | |
| <pre><code class="language-markdown" data-trim> | |
| --- | |
| name: grill-me | |
| --- | |
| Interview me relentlessly about every aspect of this plan | |
| until we reach a shared understanding. | |
| Walk down each branch of the design tree, | |
| resolving dependencies between decisions one-by-one. | |
| For each question, provide your recommended answer. | |
| Ask the questions one at a time. | |
| </code></pre> | |
| <p class="dim" style="font-size: 0.7em; margin-top: 12px;"> | |
| by <a href="https://github.com/mattpocock/skills" style="color: var(--accent);">Matt Pocock</a> | |
| </p> | |
| </section> | |
| <section> | |
| <h2>Conversation-First Design</h2> | |
| <div class="card" style="max-width: 680px; margin: 16px auto; font-size: 0.75em; line-height: 1.7;"> | |
| <p><span class="accent bold">Me:</span> "Could a Volar-based LanguageService solve our prop extraction perf problems?"</p> | |
| <p style="margin-top: 12px;"><span class="accent2 bold">Agent:</span> <em>researches Volar codebase</em> — "Volar is a perfect fit. It has great monorepo tsconfig support and would give you excellent warm benchmarks. 40 lines vs your 160."</p> | |
| <p style="margin-top: 12px;"><span class="accent bold">Me:</span> "This problem should be 100% solvable. The TS language server already gives correct autocomplete. Why can't we get correct props?"</p> | |
| <p style="margin-top: 12px;"><span class="accent2 bold">Agent:</span> "You're right. Story files already contain JSX. TypeScript already resolved those types. We don't need synthetic probes..."</p> | |
| </div> | |
| <p class="fragment" style="font-size: 0.8em; margin-top: 16px;"> | |
| The AI <span class="accent bold">asks questions</span> instead of <span class="red">assuming answers</span> | |
| </p> | |
| </section> | |
| <!-- ==================== THE SELF-HEALING LOOP ==================== --> | |
| <section> | |
| <h2>The <span class="green">Self-Healing</span> Loop</h2> | |
| </section> | |
| <section> | |
| <h2>My Agent Architecture</h2> | |
| <p class="dim" style="font-size: 0.75em; margin-bottom: 16px;">Multiple agents in separate terminal tabs, running in parallel</p> | |
| <div style="display: flex; gap: 16px; justify-content: center; align-items: stretch; margin: 16px 0;"> | |
| <!-- QA Agent --> | |
| <div class="card" style="flex: 1; max-width: 220px; text-align: center; border-color: var(--green);"> | |
| <p class="green bold">QA Agent</p> | |
| <p style="font-size: 0.65em; color: var(--dim); margin-top: 8px;">Runs the QA plan across all 5 projects with <span class="green">subagents</span> — one per project, in parallel</p> | |
| </div> | |
| <!-- Review Agent --> | |
| <div class="card" style="flex: 1; max-width: 220px; text-align: center; border-color: var(--accent3);"> | |
| <p class="accent3 bold">Review Agent</p> | |
| <p style="font-size: 0.65em; color: var(--dim); margin-top: 8px;">Fresh context every time. Reviews code with no prior bias. Catches what I missed.</p> | |
| </div> | |
| <!-- Fix Agent --> | |
| <div class="card" style="flex: 1; max-width: 220px; text-align: center; border-color: var(--accent2);"> | |
| <p class="accent2 bold">Fix Agent</p> | |
| <p style="font-size: 0.65em; color: var(--dim); margin-top: 8px;">Takes QA findings and review feedback, implements fixes, reruns tests</p> | |
| </div> | |
| </div> | |
| <div class="card fragment" style="max-width: 650px; margin: 16px auto; text-align: center; font-size: 0.75em; border-color: var(--accent);"> | |
| <p class="accent bold">When context fills up:</p> | |
| <p style="color: var(--dim); margin-top: 4px;">Tell the agent: "Write down what we've learned as a reusable plan."<br>Start a new session with that plan as input. No knowledge lost.</p> | |
| </div> | |
| <p class="dim" style="font-size: 0.65em; margin-top: 8px;">The QA plan itself was written by the AI after we successfully QA'd the first project together</p> | |
| </section> | |
| <section> | |
| <h2>The Secret: <span class="green">Real</span> Feedback Signals</h2> | |
| <div class="card-row" style="margin-top: 20px;"> | |
| <div class="card" style="font-size: 0.7em;"> | |
| <p class="green bold" style="font-size: 1.1em;">Accuracy Loop</p> | |
| <p>Does Mantine's Button still show 75 props?<br>Does Primer detect 218 components?</p> | |
| </div> | |
| <div class="card" style="font-size: 0.7em;"> | |
| <p class="accent2 bold" style="font-size: 1.1em;">Performance Loop</p> | |
| <p>Is Flowbite warm under 100ms?<br>Is Mantine cold under 15s?</p> | |
| </div> | |
| <div class="card" style="font-size: 0.7em;"> | |
| <p class="accent3 bold" style="font-size: 1.1em;">Regression Loop</p> | |
| <p>Add a prop → does it appear?<br>Remove it → does it disappear?</p> | |
| </div> | |
| </div> | |
| <p class="fragment" style="font-size: 0.85em; margin-top: 20px;"> | |
| Not toy tests. <span class="bold">5 real design systems.</span><br> | |
| <span class="dim">The feedback signal quality determines the output quality.</span> | |
| </p> | |
| </section> | |
| <section> | |
| <h2>The QA Plan: Written by AI</h2> | |
| <pre><code class="language-markdown" data-trim data-noescape> | |
| # QA Plan: react-component-meta — PR #33914 | |
| ## Test Projects | |
| | Project | Components | Props | Cold target | | |
| |----------|-----------|---------|-------------| | |
| | Flowbite | 43 | 321 | < 3s | | |
| | Reshaped | 63 | 842 | < 3s | | |
| | Park UI | 54 | 1,021 | < 6s | | |
| | Primer | 212 | 1,865 | < 5s | | |
| | Mantine | 154 | 10,292 | < 15s | | |
| ## For each component, verify: | |
| - displayName matches the intended component | |
| - required vs optional props are correct | |
| - default values are present | |
| - no key, ref, className floods leak in | |
| - member components only expose member's props | |
| </code></pre> | |
| <p class="dim" style="font-size: 0.65em; margin-top: 8px;">Excerpt from <code>rcm-qa-plan.md</code> — written by the AI after we QA'd the first project together</p> | |
| </section> | |
| <section> | |
| <h2>Plan Extraction: AI Handoff Documents</h2> | |
| <div style="text-align: left; max-width: 650px; margin: 0 auto; font-size: 0.8em;"> | |
| <div class="timeline-item"> | |
| <div class="timeline-dot" style="background: var(--accent);"></div> | |
| <div><span class="bold">Context fills up</span> → tell AI: "Write down what we've learned"</div> | |
| </div> | |
| <div class="timeline-item"> | |
| <div class="timeline-dot" style="background: var(--accent2);"></div> | |
| <div><span class="bold">AI writes a reusable plan</span> with baselines, scripts, status checkboxes</div> | |
| </div> | |
| <div class="timeline-item"> | |
| <div class="timeline-dot" style="background: var(--green);"></div> | |
| <div><span class="bold">New session</span> picks up the plan file as context</div> | |
| </div> | |
| </div> | |
| <div class="card fragment" style="max-width: 650px; margin: 20px auto; font-size: 0.65em;"> | |
| <p class="bold dim">Plans the AI wrote for this project:</p> | |
| <p style="margin-top: 8px;"> | |
| <code class="accent">volar-style-ls.md</code> → Architecture design<br> | |
| <code class="accent">probe-elimination.md</code> → Remove virtual probe files<br> | |
| <code class="accent">volar-adoption.md</code> → Replace hand-rolled infra with Volar<br> | |
| <code class="accent">rcm-qa-plan.md</code> → Full QA across 5 projects<br> | |
| <code class="accent">rpt-qa-plan.md</code> → Automated validation scripts | |
| </p> | |
| </div> | |
| </section> | |
| <section> | |
| <h2>Guarding Architecture Quality</h2> | |
| <div class="card" style="max-width: 650px; margin: 20px auto; font-size: 0.8em; line-height: 1.7; text-align: left;"> | |
| <p>Every time a bug was fixed, I asked:</p> | |
| <p style="margin-top: 16px; padding-left: 16px; border-left: 3px solid var(--accent); font-style: italic;"> | |
| "Check our Volar architecture plan. Are we still using the same battle-tested patterns that Volar uses? Don't regress quality to fix a bug." | |
| </p> | |
| </div> | |
| <div class="fragment" style="margin-top: 24px;"> | |
| <p style="font-size: 0.85em;">Without this, the agent <span class="red bold">drifts</span>.</p> | |
| <p class="dim" style="font-size: 0.75em; margin-top: 8px;">It fixes the symptom with a hack instead of following the proven pattern.<br>You need a <span class="accent bold">reference architecture</span> and constantly pull the agent back to it.</p> | |
| </div> | |
| </section> | |
| <!-- ==================== WHAT I GOT WRONG ==================== --> | |
| <section> | |
| <h2>What I Got <span class="red">Wrong</span></h2> | |
| </section> | |
| <section> | |
| <h2>After Two Weeks</h2> | |
| <div class="card-row" style="margin-top: 20px;"> | |
| <div class="card" style="text-align: center;"> | |
| <p class="green bold" style="font-size: 1.1em;">The Good</p> | |
| <p style="font-size: 0.7em;"> | |
| 100% accurate<br> | |
| 48-80x faster warm times<br> | |
| All 5 projects passing<br> | |
| Product-ready | |
| </p> | |
| </div> | |
| <div class="card" style="text-align: center;"> | |
| <p class="red bold" style="font-size: 1.1em;">The Bad</p> | |
| <p style="font-size: 0.7em;"> | |
| I didn't understand the code<br> | |
| Hacky perf solutions<br> | |
| Unreadable unit tests<br> | |
| Impossible to review | |
| </p> | |
| </div> | |
| </div> | |
| </section> | |
| <section> | |
| <h2>The Review That Proved It</h2> | |
| <div class="tweet"> | |
| <p class="tweet-author">Jeppe Reinhold <span class="tweet-handle">PR #33914 review</span></p> | |
| <div class="tweet-body"> | |
| "<em>The biggest one probably being about the lack of readability on the tests.</em>"<br><br> | |
| • Test readability — couldn't understand what was being tested<br> | |
| • Architecture documentation — needed a mermaid diagram<br> | |
| • PR size — massive and hard to review<br> | |
| • Could it have been broken into smaller PRs? | |
| </div> | |
| </div> | |
| <p class="fragment" style="font-size: 0.8em; margin-top: 16px;"> | |
| I completely rewrote the tests. <span class="green">Jeppe approved the next day.</span> | |
| </p> | |
| </section> | |
| <section> | |
| <h2>What I Should Have Done</h2> | |
| <div style="text-align: left; max-width: 680px; margin: 0 auto;"> | |
| <div class="timeline-item fragment"> | |
| <div class="timeline-dot" style="background: var(--green);"></div> | |
| <div><span class="bold green">TDD from day one</span><br><span class="dim">Own the unit tests. Make them readable. The agent can self-heal if tests are clear.</span></div> | |
| </div> | |
| <div class="timeline-item fragment"> | |
| <div class="timeline-dot" style="background: var(--green);"></div> | |
| <div><span class="bold green">Look at the code earlier</span><br><span class="dim">I was too focused on results. Melting it into shape afterwards was way more expensive.</span></div> | |
| </div> | |
| <div class="timeline-item fragment"> | |
| <div class="timeline-dot" style="background: var(--green);"></div> | |
| <div><span class="bold green">Enforce architecture from the start</span><br><span class="dim">Keep it decoupled. Self-isolated. Like an open-source library you build yourself.</span></div> | |
| </div> | |
| <div class="timeline-item fragment"> | |
| <div class="timeline-dot" style="background: var(--green);"></div> | |
| <div><span class="bold green">Accept the tradeoff</span><br><span class="dim">Not understanding every line is OK. This would have taken 8+ weeks by hand. We couldn't bet on it.</span></div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- ==================== THE REAL SECRET ==================== --> | |
| <section> | |
| <h2>The Real Secret</h2> | |
| <div style="margin: 30px 0;"> | |
| <div class="card" style="max-width: 650px; margin: 0 auto; text-align: center; padding: 30px;"> | |
| <p style="font-size: 1.1em; line-height: 1.6;"> | |
| <span class="tag tag-green" style="font-size: 0.7em;">TDD</span> so the agent can <span class="green bold">self-heal</span> the tests | |
| </p> | |
| <p style="font-size: 0.5em; color: var(--dim); margin: 12px 0;">+</p> | |
| <p style="font-size: 1.1em; line-height: 1.6;"> | |
| <span class="tag tag-orange" style="font-size: 0.7em;">Manual QA Plans</span> on <span class="accent2 bold">real projects</span> | |
| </p> | |
| <p style="font-size: 0.65em; color: var(--dim); margin: 4px 0;">Unit tests alone are too synthetic. You need real-world validation.</p> | |
| <p style="font-size: 0.5em; color: var(--dim); margin: 12px 0;">=</p> | |
| <p style="font-size: 1.1em; line-height: 1.6;"> | |
| <span class="tag tag-purple" style="font-size: 0.7em;">Self-Healing Loop</span> that <span class="accent bold">actually works</span> | |
| </p> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- ==================== ADEs ==================== --> | |
| <section> | |
| <h2>The Rise of <span class="accent">ADEs</span></h2> | |
| <p class="dim" style="font-size: 0.8em;">Agent Development Environments</p> | |
| </section> | |
| <section> | |
| <h2>CLI Was Great, But...</h2> | |
| <div style="text-align: left; max-width: 680px; margin: 0 auto;"> | |
| <div class="timeline-item fragment"> | |
| <div class="timeline-dot" style="background: var(--dim);"></div> | |
| <div><span class="bold">Multiple terminal tabs</span><br><span class="dim">I ran QA, fix, and review agents in separate tabs</span></div> | |
| </div> | |
| <div class="timeline-item fragment"> | |
| <div class="timeline-dot" style="background: var(--red);"></div> | |
| <div><span class="bold">Close terminal = lose session</span><br><span class="dim">Hard to get back to past sessions</span></div> | |
| </div> | |
| <div class="timeline-item fragment"> | |
| <div class="timeline-dot" style="background: var(--red);"></div> | |
| <div><span class="bold">No git diff visibility</span><br><span class="dim">Hard to see what agents actually changed</span></div> | |
| </div> | |
| <div class="timeline-item fragment"> | |
| <div class="timeline-dot" style="background: var(--red);"></div> | |
| <div><span class="bold">Can't inspect subagents</span><br><span class="dim">You want to quickly see progress of all running agents and switch between them</span></div> | |
| </div> | |
| <div class="timeline-item fragment"> | |
| <div class="timeline-dot" style="background: var(--red);"></div> | |
| <div><span class="bold">VS Code / Cursor = one project</span><br><span class="dim">You need to manage 5 different agents working for you simultaneously</span></div> | |
| </div> | |
| </div> | |
| </section> | |
| <section> | |
| <h2>What ADEs Give You</h2> | |
| <div class="card-row" style="margin-top: 20px;"> | |
| <div class="card" style="font-size: 0.7em;"> | |
| <p class="accent bold" style="font-size: 1.1em;">Session Persistence</p> | |
| <p>Close and come back.<br>Your agents are still running.</p> | |
| </div> | |
| <div class="card" style="font-size: 0.7em;"> | |
| <p class="accent2 bold" style="font-size: 1.1em;">Git Worktrees</p> | |
| <p>Multiple agents on the same repo<br>without conflicts.</p> | |
| </div> | |
| <div class="card" style="font-size: 0.7em;"> | |
| <p class="accent3 bold" style="font-size: 1.1em;">Agent Inspection</p> | |
| <p>See subagents in your UI.<br>Inspect what they're doing.</p> | |
| </div> | |
| </div> | |
| <div class="card fragment" style="max-width: 600px; margin: 20px auto; text-align: center; font-size: 0.75em;"> | |
| <p class="dim">Codex Desktop · Claude Code Desktop · Emdash · ctx</p> | |
| <p style="margin-top: 8px;">The <span class="accent bold">self-healing loop</span> I did manually is becoming a <span class="green bold">built-in feature</span></p> | |
| </div> | |
| </section> | |
| <section> | |
| <h2>Auto-Fix CI Loop</h2> | |
| <p style="font-size: 0.85em; margin-bottom: 20px;">Claude Code Desktop can now <span class="green bold">automatically</span>:</p> | |
| <div style="margin: 20px 0;"> | |
| <div class="diagram-box" style="margin: 8px;">Push code</div> | |
| <span class="diagram-arrow">→</span> | |
| <div class="diagram-box orange-border" style="margin: 8px;">CI fails</div> | |
| <span class="diagram-arrow">→</span> | |
| <div class="diagram-box cyan-border" style="margin: 8px;">Agent investigates</div> | |
| <span class="diagram-arrow">→</span> | |
| <div class="diagram-box green-border" style="margin: 8px;">Pushes fix</div> | |
| </div> | |
| <div class="fragment" style="margin-top: 24px;"> | |
| <p style="font-size: 0.85em;">But the <span class="accent bold">real power</span> is still:</p> | |
| <div class="card" style="max-width: 500px; margin: 12px auto; text-align: center; font-size: 0.8em;"> | |
| <p><span class="green bold">TDD</span> → so it knows how to fix<br> | |
| <span class="accent2 bold">QA Plans</span> → so it knows what to check</p> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- ==================== HOW TO GET BETTER ==================== --> | |
| <section> | |
| <h2>How I Progressed in<br><span class="accent">Agentic Programming</span></h2> | |
| </section> | |
| <section> | |
| <h2>I Just Try to Do <span class="accent">Everything</span> with AI</h2> | |
| <p class="dim" style="font-size: 0.75em; margin-bottom: 20px;">Even when it seems weird or hard</p> | |
| <div class="card-row" style="margin-top: 16px;"> | |
| <div class="card" style="font-size: 0.7em; text-align: center;"> | |
| <p class="bold" style="font-size: 1.1em;">The obvious</p> | |
| <p class="dim">Implementation<br>Refactoring<br>Bug fixes</p> | |
| </div> | |
| <div class="card" style="font-size: 0.7em; text-align: center;"> | |
| <p class="accent bold" style="font-size: 1.1em;">Less obvious</p> | |
| <p class="dim">Opening PRs<br>Writing issues<br>Code review</p> | |
| </div> | |
| <div class="card" style="font-size: 0.7em; text-align: center;"> | |
| <p class="accent2 bold" style="font-size: 1.1em;">Seemed weird at first</p> | |
| <p class="dim">Full manual QA<br>Presentations<br>Research</p> | |
| </div> | |
| </div> | |
| <div class="fragment" style="margin-top: 24px;"> | |
| <blockquote style="font-size: 0.85em;"> | |
| Starting to do <span class="accent2 bold">manual QA with agents</span> was a key unlocker for me.<br><br> | |
| It's not always faster at first.<br> | |
| But <span class="accent bold">trying is how you learn</span>.<br> | |
| And along the way you discover skills, plans, and loops that actually make you faster. | |
| </blockquote> | |
| </div> | |
| </section> | |
| <section> | |
| <h2>My Workflow Today</h2> | |
| <div style="text-align: left; max-width: 680px; margin: 0 auto;"> | |
| <div class="timeline-item"> | |
| <div class="timeline-dot" style="background: var(--accent);"></div> | |
| <div><span class="bold accent">1. Grill-me</span><br><span class="dim">Have a conversation. Let the AI ask questions. Arrive at shared understanding.</span></div> | |
| </div> | |
| <div class="timeline-item"> | |
| <div class="timeline-dot" style="background: var(--green);"></div> | |
| <div><span class="bold green">2. TDD the acceptance criteria</span><br><span class="dim">Write clear, readable tests that define "done". Own them.</span></div> | |
| </div> | |
| <div class="timeline-item"> | |
| <div class="timeline-dot" style="background: var(--accent2);"></div> | |
| <div><span class="bold accent2">3. Let it implement</span><br><span class="dim">Tell the agent when to start coding. Not before.</span></div> | |
| </div> | |
| <div class="timeline-item"> | |
| <div class="timeline-dot" style="background: var(--accent3);"></div> | |
| <div><span class="bold accent3">4. Self-healing loop</span><br><span class="dim">QA on real projects. Fix. Repeat. Start fresh sessions often — write plan extraction docs to keep implementation clean. Or use subagents to guard against context overflow.</span></div> | |
| </div> | |
| <div class="timeline-item"> | |
| <div class="timeline-dot" style="background: #fff;"></div> | |
| <div><span class="bold">5. Review the architecture</span><br><span class="dim">Not every line. But: is it decoupled? Is it testable? Can someone else understand it?</span></div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- ==================== TAKEAWAY ==================== --> | |
| <section> | |
| <div style="margin: 40px 0;"> | |
| <p class="dim" style="font-size: 0.7em; margin-bottom: 20px;">The Takeaway</p> | |
| <h1 style="font-size: 1.6em; line-height: 1.4;"> | |
| Don't let the AI <span class="red">assume</span>.<br> | |
| <span class="accent">Grill it.</span><br> | |
| Give it <span class="accent2">real acceptance criteria</span><br> | |
| against <span class="green">real projects</span>.<br> | |
| Let it <span class="accent3">self-heal</span> until it passes. | |
| </h1> | |
| </div> | |
| </section> | |
| <section> | |
| <p class="dim" style="font-size: 0.7em; margin-bottom: 20px;">And most importantly</p> | |
| <h1 style="font-size: 1.5em; line-height: 1.4;"> | |
| Try to do <span class="accent">everything</span> with AI<br> | |
| for a week. | |
| </h1> | |
| <p class="fragment" style="font-size: 0.9em; margin-top: 24px;"> | |
| You'll find many things it's not great at yet.<br> | |
| But you'll also <span class="accent2 bold">discover new things</span> where it's surprisingly good. | |
| </p> | |
| <p class="fragment" style="font-size: 0.8em; margin-top: 16px;"> | |
| <span class="dim">That is a great way to learn and become better at agentic programming.</span> | |
| </p> | |
| <p class="fragment dim" style="font-size: 0.7em; margin-top: 32px;"> | |
| (This presentation was also built with AI.) | |
| </p> | |
| </section> | |
| <!-- ==================== END ==================== --> | |
| <section> | |
| <h1 style="font-size: 1.4em;">Thank You</h1> | |
| <p style="margin-top: 20px; font-size: 0.85em;"> | |
| <span class="dim">PR:</span> <a href="https://github.com/storybookjs/storybook/pull/33914" style="color: var(--accent);">storybookjs/storybook#33914</a> | |
| </p> | |
| <p style="font-size: 0.75em; margin-top: 12px;"> | |
| <span class="dim">Grill-me skill:</span> <a href="https://github.com/mattpocock/skills" style="color: var(--accent);">github.com/mattpocock/skills</a> | |
| </p> | |
| <p style="font-size: 0.75em; margin-top: 8px;"> | |
| <span class="dim">Kasper Peulen</span> | |
| </p> | |
| </section> | |
| </div> | |
| </div> | |
| <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/plugin/highlight/highlight.js"></script> | |
| <script> | |
| Reveal.initialize({ | |
| hash: true, | |
| slideNumber: true, | |
| transition: 'fade', | |
| transitionSpeed: 'fast', | |
| center: true, | |
| width: 1100, | |
| height: 700, | |
| margin: 0.08, | |
| plugins: [RevealHighlight] | |
| }); | |
| // Re-render Twitter embeds when slide becomes visible | |
| Reveal.on('slidechanged', () => { | |
| if (window.twttr && twttr.widgets) { | |
| twttr.widgets.load(); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment