Kestrel Gives: rebuilding a charity auction with AI
A from-memory rebuild of a charity auction web app I designed and built on my own at Netflix, shipped with Claude Code in about four days.

In brief
- The problem
- At Netflix I was the only designer and engineer on a web app that replaced the manual parts of a hand-run charity auction (a form, a spreadsheet, and a lot of email), but I can't show it. I wanted a public version that shows how I design and build with AI, without any of the original code, designs, or data.
- What changed
- A working public demo with bidding, inventory, donation proof, and an admin dashboard, live in about four days across eight milestones and passing 764 automated checks, including accessibility in light and dark mode.
- My part
- I wrote the spec, set the visual direction, made the logos, and reviewed every stage at a checkpoint before anything went live. Claude Code wrote the code. I used Claude in a separate chat to help finish the spec and as a second reviewer at each checkpoint.
Keep reading for the full story, or skip to the next case study, Making the banner API worth adopting →
The full story
The old auction ran on a form, a spreadsheet, and a lot of email
Every December, the Experience Design org at Netflix ran a charity auction for a few days, and three hosts did all the work. Items came in through a Google Form and landed in a spreadsheet with a tab for each one. The hosts listed every silent auction and instant sale item on a Google Site by hand. Clicking an item opened its tab, where people typed their email address and a bid, or a quantity and the total they owed.
When the auction closed, the hosts went through every tab to work out who had won each silent auction item and who had bought what. They emailed each person what they owed with a link to donate, and then checked off the receipt screenshots people emailed back. With a few dozen items each year, all of that was done by hand.
I built a replacement at Netflix, and I couldn’t show it
The hosts ran the event; my part was the software. In September and October of 2026, I built XD Made, an internal web app for the few hundred people in the org, and I was the only designer and engineer on it, working with Figma Make and Claude Code. Each manual step became part of the app: people submitted items on a form, bid and bought on the item pages, saw the current high bid, and uploaded their donation proof in one place, while the app worked out winners and totals and sent the emails. Payments stayed on the company’s giving platform. The app ran on Netflix’s internal infrastructure and passed a security review. Item submissions had just opened when I was laid off, so I never saw the auction finish, but the hosts had already told me it saved them a lot of manual work.
After I left, I still had the code, but I wasn’t going to use it or show it. So I rebuilt it from memory as Kestrel Gives, for a fictional company called Kestrel, with invented people, items, and charities. The first line of my instructions to Claude Code set the rule:
Build everything from scratch. Do not search my computer for,
open, or reference any code from the original. If you come
across it, stop and tell me.
The hard part was the rules and the demo
Most of the work in an auction site is in its rules. Two people bid at the same moment. Two people buy the last unit. An admin removes the winning bid after bidding closes, so the winner changes and two people’s totals move, possibly after one of them already uploaded proof of a donation.

A portfolio demo added its own problems. Anyone can visit, so everyone shares the same data. A real event takes weeks from the first submission to the last proof, but a hiring manager will spend five minutes. I also needed a way to keep code written by AI consistent across a few hundred changes.
I wrote the spec first, one question at a time
Before any code, I spent a day turning my memory of the original into a spec, answering one question at a time in a Claude chat. Some of my answers corrected Claude’s suggestions. It proposed 12 demo users; I cut it to 7, two of them admins. It proposed per-item donation proofs; I chose one combined proof per person, because each donation is split evenly across three charities and people give once. I also made amounts whole dollars everywhere, which simplified both the forms and the math.
The spec became the contract for every change: design tokens only, WCAG 2.2 AA in light and dark mode, approved dependencies only, and eight conformance checks that had to pass at every checkpoint. It grew from version 1.0 to 1.23 as the build answered questions the spec hadn’t, and Claude Code logged 135 decisions with the options it considered and why.
The demo needed its own design
A bar across the top lets a visitor view the site as any of the seven people, jump the event to another phase, and restore the original data. Jumping moves the event’s dates instead of faking the clock, so the real rules run in every phase. Because the demo is shared, it restores itself every night, and the bar says so.

One decision changed late. Jumping back to “Submissions open” left every bid in place, so an item showed “Top bid · 6 bids” next to a banner saying bidding hadn’t started. Claude Code suggested leaving it and explaining it in the README. I decided that nobody reads a README while clicking around a demo, so that jump now clears bids, purchases, and proofs, asks first, and Restore brings them back.
Checkpoints caught what the tests didn’t
Each milestone was planned, then built in small stages, and every stage stopped at a checkpoint: all checks passing, a preview deployment, and screenshots in light and dark at phone and desktop widths. Nothing reached the live site until I approved it.
The tests caught the logic problems. When two bids arrive at the same moment, exactly one is saved and the other person sees the new minimum. A test found a deadlock between restoring the demo and a normal request, and another test turned out to pass without checking anything, which Claude Code noticed and rewrote.

The screenshots caught problems the tests couldn’t see. Tiles styled “Top bid $50” entirely in the large red price style, so the label was as loud as the number. A lost auction read “Your bid · Won at $240”, which looked like a win. In dark mode, the bright yellow phase banner was the loudest thing on the page, and a cancelled item still showed a crown on its top bidder. Each one was a small fix.
I made mistakes too
I pasted a database connection string, with its password, into a chat by mistake. Since branches copy passwords from their parent, I treated the production and development passwords as exposed too. We rotated all three in an order that kept the live site connected, and the only outage was the health check for a couple of minutes.
The seed photos took more work than I expected. The first stock site’s API had paused new keys, and the photo license meant the original files couldn’t sit in a public repo, so they moved to storage outside git. When Claude Code’s research showed that a burst of traffic could lock the free storage plan for 30 days, I upgraded to the paid plan instead of risking a broken demo while recruiters were looking at it.
How I built it
The app is plain HTML, CSS, and TypeScript with no framework, on Vercel with a Neon Postgres database. Claude Code wrote all of the code. My job was the spec, the design direction, the logos, and the decisions at each checkpoint. I first asked AI for logo concepts and didn’t like any of them, so I made the kestrel marks myself; Claude Code uses them unmodified.
Live in about four days
Kestrel Gives went live about four days after kickoff, nights included, across eight milestones. The final run passed 310 unit tests, 120 database tests, 288 accessibility and keyboard tests, 21 reflow tests at 320 pixels wide, and 25 visual tests covering 288 screenshots. The live demo has a short tour, and the repo includes the spec, every decision, and a build log of each stage.
If I did it again, I’d plan the shared demo before the data model, since phases, jumping, and restoring shaped more of the database than I expected.