# Monitoring Setup Instructions Concrete setup steps for the approaches chosen in `monitoring-plan.md`: **Logging** and **Dashboards** (no Alerting). ## Logging ### What to log - Uncaught JavaScript errors / exceptions (the app already has an `ErrorBoundary` component from Code Generation — this is the natural hook point). - Broken/failed navigation (e.g. an unexpected router error). - No user PII, form input, or sensitive data should ever be logged — this is a public marketing site, but keep this discipline regardless. ### Destination — open decision The destination was not finalized (original Question 3 = C). Two supported options, either of which can be adopted later without further design work: **Option 1: Browser console only (default today)** - No code changes needed — errors already surface via `console.error` inside the existing `ErrorBoundary`. - Zero cost, but not centrally visible; only useful for manual debugging (e.g. via a user's screenshot or a support request). **Option 2: External error-tracking service (e.g. Sentry free tier)** - When decided, add `@sentry/react` as a dependency, initialize it once in the app entry point (e.g. `src/main.tsx`) with the project DSN, and report caught errors from the `ErrorBoundary`'s `componentDidCatch`/`onError` hook to Sentry in addition to the console. - Store the DSN as a Gitea Actions variable (or a build-time `.env` value, since it's not a secret — Sentry DSNs are safe to expose client-side) and inject it via Vite's `import.meta.env`. - Free tier limits (error volume, retention) are typically sufficient for a low-traffic marketing site. **Log level strategy**: only errors are logged (no verbose/info-level client logging) — this is a static site with no meaningful "business events" beyond page views, which are covered by analytics (see Dashboards below), not logging. ## Dashboards ### Website analytics — decided: self-hosted Umami **Decided**: self-hosted Umami, running via Podman on the webserver Pi (Pi Main, `192.168.1.103:3000`), reachable for the dashboard itself via `analytics.slpsoftware.nl` (reverse-proxied + SSL via certbot, same pattern as `test.slpsoftware.nl`). Chosen over GA4 for privacy-friendliness (typically no cookie banner needed) and full self-hosted control, and over a hosted Umami/Plausible plan to avoid recurring cost. - Full step-by-step setup: `operations/monitoring/umami-setup.md` (Podman/compose files, systemd auto-start, reverse proxy + SSL, website registration). - Example config: `operations/deployment/umami/podman-compose.yml.example` + `.env.example`; `operations/deployment/nginx/analytics-nginx.conf.example`. - The tracking script is injected client-side by `src/components/UmamiAnalytics.tsx`, gated on two build-time variables (`VITE_UMAMI_SCRIPT_URL`, `VITE_UMAMI_WEBSITE_ID`), wired into `continuous_integration.yaml`'s `Build` step as Gitea repository variables, not secrets (same pattern as `VITE_SENTRY_DSN`). It never loads during local development (`pnpm dev`), even if those variables happen to be set, so local testing never pollutes visitor analytics. - Key metrics to surface: unique visitors, page views per route (Home, Packages, etc. — see `frontend-components.md`), and referral sources. ### Uptime dashboard — decided: UptimeRobot **Decided**: UptimeRobot (free tier: up to 50 monitors, 5-minute check interval, optional e-mail notification on downtime — opportunistic, not a designed alerting feature per `monitoring-plan.md`). Chosen over Better Uptime for its long-standing free tier and simplicity for a single low-traffic site. **Setup**: 1. Create a free UptimeRobot account (https://uptimerobot.com). 2. Register `test.slpsoftware.nl` as an HTTP(S) monitor now (checking for a `200` response); add the production URL once hosting is finalized (see `operations/deployment/deployment-plan.md` "Open Item") — still an open follow-up. 3. Optional: publish a public status page if desired for transparency to visitors. 4. Key metric to surface: uptime percentage / current status. No application code changes are needed for UptimeRobot — it works purely by polling the public URL from the outside, entirely independent of the site's own codebase. ## Summary Table | Concern | Approach | Status | |---|---|---| | Client-side errors | Logging (console today; Sentry free tier optional later) | Destination open item | | Visitor/usage insight | Analytics dashboard (self-hosted Umami) | Tool decided; deployment (Podman on Pi Main + `analytics.slpsoftware.nl`) is a manual follow-up, see `umami-setup.md` | | Site reachability | Uptime dashboard (UptimeRobot) | Tool decided; account creation + production URL are manual follow-ups | | Alerting | Out of scope | Not configured | | Shared infrastructure reuse | Out of scope | None exists yet |