# Doris Dashboard Local homepage for John's briefing, glanceable status, and "what matters right now" view. ## What it is Doris Dashboard is the quiet front page for John's local information stack on NOMAD. It is not a general website and it is not meant to be another feed reader with a fresh coat of paint. It exists to turn Doris Digest output and a few homelab/task signals into one page John can open for a fast read. The dashboard is meant to answer: - what is worth looking at this morning - what local or homelab signals need attention - what chores or Paperless follow-ups are still hanging around - what topics are surfacing too often and should be tuned down ## Why it exists Without this stack, the raw inputs are noisy: - Doris Digest candidates are too broad on their own - Donetick and Paperless are useful but fragmented - local weather/sky/homelab signals live in separate places The dashboard turns that into one opinionated, local-only page that Doris can tune over time. ## Runtime model - **Repo source:** `/home/fizzlepoof/repos/truenas-stacks/home/doris-dashboard` - **Live runtime:** `/opt/doris-dashboard` - **Generated page:** `/opt/doris-dashboard/public/index.html` - **LAN URL:** `http://10.5.30.7:8787/` - **Exposure rule:** local-only unless John explicitly asks otherwise ## What it shows - top briefing cards from Doris Digest candidates - space / homelab / local / other signal lanes - an experimental `New to You` lane for off-profile category sampling - Donetick tasks - Paperless review queue items - weather, sky, and homelab pulse cards - lightweight stats about candidate/source mix ## How it works - `bin/generate_dashboard.py` reads Doris Digest candidates plus a few local/runtime data files. - It scores, deduplicates, and groups stories into dashboard sections. - It writes generated JSON artifacts under `data/` and the final static page under `public/`. - `bin/dashboard_server.py` serves the page and handles interactive actions like topic feedback and Paperless review state. - The wind watchdog writes a quiet forecast notice into `~/.hermes/state/wind_alert_watchdog.json`; the dashboard surfaces that for longer-range wind events before they are close enough to deserve a direct ping. That means the dashboard is static-looking for the reader, but still has enough local interactivity for feedback and review flows. ## Live paths Live runtime path: ```bash /opt/doris-dashboard ``` Generated page: ```bash /opt/doris-dashboard/public/index.html ``` ## Generate manually ```bash cd /opt/doris-dashboard bin/generate_dashboard.py ``` ## Preview locally ```bash cd /opt/doris-dashboard/public python3 -m http.server 8787 ``` Then open: ```text http://localhost:8787/ ``` If viewing from another machine on the LAN, use NOMAD’s LAN IP instead of localhost and make sure the firewall allows the port. ## Cron refresh Installed in `fizzlepoof`’s crontab: ```cron # BEGIN DORIS DASHBOARD DORIS_DASHBOARD_DIR=/opt/doris-dashboard DORIS_DIGEST_DIR=/home/fizzlepoof/.openclaw/workspace/doris-digest # Refresh local dashboard after digest collection windows; wrapper enforces Chicago daytime. 5,35 * * * * cd $DORIS_DASHBOARD_DIR && bin/cron_generate_dashboard.sh >> logs/generate.log 2>&1 # END DORIS DASHBOARD ``` Inspect with: ```bash crontab -l | sed -n '/# BEGIN DORIS DASHBOARD/,/# END DORIS DASHBOARD/p' ``` ## Data inputs Main news source: ```bash /home/fizzlepoof/.openclaw/workspace/doris-digest/data/candidates.json /home/fizzlepoof/.openclaw/workspace/doris-digest/data/preferences.json ``` Local dashboard placeholders: ```bash data/todos.json data/calendar.json data/notes.json ``` These are intentionally simple JSON arrays so calendar/Donetick integrations can be added later without rewriting the page. ## Next integrations to add 1. Donetick tasks 2. Calendar events 3. Weather / severe weather 4. Moon phase / ISS passes / meteor shower calendar 5. Homelab health pulse 6. Article feedback buttons or quick links back to Doris ## Privacy/deployment note This dashboard is local-only on NOMAD unless John explicitly asks to expose it. Do not publish it externally without asking. ## LAN service The dashboard is exposed on NOMAD's LAN IP via systemd: ```text http://10.5.30.7:8787/ ``` Service file: ```bash /etc/systemd/system/doris-dashboard.service ``` Manage it: ```bash sudo systemctl status doris-dashboard.service sudo systemctl restart doris-dashboard.service sudo systemctl stop doris-dashboard.service ``` The service runs as `fizzlepoof`, serves `public/`, binds `0.0.0.0:8787`, and regenerates the page before starting. At setup time UFW was inactive, so no firewall rule was required. ## Buildout added 2026-05-12 The dashboard generator now builds a richer local homepage directly on NOMAD. Added sections/data: - Weather metrics for Clarksville via Open-Meteo (`data/weather.json`) - Moon phase / sky note calculated locally (`data/sky.json`) - Homelab pulse checks (`data/homelab.json`): dashboard service, cron, digest freshness, workspace disk - Article export from Doris Digest candidates (`data/articles.json`) - Dashboard metadata (`data/dashboard.json`) The generated page still lives at: ```bash /opt/doris-dashboard/public/index.html ``` And the LAN service remains: ```text http://10.5.30.7:8787/ ``` Verification commands: ```bash cd /opt/doris-dashboard python3 -m py_compile bin/generate_dashboard.py bin/generate_dashboard.py curl -fsS http://127.0.0.1:8787/ | grep 'Doris Dashboard' systemctl is-active doris-dashboard.service crontab -l | sed -n '/# BEGIN DORIS DASHBOARD/,/# END DORIS DASHBOARD/p' ``` Notes: - Weather.gov and NASA API are not used; Open-Meteo worked reliably without an API key. - Donetick live task import is still not enabled in the dashboard; `data/todos.json` remains the safe placeholder until the exact read-only endpoint is confirmed. - Raw secrets are not written to dashboard output. ## Compact news layout 2026-05-13: News/article sections were changed from large cards to compact rows so the dashboard can keep plenty of articles without making John scroll forever. Implementation: - `generate_dashboard.py` renders article sections with `compact-card` rows by default. - `public/style.css` contains the compact layout rules. - Metrics/weather/homelab pulse remain large cards. ## Donetick integration 2026-05-13: The dashboard now imports open Donetick chores read-only during generation. Implementation notes: - Secrets remain encrypted in `/home/fizzlepoof/.openclaw/workspace/.secrets/donetick_secrets.json.enc`. - `bin/generate_dashboard.py` decrypts secrets at runtime using the local encryption key and logs in with the Doris service account. - It reads `/api/v1/chores` and `/api/v1/users` only. - It writes sanitized task data to `data/todos.json` for the dashboard. - It does not expose tokens, passwords, or raw secrets in generated HTML/JSON. Verify: ```bash cd /opt/doris-dashboard bin/generate_dashboard.py python3 - <<'PY' import json from pathlib import Path for item in json.loads(Path('data/todos.json').read_text()): print(item.get('time'), item.get('title'), item.get('assignee')) PY ``` ## Donetick compact board + topic feedback 2026-05-14: The dashboard's Donetick section was reworked to match the tighter PD Dakboard pattern more closely. Current behavior: - Donetick renders compact task cards with due cue, task title, label chips, and a short subtitle. - Tasks are sorted by urgency first (overdue/today/upcoming/no due date), then due time. - The dashboard injects a pinned Paperless follow-up card into the Donetick area so that cleanup work stays visible. - News cards now show `👍 / 👎` topic buttons. - Topic feedback is persisted through the local dashboard server into `../doris-digest/data/feedback.json` with `origin: "dashboard"`. - `Reset hidden topics` clears both browser state and dashboard-origin feedback entries. - Paperless review cards now have `Acknowledge` / `Dismiss` actions persisted to `data/paperless_review_state.json`. - Major dashboard sections are collapsible and remember collapsed state in the browser. Important note: - The interactive actions require the dashboard to be served by `bin/dashboard_server.py`, not plain `python -m http.server`. ## Runtime path sanity The live systemd unit and crontab must point only at: ```bash /opt/doris-dashboard ``` Do not run the dashboard from an agent workspace. Agent workspaces are for editing and staging; NOMAD host-run services belong under `/opt/`. ## Cron fix — 2026-05-13 The dashboard cron now uses `bin/cron_generate_dashboard.sh`, which checks America/Chicago daytime internally. This avoids relying on `CRON_TZ`, which NOMAD's cron did not honor consistently. ## Paperless review queue contract The dashboard displays sanitized Paperless intake triage items written by n8n at `data/paperless_review.json`. Example contract: `data/paperless_review.example.json`. Expected shape is a JSON array. Each item may include: - `id`, `title`, `original_filename`, `added`, `archive_url` - `current.correspondent`, `current.document_type`, `current.tags` - `triage.summary`, `triage.suggested_title`, `triage.document_type`, `triage.suggested_tags`, `triage.due_date`, `triage.needs_review`, `triage.urgency`, `triage.reason`, `triage.confidence` - `safety.forced_review`, `safety.eligible_for_safe_apply`, `safety.apply_safe_enabled` - `queued_at` Do not write tokens, raw OCR text, API responses, or credentials into this file. It is display-only derived data for local review.