This is a recording of a live stream I did on September 16th, a few weeks back. Almost nobody tuned in, which suited me. I wanted a record of what building with an AI agent looks like when nobody has cleaned it up. BossFight has been in production since mid-September, and it has come a long way since this stream, so what you’ll see is the app mid-build, with a lot of mock data. I built it from scratch, and I wanted to show you what that looks like when you start from nothing.
What BossFight is
BossFight (bossfight.net) is an interactive map of every 2026 U.S. House and Senate race, ranked by how competitive the money says it is. Click a race and you get a bracket of the candidates. Click a candidate and you get their profile. Hit head-to-head and you get a tale-of-the-tape comparison.
Why I built it
I built BossFight to make sure the people who get voted in are doing their job. Voting is the easy part. Checking up on them afterward is hard.
None of this is secret. Every federal contribution is disclosed. Every roll call vote is recorded. Every lobbying engagement is filed quarterly. Every foreign agent registers. Who influences whom has been sitting in public archives for decades, but the records are scattered across agencies in formats built for compliance, not for people. Nobody can read them. BossFight puts the money, the votes, and the timeline side by side where a regular voter can actually see them. The site has a page called Why that lays this out, and in the stream you’ll see me read it (and admit the AI wrote the first draft of that copy).
It also comes from something that bugs me every election cycle. Candidates say one thing and do another, and the noise of ads, mailers, and 30-second spiels drowns out the record. I’d rather a voter see something closer to a resume: what this person has done, who funds them, how they voted, and whether they kept their promises. And I want the site to be honest about which of those facts are sourced and which we simply don’t know yet.
Why I’m sharing this here
BossFight has already been shared in other places. I saved Radical Insider for last on purpose. This newsletter is mostly about AI and software, and I know some of you are allergic to politics. That’s fine, and I’m not trying to change anyone’s mind. My job on this project was the data approach: pull public records together, label what’s real and what isn’t, and let people look for themselves. This post is really about how it got built, which is why it belongs here.
For the record, I’m mostly politically homeless. I’m capitalist, but I believe in some progressive policies that make sense. I also believe in AI, though not without its issues. Some of them are truly serious, just not the kinds the media tends to focus on.
With the midterms coming up, there’s plenty out there for people to get informed on. For me, it’s the money: how it flows into our public system and how it influences policy. I think it’s important to participate in the political process, despite how frustrating it can be. And it’s bullshit to complain about the government when you don’t participate in it.
So here’s my cheat sheet. Know what kind of money flows into these candidates’ coffers, and understand that it has a much bigger influence than what they say at the podium. That doesn’t mean all PACs are bad. It does mean it’s important to understand what kind of money goes in. Yes, the system kind of sucks, but I decided to try to solve it, and this is one way.
The rule the whole project hangs on
You’ll hear me say “this is still a mock” a lot, and that’s deliberate. Candidate name, party, incumbency, and money raised are real, sourced from FEC bulk data. Anything the pipeline doesn’t have yet, such as polling, ground-game scores, or endorsements, is labeled DEMO in the app and kept generic, never a specific-sounding claim about a real person. A site about real politicians that quietly invents plausible details is worse than no site. That rule now lives in the code: the curated-data layer rejects any claim without a source URL, and it keeps “nobody checked” and “checked and found nothing” as separate states.
The app has moved well past this stream
A lot has changed since September 16th. Much of the data I’m mocking up on stream has since been pulled in for real, so the live site shows far more than this recording does. Polls and forecaster ratings, outside spending, where each candidate’s donations come from by state, and recorded votes are all in the pipeline now. The best way to see it is to visit the site.
The part I’m proudest of is The Chamber, which covers the Senate and House seats visually. It draws all 100 Senate seats and 435 House seats as one hemicycle. Seats held by each party sit on the left and right, and the seats actually in play form a purple block in the middle, with more money sitting closer to the center. Click any seat to see the race, the candidates, and where their money comes from. There’s also a Reports page covering the most expensive races, the funding mix, and outside spenders, plus a what-if simulation that lets you shift the national mood a few points and watch the chamber change. It’s labeled as a what-if, not a forecast.
The same rules from the stream still apply. Money for and money against a candidate are shown separately, never netted. Money raised and outside spending are never added together. And every money figure carries an as-of date.
What got cut, and what got added
Not everything you see in the stream made it. Some features didn’t pan out because there just wasn’t enough data to make them worthwhile. A feature built on thin data ends up either empty or misleading, and I’d rather cut it than fake it. Over time I built, looked at, and pulled out or shelved a few things, including a bill-vote view, a donor map, and live election-night counts. That’s a normal part of building this way: the agent will happily build whatever you ask for, and it’s on you to decide what’s worth keeping.
Other features were added or reworked after the stream. The Chamber and Reports pages came later, along with shareable cards, a view of which campaigns’ money moved recently, and search and link previews. Late October was a round of polish: button layouts, a label that clipped, and a speed-up for the map. So treat the stream as a snapshot, not a spec.
What you’ll see in the stream
Prototype first, wire later. The agent kept offering to connect real data. I kept saying no. You can’t design around data you haven’t confirmed exists.
The agent makes mistakes and fixes them. While pulling FEC data, it opened a huge zip file and tracked down why itemized contributions didn’t add up.
Bugs fixed in plain English. A sticky header let content bleed through. I pointed at the element, and the agent traced it to a missing z-index and a transform creating its own stacking context.
Planning still matters. Partway through I realized we’d pulled in a pile of APIs without organizing how the data came in. I say so on stream. You can’t just vibe-code your way through it.
Product judgment stays with me. I didn’t want a single “promises kept” number, because not all promises weigh the same. The agent also pushed back on showing a confident-looking score without saying it’s built on inference, so we now label what’s reported fact and what’s derived.
Matching the model to the job. Near the end I switched to a larger model at max effort to plan the polling “significant move” feature, then to a cheaper one to build it.
The finding that shaped the product
Before the app existed, I ran a case study on S.2155, a 2018 bank-deregulation bill. Among Senate Democrats and independents, the 17 who voted yes had received about 2.4 times the share of PAC money from depository banks, compared with the 31 who voted no. It held up against a panel of other industries and pointed the right way for labor. Then the ideology control failed: once I accounted for how moderate each senator was, the money signal stopped predicting the vote. That failed test turned out to be the most valuable result, because it set the product rule. BossFight reports association, specificity, and confounds, never a verdict.
How it’s built
The backend is FastAPI in Python, the frontend is vanilla JavaScript with no build step, and the map runs on Leaflet with anime.js for animation. Postgres, Docker, and Coolify handle storage and deploys. I also set up rules for the agents: a CLAUDE.md that tells every Claude session to ask before editing, a separate branch and worktree for each thread, and git hooks that block commits straight to production. Several threads had been overwriting each other’s changes, and this fixed it. In late October the history shows the payoff: six small tickets, each a short Claude-assisted branch, merged and released as versions 0.4.0 through 0.4.4 in about four days.
Rough guide to the recording (158 min)
16:00 Building a live data inventory page
19:45 The “ground game” index and why it needs a caveat
23:00 Donor breakdown and the 2.2 GB FEC file
40:00 Prototype first, wire later
43:00 The bracket screen and candidate card zoom
52:00 API sprawl, and why to plan the data first
1:06:00 The z-index bug fix
1:16:00 Promises kept and fact vs. fiction
1:34:00 Poll chart and the “significant move” idea
2:00:00 Vote Smart and who ducks the questionnaire
2:21:00 The LLM summary layer and its citation rules
If you want to see how this kind of work really goes, with the dead ends, the self-corrections, and a developer arguing with the tool, this is it. You’ll also hear my cat try to get my attention the whole time. But trust me, I played with him later. And yes, I did feed him.
Have fun. Be a part of the process. Now go vote.




