# NHSD Service Status Dashboard A web-based status feed aggregator for the North Hills School District IT department. Provides a single-pane-of-glass view of vendor service health across 26 platforms. ## Features - **Vendor status cards** — real-time health for all district platforms, color-coded and sortable by severity - **Auto-refresh** — vendor status refreshes every 2 minutes - **Glanceable design** — optimized for a wall-mounted monitor; status obvious from across the room ## Prerequisites - **Node.js** v18 or later - **Caddy** v2 — place `caddy.exe` in `bin/caddy/` - **NSSM** (optional, for running as Windows services) — place `nssm.exe` in `bin/nssm/` ## Setup ### 1. Install backend dependencies ```bash cd backend npm install ``` ### 2. Configure credentials Copy the template and fill in your values: ```bash cp backend/.env.example backend/.env ``` Edit `backend/.env`: ```env # Microsoft 365 — Azure AD app registration AZURE_TENANT_ID=your-tenant-id AZURE_CLIENT_ID=your-client-id AZURE_CLIENT_SECRET=your-client-secret ``` **Microsoft 365**: Create an app registration in Azure AD with `ServiceHealth.Read.All` permission (application, not delegated). ### 3. Start the backend ```bash cd backend npm start ``` The backend listens on `http://localhost:3000`. ### 4. Start Caddy ```bash bin/caddy/caddy.exe run --config config/Caddyfile ``` The dashboard is then available at `https://status.nhsd.net:8443`. > **Note:** There is a separate, pre-existing Caddy instance on this machine. Always use the `--config config/Caddyfile` flag to target the dashboard Caddy specifically. ## Running as Windows Services (NSSM) Use the helper scripts in `scripts/` to install the backend and Caddy as NSSM services so they start automatically with Windows. ## API Endpoints | Endpoint | Description | |---|---| | `GET /api/status` | All vendor status (array) | | `GET /api/health` | Backend liveness check | ## Adding a New Vendor 1. Create `backend/providers/.js` exporting `name`, `url`, and `checkStatus()` 2. Add it to `backend/providers/index.js` See any existing provider for the expected return shape: ```js export const name = "Vendor Name"; export const url = "https://status.vendor.com/"; export async function checkStatus() { // ... return { name, status, // "operational" | "degraded" | "outage" | "unknown" message, // short human-readable description lastUpdated: new Date().toISOString(), }; } ``` If a vendor check throws, the backend catches it and returns `status: "unknown"` — the dashboard degrades gracefully.