status.lyrenth.com. One static HTML file, no framework, no build: a status page must be the last thing that can break. It is deliberately hosted away from Lyrenth's own infrastructure (Vercel project, GitHub prober) so it stays up when we are down.
Two jobs:
index.htmlshows live reachability, probed from the visitor's own browser (the page cannot pretend), plus the incident history fromincidents.json..github/workflows/probe.ymlprobes every 5 minutes from GitHub's side and pushes a phone notification via ntfy.sh when something is down. Setup steps are at the top of that file.
Edit incidents.json, newest incident first, newest update first
inside it. Plain English, no internals: name what a user experiences
and what we know, never architecture. Push to deploy.
Fields, and why the machine-readable ones matter:
date the day it began, YYYY-MM-DD
title one line a customer would recognise
status investigating | identified | monitoring | resolved
severity major (served nothing) | degraded (served, badly)
started ISO 8601 UTC, e.g. 2026-08-21T12:55:00Z
resolved same, omitted while the incident is open
windows optional, for an incident that stopped and came back:
a list of {started, resolved} pairs. The bars add up
the windows, not the span, so a fault that recurred
after two good hours is not published as two hours of
downtime. Leave it out and the started/resolved pair
is the single window.
components which of website, api, reads, mcp were affected
updates newest first, each with a human time and text
severity, started, resolved and components are what the uptime
bars are computed from, and they exist because the probe cannot report
an outage it was not running for. Recording began on 21 August, hours
after that day's outage ended, so the samples for that day hold no
failures at all: without the incident record the page would have shown
100 percent for a day we served nothing for nearly four hours. A day
carrying an incident is always counted from the incident. Fill these
fields in, or the page will quietly overstate the service.
An incident from before the prober existed is drawn on the bar but is left out of the percentage, and the label says how many days the percentage was measured over. That is deliberate. Counting the one bad unmonitored day while ignoring the eighty-seven good ones either side of it would not be a measurement, it would be a choice of which days to remember. The history shows everything we know; the number reports only what we watched.
- Create a GitHub repository (public keeps Actions minutes unlimited;
the content is public anyway) under the
lyrenthorg and push this folder to it. - In Vercel: Add New Project, import that repository, framework preset "Other", no build command, output directory left empty.
- Add the domain
status.lyrenth.comto the project; create the DNS record Vercel shows. - Add the repository secret
NTFY_TOPIC(a long random string) and subscribe to it in the ntfy app on your phone.