github jordibrouwer/nextdash v2026.07.03

latest releases: v1.3.2, v1.3.1, v1.3.0...
one month ago

Security hardening, activity log, extension shortcuts, and sync reliability — Structured server-side activity logging, CSP and SSRF rate limits (plus a dedicated status-ping bucket), DNS IP pinning, and startup validation for self-hosters. Dashboard data revision uses content hashes and detects name/URL/shortcut drift. Config bookmark saves keep layout and weather settings intact while category moves sync to the dashboard. Browser extension can save optional shortcuts with auto-suggest. What's new modal shows the 7 most recent releases on scroll. General Essentials/Advanced toggle preserves toolbar position; Playwright E2E suite fully green.

Security & server

  • new Activity logactivity_log.go: JSON lines for bookmark.add / edit / delete / move / import, status pings (10-minute dedupe unless refresh=1), optional opens, and security events. Env: NEXTDASH_ACTIVITY_LOG (mutate, status, open, security, off), NEXTDASH_ACTIVITY_LOG_PERSIST, NEXTDASH_ACTIVITY_LOG_FILE.
  • new CSP headerssecurity.go sends Content-Security-Policy on HTML responses; NEXTDASH_CSP=off disables.
  • fix CSP weatherconnect-src allows Open-Meteo geocoding and forecast APIs so the dashboard weather widget works under CSP (security.go).
  • new Rate limitsrate_limit.go: per-IP limits on outbound fetches (NEXTDASH_OUTBOUND_REQUESTS_PER_MIN, default 120) and SSRF-sensitive APIs (NEXTDASH_SSRF_API_RATE_PER_MIN, default 60); separate status ping bucket (NEXTDASH_STATUS_PING_RATE_PER_MIN, default 300); HTTP 429 + optional security activity event.
  • fix DNS IP pinninghost_ip_pin.go: pin resolved public IPs for ~2 minutes on outbound dials (url_safety.go).
  • fix Startup validationstartup_validate.go: validate PORT (1–65535) and writable NEXTDASH_DATA_DIR before listen (main.go).
  • fix Request contextpingURLDetailed(ctx), fetchBookmarkPreview(ctx); status.go, handlers.go, favicon_prefetch.go pass r.Context().

Dashboard & sync

  • fix Hash-based data revisionGetDataRevision hashes file contents instead of mtimes (handlers.go, models.go).
  • fix Stale cache: name, URL, shortcutisPageBookmarksStale() compares all bookmark fields; tests in dashboard-data coverage.
  • fix Preview metadata cache — in-memory cache with previewCacheDirty, periodic flush (~30 s) and shutdown flush (cache_store.go, handlers.go).
  • fix Tag popover save contract — popover reports failure when bookmark save fails.
  • fix Preview metadata save toast — user notification when preview persist fails.
  • fix Tag-filter bulk delete — success check and page-cache sync after bulk delete.
  • fix Shared cache-bust tokensasset_versions.go centralizes cross-page tokens; dashboard/config/health templates use {{.Assets.*}}.
  • fix Config → dashboard category sync — bookmark saves keep settings sync (layout chrome) and force a full dashboard render so category moves appear in the correct column; incremental patch also reparents rows across columns (config-persistence.js, dashboard-config-sync.js, dashboard-render-incremental.js).
  • fix Config save layout regression — revert structure-only sync on saveChanges() (392c1f6); structure refresh still reapplies setupDOM for tags/finders updates (dashboard-config-sync.js).
  • fix Device layout overrides — bookmark-only config save no longer clears device-specific dashboard settings when server settings are unchanged (config-persistence.js).
  • fix Config save settings guardsaveChanges() syncs General UI and POSTs settings only when settings actually changed; theme/layout autosave skips updateFromUI; regression test for bookmark-only save (config-persistence.js, config-settings-guard-1).
  • fix Status ping rate limit — bookmark /api/ping uses dedicated limiter; client treats HTTP 429 as rate-limited instead of offline (status.go, status.js, status-rate-limit-1).

Browser extension

  • new Optional shortcut fieldextension/popup.html/js; auto-suggest via suggestBookmarkShortcut() in save-common.js.
  • fix Shortcut on savepostAddBookmark sends resolved shortcut (no longer always '').
  • fix 409 duplicate shortcut — conflict handling in popup; i18n in extension/locales/{en,nl,de,fr}.json.

What's new modal

  • new 7-release historyMAX_VISIBLE_RELEASES = 7; manifest sorted by version tag; lazy-load per-release JSON unchanged (whats-new-v121).

Config

  • fix General layer scrollpreserveScroll compares prevLayer to nextLayer (was always false before assignment); preserveScrollAnchor runs a synchronous fix before requestAnimationFrame (general-layer-scroll-anchor-2).
  • fix Status re-check default — General → Status defaults to every 5 minutes for background bookmark reachability checks (status-recheck-interval-select).

Developer & docs

  • fix README, MANUAL, Config Help — self-hosting security, env-var table, extension shortcuts, Help sections Browser extension and Security & self-hosting (EN/NL/DE/FR); docker-compose.prod.yml commented prod env block.
  • fix CI on mainrelease-to-main.sh + ci.yml keep tests on main after prune.
  • fix Playwright E2E — full suite green: finders toBeHidden, config C14 snapshot baseline in waitForConfigReady, tags #tags-filter-empty-hint selector, layout-nudge manual replay (AUTO_PROMO_DISABLED), General toolbar scroll within Advanced max range; fresh temp NEXTDASH_DATA_DIR per managed run; config-dashboard-category-sync.spec.js and structure-sync assertion on bookmark save.
  • fix Tests — activity log, data-revision hash, stale name/url/shortcut, asset_versions_test.go drift check.
  • fix Cache-bustwhats-new-v124 data version; config-settings-guard-1 on config-persistence.js; status-rate-limit-1 on status.js; config-category-sync-1 on dashboard-render-incremental.js and dashboard-bookmark-rows.js; general-layer-scroll-anchor-2 on config-general-layers.js.
  • fix What's new sort order — manifest sorts by version tag first (v2026.07.03 before v2026.07.02); releasedAt is tie-breaker only (whats-new-v120).
  • fix What's new manifestindex.json regenerated from on-disk release JSON (tag order); CI checks index ↔ file parity; modal uses id || tag when fetching (whats-new-v121).

Don't miss a new nextdash release

NewReleases is sending notifications on new releases.