# I Built a Monitor for Servers. Then Pointed It at Myself.

> Source: <https://dev.to/dannwaneri/i-built-a-monitor-for-servers-then-pointed-it-at-myself-g5>
> Published: 2026-07-13 01:22:10+00:00

*This is a submission for Weekend Challenge: Passion Edition*

I'm in Port Harcourt. This World Cup, kickoffs have landed at 1am, 2am, sometimes later — late enough that a match the tournament calendar dates one day is already the next day where I am. I watched Argentina beat Switzerland 3-1 in the quarterfinal that way: officially a July 11 fixture, already July 12 in Port Harcourt by kickoff. Fell asleep around 4am, up for work a few hours after that.

This is the first World Cup hosted in North America since I've been following closely, and the timezone math is unforgiving from Port Harcourt.

Four days before this challenge launched, I shipped `workers-monitor`

— a Cloudflare Worker that watches my other Workers for trouble. Cron trigger, hourly. Pulls fleet metrics from Cloudflare's GraphQL Analytics API. A deterministic threshold gate decides if something's actually wrong. Only if the gate trips does it call Claude Haiku to separate signal from noise. Only if Haiku confirms does it send a Telegram alert. A quiet hour makes zero Anthropic calls.

[github.com/dannwaneri/workers-monitor](https://github.com/dannwaneri/workers-monitor)

When this challenge's prompt landed — build something inspired by passion — I didn't reach for a new pattern. I reached for the one I'd just proven, and asked what else deserved that kind of restraint. Sleep did.

**Nightwatch** is the result: same shape, different domain. A gate decides if anything decisive happened; an LLM judges whether it's worth waking up for. Telegram delivers whatever survives both.

The part that's actually the point is the LLM call, and it isn't describing the event. A template can turn JSON into a sentence. What it's doing is judging whether the event still matters — a 4th goal in a 4-0 game and a 90th-minute equalizer are both technically "goal" events, but one is worth breaking sleep for and one isn't. Every notification app on my phone already tells me the score. None of them ask whether I should care.

Quarterfinals ended July 11. Semifinals start July 14 — a day after this challenge's deadline. There was no live match to point Nightwatch at while I was building it.

So this demo replays the real event feed from Argentina 3-1 Switzerland through the actual deployed pipeline — same gate, same Telegram delivery — rather than capturing a live match in progress. Nine real alerts fired, scoreline computed deterministically in code rather than left to the model to restate, so it tracks the real match exactly: 1-0, 1-1, 2-1, 3-1. Four events came back rated HIGH significance (the 10' opener, the 67' equalizer, the 72' red card, the 112' go-ahead goal in extra time), and five LOW (four routine cards plus the 120+1' insurance goal). I'd rather tell you the real breakdown than round it to something tidier.

[Watch the alerts fire]([https://i.imgur.com/EJfqdxC.mp4](https://i.imgur.com/EJfqdxC.mp4)

[github.com/dannwaneri/nightwatch](https://github.com/dannwaneri/nightwatch) — a new repository, first committed July 12, within this challenge's window.

It pulls from ESPN's undocumented public scoreboard endpoint — `site.api.espn.com/apis/site/v2/sports/soccer/fifa.world/scoreboard`

. No key, no signup. It's unofficial and could change without notice; I built the parser to fail closed per-event rather than crash the whole poll if that happens.

The gate itself: a goal or card has to show up on two consecutive polls before it's confirmed. ESPN's feed occasionally lists something briefly before settling — I didn't want a false "GOAL" alert because I trusted the first read.

One bug worth naming: early on, the running scoreline in each alert came from Haiku's own prose, and Haiku occasionally restated the wrong number even when given the correct one. The fix was structural, not a prompt tweak — the code now computes and prepends the scoreline itself, and strips any score-shaped digits the model tries to add in its own text; the model only ever gets to judge significance and describe what happened. A related fix: the model wasn't given real player names, so it invented one for a goal ("Messi" scored a goal Julián Álvarez actually scored) — fixed by passing ESPN's real athlete data into the prompt instead of letting the model guess.

**What's still v1:** No auto-discovery of the day's fixtures — you `POST /track`

a match id by hand before kickoff. The sleep-window suppression (don't ping for LOW-significance events between, say, 11pm and 6am) is a hardcoded env var right now, not a config endpoint — it's spec'd but not built. `workers-monitor`

has a real `/maintenance`

endpoint for suppressing alerts during planned deploys; Nightwatch doesn't have its own equivalent yet. No automated test suite; verification was manual, against real ESPN data.

None of that changes what actually happened watching Argentina-Switzerland. I still lost the sleep on that one. The next one, I won't have to choose.

Not submitting to a prize category this round — no Snowflake, Solana, ElevenLabs, or Google AI in the current build.
