p?: Provider rejects an explicit undefined under
exactOptionalPropertyTypes — generated schema fields are optional.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Settings splits into labelled sections — renderer, appearance, wallpaper
and CSS, notifications, auth, backup — each with an icon header. Renderer
options gain a per-style glyph and accent-highlighted selection; theme
becomes a segmented Dark/Light control; the dialog widens to max-w-xl.
Renderer switching itself verified working end-to-end (live switch +
persistence across reload); unchanged code path since v2.0.0.
Authored By: TDvorak <[email protected]>
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Ports Beszel's chart design language onto our recharts primitives:
titled card grid, area fills on a true time axis, unit-aware Y ticks,
sorted dotted tooltips, and legend chips. System detail gains stacked
per-container Docker CPU/memory, per-sensor temperature lines, load
1/5/15, and GPU usage/VRAM — all from data the agent already sends.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Nav and header wired as proof. Full string extraction deferred until a
second locale exists; CONTRIBUTING records the convention.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
fmtBytes used 1<<40 — a 32-bit shift in JS evaluates to 1<<8=256, so every
value >=256 bytes rendered as TB. Also drop undefined-valued props that
exactOptionalPropertyTypes rejects in incident/status-page bodies.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
incidents + incident_updates + maintenance_windows + status_pages
tables. Monitor transitions auto-open incidents on down and
auto-resolve on recovery; an active maintenance window covering
the monitor suppresses alerts and auto-incidents, and status
pages report the covered monitor as `maintenance`.
Public status view: GET /api/status-pages/:slug/public aggregates
overall state, monitor uptime, systems, open incidents, and
scheduled maintenance; rendered read-only at /status/:slug.
GET /api/badge/:kind/:id.svg serves stateless shields; GET
/api/metrics exposes Prometheus text over existing tables;
POST /api/import/csv?kind=monitors|domains does header-driven
bulk import; /api/export v2 folds monitors/domains/systems rows
into the backup payload.
Frontend: /incidents with timeline + status flow, /status admin
for pages + windows, /status/:slug public page; nav and palette
wired.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
systems + system_stats tables; agents push JSON every N seconds
to POST /api/systems/ingest with a per-system bearer token. The
server stores each sample, keeps a `latest` snapshot for cheap
list/widget reads, prunes stats after 7d, and marks systems down
when silent > max(3x interval, 30s) — firing system.up/down
webhook events on transitions.
cmd/dash-agent is a standalone Linux collector: /proc for
cpu/mem/net/load/uptime, /sys hwmon temps, statfs disk, and
container liveness via /var/run/docker.sock when present.
No imports from the server module — the sample shape is
duplicated deliberately so the agent stays a single static
binary.
Frontend: /systems card grid with usage bars, /systems/:id with
recharts cpu/mem/net/load, temps + containers tables, and the
agent command; `system` board widget; nav + palette + WidgetDialog
picker wired.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Generic webhook notification delivery configured via the
notify_webhook settings key — no new schema. Fires on monitor
up/down transitions (pending stays silent), domain expiry,
domain expiring, and TLS cert expiring; dispatch is async and
failures are logged, never fatal.
POST /api/notify/test verifies configuration; Settings dialog
gains a webhook URL field with save + send-test. Payload carries
event/name/text/content/message so Slack, Discord, ntfy, and
custom receivers all work.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Two tracks from the Beszel/Domain-Locker merge plan in ROADMAP.md:
- Importers: POST /api/import/external sniffs Homepage services.yml,
Homarr JSON, and Dashy conf.yml into sections/items; SettingsDialog
import now accepts all four formats.
- Monitors (M1): monitors + heartbeats schema, pure checkers for
http/tcp/ping/dns/keyword/json-query/push, scheduler on app ctx,
CRUD + check-now + push ingest API, /monitors + /monitors/:id pages
(wouter), monitor board widget, ServiceDialog monitor opt-in.
Authored By: TDvorak <[email protected]>
Generated with Devin (https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Backend: internal/widget registry (type metadata + Fetcher), Pi-hole
v5 / AdGuard / Immich fetchers, /api/widgets/types + /api/widgets/:id/data
with 30s TTL cache (failures cached too), kind+config on item create/patch.
Config secrets are never logged or echoed in errors.
Frontend: WidgetContent host maps config.type to a component, polls
/data every 30s for server-backed types; clock renders client-side.
Generic WidgetDialog builds its form from the registry's field list.
Widget tiles are sortable items in both renderers.
Generated with [Devin](https://devin.ai)
Authored By: TDvorak <[email protected]>
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>