Node 14-compatible dashboard server and admin UI for NanoPi2, designed to replace the current MagicMirror runtime while keeping display and server processes decoupled.
- Server listens on
0.0.0.0:8090 - Health endpoints:
/health/live,/health/ready - Dashboard route:
/with hybrid layout and rotating focus pane - Admin auth flow:
/login+ protected/admin - Admin APIs:
GET /api/admin/statusPOST /api/admin/configPOST /api/admin/sync(sync,pull,push)
- State API:
/api/state - Fronius support:
- realtime polling
- archive
DailySumtotals - estimated fallback mode after 10 minutes without archive refresh
- configurable polling cadence via
fronius.realtimeRefreshSecondsandfronius.archiveRefreshSeconds
- Weather/news/bins integration:
- default weather provider is OpenWeather (
weather.provider = openweathermap) - weather requests are server-side only and rate-limited by
weather.refreshSeconds - missing/invalid weather key falls back to non-crashing placeholder status
- news headlines parsed from RSS feed
- bins status from configured JSON endpoint
- default weather provider is OpenWeather (
- Radar integration (RainViewer API based):
- server polls RainViewer metadata API (
radar.apiUrl) - startup recovery retries metadata fetch every few seconds (
radar.startupRetrySeconds,radar.startupRetryMaxAttempts) before settling into normalradar.refreshSecondscadence - browser only requests local endpoints
/api/radar/metaand/api/radar/tile/... - browser also requests local OSM basemap endpoint
/api/map/tile/... - radar is rendered with local map+radar tile compositing at configured lat/lon/zoom
- smooth transitions controlled by
radar.frameHoldMsandradar.transitionMs - refresh interval controlled by
radar.refreshSeconds - map provider template configured in
map.tileUrlTemplate
- server polls RainViewer metadata API (
- BOM tiled radar provider:
- set
radar.providertobom_tilesto use BOM Web Mercator radar tiles (radar.tileUrlTemplate) - server synthesizes recent 5-minute frame timestamps and renders them through the existing server GIF path
- set
- Solar focus visuals:
- canvas current-generation gauge
- canvas daily ring summary
- canvas history chart from server-side realtime history (
solarHistoryin/api/state)
- Git sync:
- manual sync actions via admin API
- background auto-sync scheduler from config (
git.autoSyncEnabled,git.intervalSeconds)
- Systemd templates for server + Firefox kiosk split
If HTTPS certificate validation fails due to old CA/cipher support, set:
"insecureTLS": trueThis allows server-side HTTPS fetches without certificate verification. Use only on trusted networks.
Debugging is off by default. Enable with env vars:
LOG_LEVEL=debug
DEBUG_EXTERNAL=1
DEBUG_GIF=1
DEBUG_EXTERNAL_BODY_MODE=full
DEBUG_BODY_MAX_BYTES=65536Supported body modes:
metadata(status/timing only)metadata_response(adds response size and content-type)full(adds capped request/response bodies; binary is base64)
Debug events are buffered in memory and available after admin login:
GET /api/admin/debug/events?limit=200POST /api/admin/debug/clear
Server-side radar GIF rendering uses ffmpeg for tile compositing and GIF encoding.
If ffmpeg is unavailable, the server still starts normally and falls back to PNG radar mode (/api/radar/meta + /api/radar/tile/...) instead of crashing.
You can force a backend with config:
"radar": {
"gifBackend": "auto"
}Supported values: auto (default) and ffmpeg. sharp is intentionally not a production dependency because its native binaries can crash on older CPUs without SSE4.2.
To ensure GIF mode in runtime images, install ffmpeg in the runtime image:
apt-get install ffmpegsrc/server and runtime logicconfig/runtime config files (auth.jsonis local-only)public/static dashboard/admin pagesdeploy/systemd/service templates and kiosk launcherdocs/plans/design and implementation plans
npm test
cp config/auth.json.example config/auth.json
# set password hash/salt values in config/auth.json
npm startOptional local secrets in .env.local:
cp .env.example .env.local
# set OPENWEATHER_APPID/OPENWEATHER_APP_ID, OPENWEATHER_LOCATION_ID, RADAR_SOURCE_URL, RADAR_LAT, RADAR_LONOPENWEATHER_APPID (or OPENWEATHER_APP_ID), OPENWEATHER_LOCATION_ID, RADAR_SOURCE_URL, RADAR_LAT, RADAR_LON, and INSECURE_TLS from .env/.env.local override values from config/dashboard.json.
Set timeZone in config/dashboard.json (for example Australia/Brisbane) or DASHBOARD_TIMEZONE in env to keep daily solar bins/charts aligned on servers with different host timezones.
Open on LAN:
- Dashboard:
http://192.168.0.27:8090/ - Admin:
http://192.168.0.27:8090/admin
./scripts/bootstrap-auth.sh '<strong-password>'This writes config/auth.json with secure file mode 600.
sudo ./scripts/install-systemd.sh nanopi /opt/nanopi2-dashboardThis installer rewrites service templates with your service user/install path, enables both services, and restarts them.
Use:
docs/cutover/2026-02-14-cutover-checklist.md
Use VS Code Remote SSH from your laptop to 192.168.0.27 and open this repo directly. Keep dashboard server runtime on NanoPi so behavior matches production.