Two hours from idea to a live URL

buffer_overlord2 pts0 comments

Two hours from idea to a live URL — Chovy's Blog

Two hours from idea to a live URL

2026-08-19, by Anthony “chovy” Ettinger.

How this was written: drafted with an AI assistant from my own notes, then edited by me.

I wanted to know when my team played next. That is the whole idea. Not a sports app, not scores,<br>not a feed of takes. A notification an hour before kickoff and another one minute out, for whatever<br>teams I care about, and then nothing else from me for the rest of the week.

Every product that does this wants an account, an app install, and a subscription, and then it<br>covers four leagues. So I built it. First commit at 15:28 this afternoon, live on the domain by 17:30.<br>tipoffwatch.com.

Why it could be free

The thing that decides whether this project exists is the fixture data. StatPal wanted $129 a<br>month. That price means the app has to charge, charging means Stripe and a pricing page and a<br>support inbox, and now it is a business instead of a notification.

ESPN publishes the same data as public JSON with no key. Two endpoints, one for scoreboards and<br>one for the league catalogue. I counted 354 leagues across 17 sports, and soccer alone is 216. A<br>date range comes back in a single request, so sweeping a two week horizon across everything is<br>about 354 calls. That runs on a hobby box for nothing.

Cricket returns zero leagues and rugby uses numeric slugs, so it is not perfect. It is free,<br>which is a different and better property.

What two hours actually buys

Not a finished product. It buys a URL that a stranger can load, which is the only thing that<br>tells you whether any of the rest is worth doing.

The decisions took longer than the code. Bun instead of Node, because the web server and the<br>background workers then share one runtime and one container. Hono with server rendered JSX instead<br>of Next, because every control on the site is a plain form and works with JavaScript off. Postgres<br>instead of the SQLite service I use everywhere else, because follows and delivery receipts are<br>write heavy and I have already been burned by a shared write primary. BullMQ on Redis for the<br>reminder fan out. Magic link and passkeys, so there is no password to leak.

I made those calls in about ten minutes because I have made all of them before, and been wrong<br>about most of them before. That is the actual speed. Not typing.

The bill comes after

There are 49 commits on the repo tonight and most of them are me finding out what I shipped.

Every page rendered in quirks mode for the first hour, because hono/jsx does not emit a doctype<br>and the markup looks completely fine until you read the bytes on the wire. The NFL page listed<br>"Cal Poly Mustangs at Houston Texans", because ESPN team ids are only unique inside a league and<br>20 of the NFL's 32 collide with college football. Boot crashed on a BullMQ job id containing a<br>colon. Then ESPN started 403ing every request from the datacenter until I sent a User-Agent it<br>liked, and I spent twenty minutes blaming that block for a live score bug that turned out to be my<br>own SQL.

The Redis cache I wrote as the defence against a traffic spike sat there uncalled for a week.<br>Written, documented, never wired up. Nobody notices that in review. You notice it when something<br>is slow and you go looking.

The point

Two hours is not a flex about output. It is a limit I set so I would stop designing and go find<br>out. Everything genuinely hard about this app, the team id collisions, the retries that could not<br>retry, the sync timer that pushed itself six hours further out on every deploy, was invisible from<br>the planning side and obvious within minutes of real data hitting real users.

It is live and it is free. Follow a team and forget about it.

Find me: Mastodon &middot;<br>GitHub &middot;<br>email

from hours live because idea team

Related Articles