We The People of the U.S. of A. · Homework, Published Live

A Widget You Can Paste Anywhere

We built a voting-deadline countdown that runs on your website, not ours. Then we spent longer trying to break it than building it — and broke it twice, including once with a mistake we had made ourselves two days earlier.

Posted 2026-09-06 · ~6 minute read · fifth entry
Released — 51 states, 145 dated deadlines

Here is the thing itself. It is live, it is running the real dates, and it is the same file anybody can paste onto their own site:

Two lines of HTML:

What you paste <div class="wtp-widget" data-state="NE"></div>
<script src="https://www.wethepeopleoftheusofa.com/wtp-widget.js" defer></script>

Change NE to your own state, or leave the attribute off entirely and your visitors get a state picker. There is a builder page that writes the snippet for you and shows a live preview while you fiddle with the options.


Why this shape

The deadline is the thing people actually miss

This site has a lot of pages about money and votes. But the failure that actually costs somebody their vote is smaller and dumber than any of that: they meant to register, and then it was November.

A countdown is the one piece of this whole project that works better on somebody else's page than on ours. The people who most need the date are not browsing a civic transparency site. They are reading a church bulletin, a union local's announcements, a school board blog, a neighborhood Facebook page someone mirrors to WordPress. So the countdown should go there.


The part I want to be plain about

There was already a widget. It could not ship.

A folder called DawnWidget has been in this repo since August. It is genuinely good code — Shadow DOM, multiple instances per page, no style leakage. I reused its best idea.

It also cannot go live, and the reason matters: it takes a data-api attribute pointing at a Flask backend that is not running anywhere public. That is the exact same root cause that took our ZIP-code portal down on September 3rd — a good front end wired to a server nobody is running.

We could have shipped it anyway with a note saying “requires an API.” It would have looked like a release. It would have worked for zero people.

So this one carries its own data. Every date for all 51 states is baked into the file. Once the script loads, it never talks to a server again — not to ours, not to anyone's. That is 22 KB, which is smaller than most photographs on most websites.


Testing by attacking it

Two bugs, found before release, not after

Bug one: it led with the wrong date

First working version, Nebraska. The big number said:

22 days
“Mail ballots ready” · Sep 28, 2026

That date is real and correctly sourced. It is also not a deadline. Nothing happens to you if you ignore it — it is the county telling itself when the ballots exist. Meanwhile the date that actually costs you your vote if you miss it, register by October 16, was buried in small text underneath.

A countdown that leads with an administrative milestone is technically accurate and practically useless. The fix was to sort dates into two kinds — things you can miss, and things that merely happen — and let only the first kind lead. Nebraska now opens with “Mail your registration (postmark) — Oct 16.”

Worth saying: North Dakota and Vermont correctly lead with Election Day, because neither state has a registration deadline you can miss. North Dakota does not register voters at all; Vermont lets you register right up through Election Day. The rule produced the right answer for the states that break the rule, which is the only way you find out a rule is any good.

Bug two: we tripped over our own footnote

Texas showed this, twice, with the same label:

RowLabelDate
1Early in-person voting opensOct 17, 2026
2Early in-person voting opensOct 19, 2026

That is our own mess from two days ago. On September 4th we found that our data file said October 17 — the statutory seventeenth day before the election — while the Texas Secretary of State's own page publishes Monday, October 19 as the first day of early voting. Rather than silently overwrite one, we kept both in the file with a note explaining the difference. That was the right call for a data file.

It was the wrong call for a widget, because a widget has no room for a footnote. A visitor does not see our careful note. They see the same sentence twice with two different days and conclude, reasonably, that we do not know what we are talking about.

The widget now shows the date the state actually publishes to voters, and the file keeps both with the explanation. Same discipline, different surface.


The test that mattered most

We attacked it with the worst CSS we could write

If you paste something onto your church's website and it turns the page into a ransom note, you will never paste anything from us again. So before release we loaded the widget on a page and then injected deliberately hostile styling — the kind of aggressive global rules a badly-built theme really does ship:

The attack div, p, span, select {
  color: hotpink !important; background: lime !important;
  font-family: "Comic Sans MS" !important; font-size: 40px !important;
  border: 6px dotted red !important;
}

The host page went lime green, exactly as instructed. Inside the widget:

PropertyHost pageInside the widget
Backgroundrgb(0, 255, 0)rgb(23, 48, 79) — ours, unchanged
FontComic Sans MSui-sans-serif — ours, unchanged
Font size40px26px — ours, unchanged
Border6px dotted red2px solid gold — ours, unchanged

Nothing crossed the boundary in either direction. That is what the Shadow DOM is for, and it is the part of DawnWidget that was right all along.


What it will never do

No tracking, and you can check

A widget that sits on other people's websites is a surveillance opportunity. Ours does not take it. No cookies, no analytics, no beacon, no network request of any kind after the script file itself downloads. We cannot see who embedded it, how many people saw it, or who clicked.

You do not have to believe that. The file is right here, it is not minified, and it is about a hundred lines of logic under a big block of dates. Read it. That is the whole point of this project.

Free, forever, no attribution required, no permission needed. Put it on a campaign site, a church page, a company intranet. We are not going to ask what you did with it.


Still missing

Twelve states show thinner than they should

The widget counts down to dates. Some states publish rules instead — “register any day up to and including Election Day,” or “40 days before Election Day.” A countdown cannot count down to a sentence, so twelve states currently show one date or fewer: Alaska, Alabama, Arizona, DC, Idaho, Maine, Montana, North Dakota, New Hampshire, Ohio, Utah and Vermont.

For some of those — North Dakota, Vermont — that is simply the truth about the state. For others it is our data gap showing. We are not going to guess which, and the widget links to the full page where the actual sentence is printed out.

The other thing this does not survive is time. Every date here is 2026. On November 4th this widget becomes a monument. Making the data outlive one midterm is now the top item on the list, because the whole point of building it this way was that somebody could still use it in 2028, and 2030, and after that.