← Back to writing

Back to the Future with a Precinct Strategy

5 min read / Alexander J. Singleton
Back to the Future parody showing Donald Trump in Doc Brown’s jumpsuit beside Marty McFly in the DeLorean.

On November 3, 2026, we tried something simple in Crawford County, Kansas. A watcher would enter the cumulative ballot count reported by the election judge and record the hour it described. I wanted to see what we could learn from those readings and what it would take to collect them reliably.

A garage door open on election day

My Sicilian great-grandmother used to open her garage in Romanelli, her Kansas City neighborhood, so her neighbors could come vote. When I talk about going back to the precinct, that’s the picture I have in mind. A garage door open on election day.

A precinct is a geographic unit. A polling place is where people go to vote. For the November 3 pilot, our build tracked 58 unique Crawford County precincts and 13 polling places, and we verified each count separately. Several precincts can share one site. The county’s directory, for example, groups all four Frontenac wards at one polling place. Crawford County polling places by precinct

Historical map of Crawford County, Kansas, showing labeled polling places and their color-coded service areas.
Polling place boundaries in Crawford County, Kansas, as mapped in October 2016. View the original county GIS map (PDF)

I understand the staffing logic behind consolidation. Fewer polling places can mean fewer buildings to staff. But when several precincts vote in one building and a watcher gets one number for the whole site, there’s very little to follow up on by precinct. If a reading looks unusual, where do you start?

That’s what I mean by going back to the future. Keep the precinct on the map and in the data. When a source can provide a precinct-level figure, preserve it so someone can check it locally. When a source provides a building-wide headcount, record it at the building level. My hunch is that giving volunteers smaller reporting assignments would make it easier to notice a gap, find the right person to ask, and get a correction. That’s what I want to test next.

Building Headcount took me back to my own roots, too. Ruby on Rails was the steepest learning curve I knew when I was getting into web development. I enjoyed coming back to it for this pilot and building around a concrete job. A watcher needed a place to record the count, the hour it described, and the reason for any correction.

I built Headcount in Ruby on Rails with Postgres and deployed it on the same Ubuntu server as an earlier build. Reusing a server and a domain I already maintained and managed, VETSI.io, helped me get the pilot online quickly. VETSI is a 501(c)(3) nonprofit incorporated to assist veterans re-assimilating into the modern workforce. About VETSI

Inside the DeLorean, Doc Brown tells Marty and Jennifer they won’t need roads.

What we collected on election night

The November 5 production backup contained 21 cumulative readings from six Crawford County polling places. Four locations reported at 7 p.m., with 2,744 cumulative ballots across those four sites.

Crawford County Headcount dashboard showing six reporting sites, their latest readings, and the times those readings describe.
Unofficial Headcount pilot dashboard. The running total of 3,718 combines the latest readings from six sites at different times.

Six readings from another location described six different hours, yet someone entered all six in about 98 seconds near 7 p.m. The numbers went up by exactly one each time. Those entries could have been practice or observations entered later, so I flagged them for follow-up. I could see the pattern because Headcount keeps the hour observed and the time submitted separately.

Arcadia Community Center’s hourly reading history, with cumulative counts rising from 8 to 13 and the submitter’s name redacted.
Unofficial pilot readings at Arcadia Community Center. The table shows the hours the readings describe. The 98-second submission window comes from the backup.

Headcount stores one reading per election, polling place, and hour. Say a site reports 350 at noon and 400 at 1 p.m. We can calculate an hourly increase of 50. If the next reading is 470 at 3 p.m., the count rose by 70 over two hours. The one-hour increase at 3 p.m. stays blank until we have a 2 p.m. reading. When someone corrects a reading, the app keeps the prior value and the reason for the change, then recalculates the affected differences.

The DeLorean backs down a trailer ramp into a smoky parking lot at night.

The invitation that wouldn’t open on cellular

My wingman could sign in and reach his Crawford County dashboard. But when he tapped a fresh password-setup link from his email on his iPhone, Sucuri returned EVA120 before Rails could show the form. I reproduced the block over cellular. By then, we’d already fixed a stale sign-in page. The invitation was failing at a different step.

An iPhone on LTE displays Sucuri’s Access Denied message after opening a link from Mail.
Sucuri blocked the emailed Headcount setup link when I opened it on an iPhone over LTE.

We switched to a shorter, single-use setup token. With Sucuri’s evasion detection still enabled, I opened a fresh invitation from my inbox on an iPhone with Wi-Fi off, set a password, and signed in.

A precinct watcher’s Headcount correction form on an iPhone, with fields for the observation hour, cumulative count, and reason for correction.
A precinct watcher’s view of the Headcount correction form on an iPhone. The form asks for the cumulative count as of the selected hour and a reason for the correction.
Doc Brown tells Marty what will happen when the DeLorean hits 88 miles per hour.

The trailing period I wanted to remember came up in a separate DNS issue. The editor appended the zone automatically, so the field needed _acme-challenge.www without the final period. The stale sign-in page had a fix of its own. In Non-Cacheable URLs, select Matches and enter /session/new. I wrote those down alongside the invitation retest, the certificate upload issue, and the visitor-IP checks. Five Sucuri troubleshooting notes

What I’ll rehearse next time

The Alexander J. Singleton rebuild taught me to check the public edge and the origin separately. VETSI made me pay attention to which hostname and path a change affects when a public site and a private app share infrastructure. Bucephalus reminded me to rehearse a restore in isolation, with outbound mail and integrations disabled. Alexander J. Singleton · VETSI · Bucephalus

Before the next election, I want to start in a watcher’s inbox, on a second phone with Wi-Fi off, and follow the invitation all the way to their assigned polling place. Then I want to sit down with the people covering one shared site and ask what they can reliably report by precinct. That gets me back to what I like about my great-grandmother’s garage. I can picture the place, the people who showed up, and who I’d ask if I wanted to understand what happened there.