Remove CDN dependency (cdn.tailwindcss.com) and replace with a
pre-built, minified Tailwind CSS file embedded in the Go binary
via go:embed.
Changes:
- Add static/static.go with go:embed for css/ directory
- Add static/css/tailwind.min.css (9KB, contains only classes
used by the dashboard template)
- Remove <script src="https://cdn.tailwindcss.com"> and inline
tailwind.config from dashboard.html
- Replace with <link rel="stylesheet" href="/s/css/tailwind.min.css">
- Mount /s/ route for embedded static file serving (go-chi)
- Add /.well-known/healthcheck endpoint per GO_HTTP_SERVER conventions
Zero external HTTP requests from the browser. All assets served
from the binary itself.
Closes#82
Add a read-only web dashboard at GET / that displays:
- Summary counts for all monitored resources
- Domain nameserver state with per-NS records and status
- Hostname DNS records per authoritative nameserver
- TCP port open/closed state with associated hostnames
- TLS certificate details (CN, issuer, expiry, status)
- Last 100 alerts in reverse chronological order
Every data point shows relative age (e.g. '5m ago') for freshness.
Page auto-refreshes every 30 seconds via meta refresh.
Uses Tailwind CSS via CDN for a dark, technical aesthetic with
saturated teals and blues on dark slate. Single page, no navigation.
Implementation:
- internal/notify/history.go: thread-safe ring buffer (last 100 alerts)
- internal/notify/notify.go: record alerts in history before dispatch,
refactor SendNotification into smaller dispatch helpers (funlen)
- internal/handlers/dashboard.go: template rendering with embedded HTML,
helper functions for relative time, record formatting, expiry days
- internal/handlers/templates/dashboard.html: Tailwind-styled dashboard
- internal/handlers/handlers.go: add State and Notify dependencies
- internal/server/routes.go: register GET / dashboard route
- README.md: document dashboard and new / endpoint
No secrets (webhook URLs, API tokens, notification endpoints) are
exposed in the dashboard.
closes#82
Full project structure following upaas conventions: uber/fx DI, go-chi
routing, slog logging, Viper config. State persisted as JSON file with
per-nameserver record tracking for inconsistency detection. Stub
implementations for resolver, portcheck, tlscheck, and watcher.