Files
truenas-stacks/home/doris-dashboard
Fizzlepoof 080ba83989
Some checks failed
secret-guardrails / artifact-secret-scan (push) Has been cancelled
secret-guardrails / gitleaks (push) Has been cancelled
Harden UniFi restricted-lane gateway access
2026-05-23 02:48:49 +00:00
..

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:

/opt/doris-dashboard

Generated page:

/opt/doris-dashboard/public/index.html

Generate manually

cd /opt/doris-dashboard
bin/generate_dashboard.py

Preview locally

cd /opt/doris-dashboard/public
python3 -m http.server 8787

Then open:

http://localhost:8787/

If viewing from another machine on the LAN, use NOMADs LAN IP instead of localhost and make sure the firewall allows the port.

Cron refresh

Installed in fizzlepoofs crontab:

# 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:

crontab -l | sed -n '/# BEGIN DORIS DASHBOARD/,/# END DORIS DASHBOARD/p'

Data inputs

Main news source:

/home/fizzlepoof/.openclaw/workspace/doris-digest/data/candidates.json
/home/fizzlepoof/.openclaw/workspace/doris-digest/data/preferences.json

Local dashboard placeholders:

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:

http://10.5.30.7:8787/

Service file:

/etc/systemd/system/doris-dashboard.service

Manage it:

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:

/opt/doris-dashboard/public/index.html

And the LAN service remains:

http://10.5.30.7:8787/

Verification commands:

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:

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:

/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/<service>.

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.