Root `make check` only ever ran the frontend, so the "main is always
green" policy was satisfied vacuously: the Go backend could be entirely
broken and the root gate stayed green.
- The backend moves onto scripts-to-rule-them-all. Its test, lint, fmt,
fmt-check, build, run and clean implementations now live in
`backend/script/`, and `backend/Makefile` is thin shims. The backend
is its own project (own module, README, LICENSE, linter config,
Dockerfile stage), and `Dockerfile.backend` only copies `backend/`
into its builder, so its scripts have to live under `backend/`.
- The root `script/test`, `script/lint`, `script/fmt` and
`script/fmt-check` now run the frontend step and then the matching
`backend/script/*` step, so `script/check` — and therefore the
pre-commit hook — gates both halves. The frontend-only steps moved
into `script/frontend-*` so nothing is duplicated.
- `script/frontend-check` is the frontend half of the gate, exposed as
the `check-frontend` target, for the frontend Dockerfile: its build
stage is a node image with no Go toolchain. The backend half is gated
by `Dockerfile.backend`, and `script/cibuild` builds both images, so
the two Dockerfiles together still gate the whole repo. The
`check-backend` target is the mirror of it.
- `script/cibuild` builds both images through one `build_image` helper,
and the Gitea workflow's only build step is `script/cibuild`; the raw
`docker build -f Dockerfile.backend .` is gone from the workflow.
`script/docker` likewise builds and tags both images.
- `backend/Makefile`'s `hooks` target is removed. It wrote the same
`.git/hooks/pre-commit` as `script/install-precommit`, so the two
clobbered each other and the developer silently ended up gating on
only one half of the repo. `script/install-precommit` is now the only
installer, and the hook it writes runs the repo-wide `script/check`.
- `backend/Makefile`'s `docker` target is removed too: the backend image
builds from the repo root with a root-level Dockerfile, so it belongs
to the root `script/docker` and `script/cibuild` rather than to a
backend script that would have to reach outside `backend/`.
- `backend/script/lint` verifies that `.golangci.yml` still matches its
pinned sha256 before running the linter. Offline hash comparison, no
network.
READMEs at the root and in `backend/` document every script, and
`TODO.md` records the change.
Local CPE (192.168.100.1) is always monitored. On startup, probe
192.168.1.1, 192.168.0.1, 192.168.8.1, and 10.0.0.1 in parallel
and add whichever responds first as "Local Gateway".
- Add prettier (4-space indents) and reformat all files
- Add Makefile with test/lint/fmt/fmt-check/check/docker targets
- Add MIT LICENSE file
- Add REPO_POLICIES.md
- Fix Dockerfile: listen on 8080 with PORT env var via envsubst
- Restructure README.md with all required sections
- Set up pre-commit hook (make check)
- Update .prettierignore, .gitignore, .dockerignore
SPA for real-time latency monitoring to 10 internet hosts:
- 250ms update interval with 300s history sparkline graphs
- Color-coded latency display (green <50ms to red >500ms)
- HEAD request timing with no-cors mode for cross-origin support
- Built with Vite + Tailwind CSS v4, all dependencies bundled
- Designed for static bucket deployment