SLOTLINE DOCS
01Overview
SLOTLINE watches Solana RPC endpoints: latency, error rate and slot lag versus a reference endpoint you choose. It stores seven days of checks in SQLite and raises threshold alerts that resolve themselves.
02Quick start
npm i npm run dev # → http://localhost:3000/dashboard
Add an endpoint, set it as reference, and press PROBE NOW — or let the scheduler run.
03Concepts
Reference — the endpoint every other endpoint is compared against for slot lag. Set it in the dashboard controls or via PUT /api/settings.
Commitment — processed, confirmed or finalized. Passed to getSlot for every probe.
Slot difference — ref_slot − endpoint_slot. Positive means the endpoint is behind the reference.
Windows — aggregates are computed over 5m, 1h or 24h of checks; alert evaluation always uses the last 5 minutes.
04Alerts
Four kinds, evaluated each cycle over the trailing 5 minutes:
- · down — last 3 checks all failed
- · latency — window p95 > threshold_latency_ms
- · error_rate — window error % > threshold_error_rate_pct (≥5 checks)
- · slot_diff — latest diff > threshold_slot_diff
Alerts dedupe on (endpoint, kind): a new alert is inserted only if no unresolved alert of that kind exists. When the condition clears, the open alert's resolved_ts is set.
05API reference
| Method | Path | Description |
|---|---|---|
| GET | /api/endpoints | List endpoints |
| POST | /api/endpoints | Add endpoint — body {name, url} |
| DELETE | /api/endpoints/[id] | Remove endpoint + its checks/alerts |
| GET | /api/settings | Read settings |
| PUT | /api/settings | Partial update; validates enum/ranges |
| POST | /api/probe | Run a probe cycle now; returns the checks |
| GET | /api/metrics?window=5m|1h|24h | Per-endpoint aggregates + status + settings |
| GET | /api/history?endpoint=<id>&window= | ≤300 downsampled points |
| GET | /api/alerts?limit=50 | Alerts, newest first, with endpoint name |
GET /api/metrics?window=5m →
{ "endpoints": [{ "endpoint": {...}, "last": {"ts","ok","latency_ms","slot","slot_diff","error"},
"latency_p50": 99, "latency_p95": 115, "error_rate_pct": 0,
"avg_slot_diff": 0, "checks_count": 12, "status": "ok" }],
"focus_endpoint_id": 2, "settings": {...} }06Configuration
| SLOTLINE_DB_PATH | data/slotline.db | SQLite file path (local mode) |
| SLOTLINE_INTERVAL_SEC | 10 | Default probe interval (sec) |
| TURSO_DATABASE_URL | — | libsql://… — switches DB to remote Turso |
| TURSO_AUTH_TOKEN | — | Auth token for TURSO_DATABASE_URL |
| CRON_SECRET | — | Bearer secret protecting GET /api/cron |
See .env.example for the full list.
07Deployment
Self-hosted — Node ≥ 20, npm run build && npm start. The built-in scheduler probes every interval_sec. The SQLite file lives at SLOTLINE_DB_PATH (default ./data/slotline.db) — persist that directory. Run a single instance: the scheduler and the DB assume one writer.
Vercel — the in-process scheduler is disabled automatically (VERCEL env). Hobby plans allow only daily crons, so vercel.json registers a daily keep-alive (0 0 * * *) hitting GET /api/cron. Probing is on-demand: any GET /api/metrics call runs a cycle if the newest check is older than the effective interval (min 15s) — an open dashboard keeps probes flowing. For true background probing, self-host or point an external pinger at /api/cron with the CRON_SECRET bearer token (Vercel sends it automatically for cron requests). Since the filesystem is ephemeral, use Turso for the DB: set TURSO_DATABASE_URL + TURSO_AUTH_TOKEN. Deploy with vercel --prod.
vercel --prod # env vars to set in the Vercel project: # TURSO_DATABASE_URL, TURSO_AUTH_TOKEN, CRON_SECRET
08Brand
| graphite | #0B1119 | Page background | |
| panel | #111A24 | Card / panel background | |
| line | #1F2B38 | Borders | |
| glacier | #7FD1F7 | Accent / OK status | |
| chalk | #F4F6F8 | Primary text | |
| muted | #8A9BAD | Secondary text | |
| warn | #F7C97F | Degraded status | |
| bad | #F77F7F | Down status / open alerts |