Problem Statement
Developers running HTTP services need to know the moment an endpoint goes down — but most uptime tools are either heavyweight SaaS with per-monitor pricing or require standing up Prometheus/Grafana-style infrastructure. The need: a self-hostable, no-friction monitor that schedules health checks, tracks failures intelligently (one blip ≠ an outage), and shows it all on a dashboard you'd actually want to look at.
Proposed Solution
Watchdog is a full-stack uptime monitor. You add an endpoint (method, headers, body, interval), and the backend schedules recurring HTTP checks, records every result, and escalates status through up → warning → down based on consecutive failures rather than a single miss. The frontend is a React 19 dashboard with a deliberately distinctive SCADA / industrial aesthetic — neon-green-on-black, telemetry panels, response-time charts, and incident logs.
Full Solution Details
- Service lifecycle — create (3-step wizard: endpoint → settings → confirm), test-before-create, edit, pause/resume, delete (with history cleanup).
- Monitoring engine — on boot, loads all active services and starts one
setIntervalper service, tracked in aMap<nodeId, Timeout>. Each tick fires the configured HTTP request, records aHealthCheckdocument (status code, response time, success/fail), increments consecutive-failure count, flips towarningat 2 anddownat threshold, and resets on success. - Dashboard — system health matrix, telemetry, diagnostics, and alerts, cached 30s.
- Service detail — metrics, response-time chart, full health-check log, incidents.
- Auth — register (with password-strength meter), login, JWT sessions.
Technical Documentation
Backend — Node + TypeScript + Express 5 + MongoDB (Mongoose 9), built as a strict 4-layer architecture: Controller → Service → Repository → Model. Services return a ServiceResult (ServiceSuccess<T> | ServiceError) and never throw — controllers never wrap service calls in try/catch, which keeps the HTTP layer thin and error handling uniform. JWT + bcrypt auth, express-validator request chains, node-cache for the 30s dashboard TTL, rate limiting, and graceful shutdown that stops all timers. 15 REST endpoints.
Frontend — React 19 + Vite + TypeScript on Feature-Sliced Design (features/{auth,dashboard,services,entrypoint} each with api/ hooks/ screen/parts/ types/, plus shared/ and ui/ shells). All HTTP goes through a single typed apiClient; all localStorage through a namespaced storageAdapter; all Lucide icons through one @icons re-export. No global state library — React state + context + TanStack Query's cache, with mutations invalidating related query keys to keep views in sync. Conditional rendering uses the author's own Meemaw <Show> component instead of ternaries. Theme is Tailwind CSS v4 via the @theme directive; GSAP + three.js power the industrial visuals.
Tech Stack
React 19, TypeScript, Vite, Tailwind CSS v4, TanStack Query, Meemaw, GSAP, three.js (frontend); Node.js, Express 5, TypeScript, MongoDB/Mongoose 9, JWT, bcrypt, node-cache, express-validator (backend).
System Design
┌──────────────── Frontend (React 19, FSD) ────────────────┐
│ apiClient ── TanStack Query cache ── SCADA dashboard │
└──────────────────────────┬───────────────────────────────┘
│ JWT
▼
Controller → Service (ServiceResult) → Repository → Mongoose Model
│
┌─────────────────────┴─────────────────────┐
▼ ▼
MonitoringEngine MongoDB
Map<nodeId, Timeout> users / nodes /
setInterval per service health-checks
│ each tick: HTTP check
▼ record result, track consecutive failures
up → warning(2) → down(threshold) → reset on success
Smart Architectural Decisions
ServiceResultinstead of exceptions. The service layer returns success/error objects and never throws; controllers stay free of try/catch and error shape is consistent across the whole API — a deliberate, disciplined error-handling contract.- In-process timer engine, no cron/queue. One
setIntervalper service in aMap, started/stopped on create/pause/resume/delete, keeps the system dependency-free and the timer lifecycle tightly coupled to service state. - Consecutive-failure escalation (
warningat 2,downat threshold) avoids alert noise from transient blips — a real reliability-engineering nuance. - Dogfooding Meemaw — the author uses his own published utility library (
<Show>) in a real product, closing the loop between his OSS and his apps. - Single choke points for HTTP (
apiClient), storage (storageAdapter), and icons (@icons) — enforced module boundaries that make the FSD codebase easy to reason about.
Impacts
A self-hostable uptime monitor with a memorable, professional industrial UI, 15 endpoints, smart failure escalation, and a clean 4-layer backend — deployed live at watchdog.devferanmi.xyz.
Demonstrated Skills
Full-stack TypeScript; disciplined backend architecture (layered, Result-type error handling, repository pattern); scheduling/timer lifecycle management; React 19 + Feature-Sliced Design; TanStack Query cache invalidation strategy; Tailwind v4 theming and distinctive UI/visual design (GSAP, three.js); auth/security; dogfooding own OSS.