Designer and director · Personal, Portfolio project, 2026

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.

Kestrel Gives in a browser and on a phone: the Silent Auction page with item cards for weekend dog-sitting, help planting a vegetable bed, homemade pasta night and a bike tune-up, and an item page for the dog-sitting with a You're winning badge on a $50 bid.
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 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.

The Admin Dashboard’s Totals tab: pledged and confirmed amounts for silent auction, instant sale and the grand total, with a separate panel for leading bids that aren’t final yet.

Admin totals keep pledged and confirmed money apart, and show leading bids separately until bidding closes.

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.

The demo bar: a Viewing as menu set to an employee, Jump to buttons for each phase of the event, and a Restore demo data button.

The demo bar: who you're viewing as, which phase the event is in, and a way to put everything back.

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.

An item page after losing a bidding race: the bid field shows the new minimum of $255, with a message under it saying someone just bid $250.

Losing a race: the field refills with the new minimum and the reason appears under it.

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.