{"slug": "two-hours-from-idea-to-a-live-url", "title": "Two hours from idea to a live URL", "summary": "Anthony \"chovy\" Ettinger built and launched tipoffwatch.com, a free sports notification service, in two hours, from first commit at 15:28 to live by 17:30 on August 19, 2026. The service uses ESPN's public JSON endpoints, avoiding StatPal's $129 monthly fee, and covers 354 leagues across 17 sports, with soccer alone having 216 leagues. Ettinger highlights that the real speed came from prior experience, not typing, and that the project's value is in testing an idea quickly rather than delivering a finished product.", "body_md": "# Two hours from idea to a live URL\n\n*2026-08-19, by Anthony “chovy” Ettinger.*\n\n**How this was written:** drafted with an AI assistant from my own notes, then edited by me.\n\nI wanted to know when my team played next. That is the whole idea. Not a sports app, not scores, not a feed of takes. A notification an hour before kickoff and another one minute out, for whatever teams I care about, and then nothing else from me for the rest of the week.\n\nEvery product that does this wants an account, an app install, and a subscription, and then it\ncovers four leagues. So I built it. First commit at 15:28 this afternoon, live on the domain by 17:30.\n[tipoffwatch.com](https://tipoffwatch.com).\n\n## Why it could be free\n\nThe thing that decides whether this project exists is the fixture data. StatPal wanted $129 a month. That price means the app has to charge, charging means Stripe and a pricing page and a support inbox, and now it is a business instead of a notification.\n\nESPN publishes the same data as public JSON with no key. Two endpoints, one for scoreboards and one for the league catalogue. I counted 354 leagues across 17 sports, and soccer alone is 216. A date range comes back in a single request, so sweeping a two week horizon across everything is about 354 calls. That runs on a hobby box for nothing.\n\nCricket returns zero leagues and rugby uses numeric slugs, so it is not perfect. It is free, which is a different and better property.\n\n## What two hours actually buys\n\nNot a finished product. It buys a URL that a stranger can load, which is the only thing that tells you whether any of the rest is worth doing.\n\nThe decisions took longer than the code. Bun instead of Node, because the web server and the background workers then share one runtime and one container. Hono with server rendered JSX instead of Next, because every control on the site is a plain form and works with JavaScript off. Postgres instead of the SQLite service I use everywhere else, because follows and delivery receipts are write heavy and I have already been burned by a shared write primary. BullMQ on Redis for the reminder fan out. Magic link and passkeys, so there is no password to leak.\n\nI made those calls in about ten minutes because I have made all of them before, and been wrong about most of them before. That is the actual speed. Not typing.\n\n## The bill comes after\n\nThere are 49 commits on the repo tonight and most of them are me finding out what I shipped.\n\nEvery page rendered in quirks mode for the first hour, because hono/jsx does not emit a doctype and the markup looks completely fine until you read the bytes on the wire. The NFL page listed \"Cal Poly Mustangs at Houston Texans\", because ESPN team ids are only unique inside a league and 20 of the NFL's 32 collide with college football. Boot crashed on a BullMQ job id containing a colon. Then ESPN started 403ing every request from the datacenter until I sent a User-Agent it liked, and I spent twenty minutes blaming that block for a live score bug that turned out to be my own SQL.\n\nThe Redis cache I wrote as the defence against a traffic spike sat there uncalled for a week. Written, documented, never wired up. Nobody notices that in review. You notice it when something is slow and you go looking.\n\n## The point\n\nTwo hours is not a flex about output. It is a limit I set so I would stop designing and go find out. Everything genuinely hard about this app, the team id collisions, the retries that could not retry, the sync timer that pushed itself six hours further out on every deploy, was invisible from the planning side and obvious within minutes of real data hitting real users.\n\nIt is live and it is free. Follow a team and forget about it.", "url": "https://wpnews.pro/news/two-hours-from-idea-to-a-live-url", "canonical_source": "https://dev.profullstack.com/~anthony/blog/024-post.html", "published_at": "2026-08-19 22:10:19+00:00", "updated_at": "2026-08-19 22:44:02.501449+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Anthony Ettinger", "tipoffwatch.com", "StatPal", "ESPN", "Bun", "Hono", "Postgres", "BullMQ"], "alternates": {"html": "https://wpnews.pro/news/two-hours-from-idea-to-a-live-url", "markdown": "https://wpnews.pro/news/two-hours-from-idea-to-a-live-url.md", "text": "https://wpnews.pro/news/two-hours-from-idea-to-a-live-url.txt", "jsonld": "https://wpnews.pro/news/two-hours-from-idea-to-a-live-url.jsonld"}}