# nextDash — Changelog Complete release history for [nextDash](README.md), in the same style as the in-app **What's new** modal: version tags, themed sections, and **new** / **fix** labels on each item. For install and security, see the [README](README.md). For how to use features, see the [user manual](MANUAL.md). The dashboard **★** button and **Config → Advanced → What's new** show the latest highlights only. --- ## Table of contents - [Unreleased](#unreleased) - [v2026.07.17.2 — July 2026](#v2026071712--july-2026) - [v2026.07.17.1 — July 2026](#v2026071711--july-2026) - [v2026.07.17 — July 2026](#v20260717--july-2026) - [v2026.07.16 — July 2026](#v20260716--july-2026) - [v2026.07.15 — July 2026](#v20260715--july-2026) - [v2026.07.14.2 — July 2026](#v202607142--july-2026) - [v2026.07.14.1 — July 2026](#v202607141--july-2026) - [v2026.07.14 — July 2026](#v20260714--july-2026) - [v2026.07.13.1 — July 2026](#v202607131--july-2026) - [v2026.07.13 — July 2026](#v20260713--july-2026) - [v2026.07.12 — July 2026](#v20260712--july-2026) - [v2026.07.11.4 — July 2026](#v202607114--july-2026) - [v2026.07.11.3 — July 2026](#v202607113--july-2026) - [v2026.07.11.2 — July 2026](#v202607112--july-2026) - [v2026.07.11 — July 2026](#v20260711--july-2026) - [v2026.07.10.2 — July 2026](#v202607102--july-2026) - [v2026.07.10.1 — July 2026](#v202607101--july-2026) - [v2026.07.10 — July 2026](#v20260710--july-2026) - [v2026.07.09 — July 2026](#v20260709--july-2026) - [v2026.07.08.1 — July 2026](#v2026070081--july-2026) - [v2026.07.08 — July 2026](#v20260708--july-2026) - [v2026.07.07 — July 2026](#v20260707--july-2026) - [v2026.07.06.1 — July 2026](#v202607061--july-2026) - [v2026.07.06 — July 2026](#v20260706--july-2026) - [v2026.07.05.1 — July 2026](#v202607051--july-2026) - [v2026.07.05 — July 2026](#v20260705--july-2026) - [v2026.07.04 — July 2026](#v20260704--july-2026) - [v2026.07.03 — July 2026](#v20260703--july-2026) - [v2026.07.02 — July 2026](#v20260702--july-2026) - [v2026.07.01.9 — July 2026](#v202607019--july-2026) - [v2026.07.01.8 — July 2026](#v202607018--july-2026) - [v2026.07.01.7 — June 2026](#v202607017--june-2026) - [v2026.07.01.6 — July 2026](#v202607016--july-2026) - [v2026.07.01.5 — June 2026](#v202607015--june-2026) - [v2026.07.01.4 — July 2026](#v202607014--july-2026) - [v2026.07.01.3 — July 2026](#v202607013--july-2026) - [v2026.07.01.2 — July 2026](#v202607012--july-2026) - [v2026.07.01.1 — July 2026](#v202607011--july-2026) - [v2026.07.01 — July 2026](#v20260701--july-2026) - [v2026.06.31 — June 2026](#v20260631--june-2026) - [v2026.06.30.2 — June 2026](#v202606302--june-2026) - [v2026.06.30.1 — June 2026](#v202606301--june-2026) - [v2026.06.30 — June 2026](#v20260630--june-2026) - [v2026.06.29.1 — June 2026](#v202606291--june-2026) - [v2026.06.29 — June 2026](#v20260629--june-2026) - [v2026.06.28 — June 2026](#v20260628--june-2026) - [v2026.06.27 — June 2026](#v20260627--june-2026) - [v2026.06.26 — June 2026](#v20260626--june-2026) - [v2026.06.25 — June 2026](#v20260625--june-2026) - [v2026.06.24 — June 2026](#v20260624--june-2026) - [v2026.06.23 — June 2026](#v20260623--june-2026) - [v2026.06.22 — June 2026](#v20260622--june-2026) - [v2026.06.21 — June 2026](#v20260621--june-2026) - [v2026.06.20 — June 2026](#v20260620--june-2026) - [v2026.06.19 — June 2026](#v20260619--june-2026) - [v2026.06.17 — June 2026](#v20260617--june-2026) - [v2026.06.16 — June 2026](#v20260616--june-2026) - [v2026.06.15 — June 2026](#v20260615--june-2026) - [v2026.06.14 — June 2026](#v20260614--june-2026) - [v2026.06.13 — June 2026](#v20260613--june-2026) - [v2026.06.12 — June 2026](#v20260612--june-2026) - [v2026.06.11 — June 2026](#v20260611--june-2026) - [v2026.06.10 — June 2026](#v20260610--june-2026) - [v2026.06.9 — June 2026](#v2026069--june-2026) - [v2026.06.8 — June 2026](#v2026068--june-2026) - [v2026.06.7 — June 2026](#v2026067--june-2026) - [v2026.06.6 — May 2026](#v2026066--may-2026) - [v2026.06.5 — May 2026](#v2026065--may-2026) - [v2026.06.4 — May 2026](#v2026064--may-2026) - [v2026.06.3 — June 2026](#v2026063--june-2026) - [v2026.06.2 — June 2026](#v2026062--june-2026) - [v2026.06.1 — June 2026](#v2026061--june-2026) - [v2026.05.7 — May 2026](#v2026057--may-2026) - [v2026.05.6 — May 2026](#v2026056--may-2026) - [v2026.05.5 — May 2026](#v2026055--may-2026) - [v2026.05.4 — May 2026](#v2026054--may-2026) - [v2026.05.3 — May 2026](#v2026053--may-2026) - [v2026.05.2 — May 2026](#v2026052--may-2026) - [v2026.05.1 — May 2026](#v2026051--may-2026) - [v2026.05 — May 2026](#v202605--may-2026) - [v2026.04 — April 2026](#v202604--april-2026) - [v2026.03 — March 2026](#v202603--march-2026) - [v2026.02 — February 2026](#v202602--february-2026) - [v2026.01 and earlier — Foundation](#v202601-and-earlier--foundation) --- ## Unreleased Nothing yet. --- ## v2026.07.17.2 — July 2026 **Jump between dashboard and config with `<`** — a single keyboard shortcut now toggles the two pages. ### Navigation - **new** **`<` opens config from the dashboard, and returns to the dashboard from config** — `<` (which is `Shift+,`, next to the `,` page overview) jumps to `/config` on the dashboard; in config it goes back to the dashboard, asking to confirm first if there are unsaved changes. Layout-independent: it accepts both the `<` character and the physical comma key with Shift, so it works on keyboard layouts that don't emit `<`. Documented in the dashboard cheat sheet (`!` / `F1`) and the Config → Keyboard tab, localized across EN / NL / DE / FR (`dashboard-setup.js`, `config-ui.js`). ### Config - **new** **Config → General opens compact on first visit** — a fresh first open of Config → General lands on **Essentials** with only **Localisation** expanded, instead of four sections open at once. Once you expand or collapse any section, your own layout is remembered as before (`config-setup.js`). --- ## v2026.07.17.1 — July 2026 **Custom theme name fields hotfix** — the two "Custom Theme" name inputs under Colors → Custom themes rendered with unstyled browser-default white input boxes instead of the dashboard's theme colors. ### Theme - **fix** **Custom theme name inputs styled** — `.custom-theme-list-item` and its reorder buttons/name input had no CSS at all, so the name field fell back to the browser default (white background, black text) regardless of the active theme. Added matching styles consistent with the existing `.category-item`/`.finder-item` list rows (`config-lists.css`, `config.css`). --- ## v2026.07.17 — July 2026 **Tours, spotlights, and promo balloons removed; quick-start card and Tips & tricks in Help take their place** — the entire interruptive discoverability layer (onboarding wizard, nine config-tab guided tours, dashboard feature tour, ~20 one-time promo balloons) is gone, replaced by a short first-run quick-start card and a proper Tips & tricks section in Help. ### Onboarding - **new** **Quick-start card** — first run shows a compact three-step card (language & auto dark mode, packed columns & columns per row, open-in-new-tab & weather) followed by a short dismissible checklist (add a bookmark, tag one, open Config → General, see the keyboard cheat sheet). The cheat-sheet checklist row is a button so there is always a way to open it, even when the toolbar's cheat-sheet button is hidden. Progress lives in `settings.quickStart` server-side, not `localStorage`, so it holds across devices (`models.go`, `dashboard-quickstart.js`, `dashboard-quickstart.css`, `dashboard/dashboard-promos.js`). - **new** **Tips & tricks section in Help** — the rotating footer tips (64 entries, one line at a time, five to eight seconds apart) are retired. A new **Tips & tricks** `.help-block` groups 30 rewritten tips by task — Everyday, Adding bookmarks, Editing and organising, Finding things, Keeping it healthy, Making it yours — each naming what the key is *for*, not just the key. Picked up automatically by the Help search filter, quick-links nav, and accordion (`config-help-tips.js`, `config.html`, `locales/{en,nl,de,fr}.json`). ### Removed - **fix** **Config-tab tours** — the nine guided tours (General, Bookmarks, Pages, Categories, Tags, Stats, Collections, Finders, Theme) and their ~40 call sites in config.js are removed; the modules are deleted and their stylesheets with them (`config-*-tour.js`, `config-general-tour.css`, `feature-tour.css`, `onboarding.css`). - **fix** **Dashboard promo balloons** — ~21 one-time "Got it" balloons (search modes, grid navigation, G+jump, smart collections, inline edit, tag cloud, tag-filter bulk toolbar, recent bookmarks, preview, quick-add, week overview, category collapse/rename, quick move/tag/delete, page overview, cheat sheet, weather location) and the promo registry that sequenced them are gone, along with `dashboard-promo-placement.js`'s anchor-sync for keyboard selection moves. Everything they taught is already in the keyboard cheat sheet, in more detail. `dashboard-promo-placement.js` itself stays — it also positions the config settings-search popover and the dashboard quick-move popover (`static/js/dashboard-*-promo.js`, `static/css/dashboard-*-promo.css`). - **fix** **Spotlights, layout nudge, and one-time toasts** — the paste and preview-card spotlights, the "try modern layout" nudge, the inbox intro modal/toast, and the layout beta/glass toasts are removed. `dashboard-promos.js` drops from ~335 to ~115 lines now that the skip flags, retry budgets, and abort/reschedule bookkeeping that ordered these against each other have nothing left to order. The device-specific glass→classic layout migration this toast used to run on load moves to `layout-version-utils.js` (`dashboard-promos.js`, `layout-version-utils.js`). - **fix** **`:tour` and `:promo` commands removed** — both pointed at systems that no longer exist (`search-commands.js`). - **fix** **Settings search promo is the one balloon that stays** — its `isGuidedFlowActive()` guard collapses to just the What's new modal now that tours and spotlights are gone, and it no longer covers the config tab bar: it is clamped to the search field's top so it can hang below the anchor but never above it (`config-settings-search.js`, `config-settings-search.css`). - **fix** **Dead CSS removed** — eleven `.button-hint` rules across five stylesheets styled the tip strip above the footer buttons that no longer exists; the mobile rule that grouped it with `.feature-spotlight` is trimmed rather than dropped, since the search-flow hint it also covers is still live (`layout-modern.css`, `layout-side-rail.css`, `mobile-experience.css`, `search.css`, `dashboard.html`). ### Help - **fix** **Help text matches what's actually there** — Getting started, Configuring, Search & toolbar, Workspace, Tags & collections, Inbox, and Finders no longer send you to buttons that are gone (e.g. "replay from Advanced → System → Tours & onboarding"); Getting started now describes the quick-start card. What's new entries keep their original tour/spotlight mentions since those releases really did ship them (`locales/{en,nl,de,fr}.json`). - **fix** **Two missing translations filled in** — `helpIntro` (Help's opening paragraph) was still English in German and French; `customThemesInfoTitle` was still English in Dutch. Found by auditing all four locale files for values that match English when the key sets were already in sync (`locales/{de,fr,nl}.json`). ### Developer & docs - **fix** **What's new modal** — **v2026.07.17** JSON added for the removal + quick-start + Tips & tricks arc. - **fix** **README, MANUAL & Config Help** — updated throughout to describe the quick-start card and Tips & tricks instead of the removed tours, spotlights, and promo balloons. - **fix** **Cache-bust** — `whats-new-v164` data version (`asset_versions.go`, `whats-new-stub.js`) and `2026.07-dashboard-release-v122` dashboard release token. - **fix** **Leftover config-page dead code from the tour removal** — the "Onboarding & tips" advanced section still had a "Reset context tips" button whose feature no longer exists; clicking it cleared two dead `localStorage` keys and showed a false success toast. Removed the button, its handler, its CSS rule, and five now-unused locale keys in all four languages; the section is renamed "Onboarding" (`config.html`, `config-setup.js`, `config-forms.css`, `locales/{en,nl,de,fr}.json`). - **fix** **Five dead `asset_versions.go` fields removed** — `ConfigBookmarksTourJS`, `ConfigToursRuntimeJS`, `PageLayoutSyncJS`, `ConfigGeneralTourCSS`, and `ConfigButtonsCSS` pointed at files deleted with the tour removal; `static/js/page-layout-sync.js` (186 lines, a leftover from the pre-v2026.07.15 standalone `/health` page) is deleted outright (`asset_versions.go`). - **fix** **Five dead Go wrapper functions removed** — `pingURL`, `fetchPageTitleSafe`, `detectRedirectURL`, `redirectLocationFromResponse`, and `validatePublicHTTPURL` were thin `context.Background()` shims around their `*Ctx` counterparts that production code no longer called directly; only their own tests did, so the tests now call the `*Ctx` variants instead (`ping.go`, `handlers.go`, `url_safety.go`). - **fix** **Playwright suite pruned of tests for already-removed features** — 18 tests across 8 files asserted on the config-tab tours, onboarding wizard, dashboard search/G-jump promos, inbox intro modal/toast, layout-version nudge spotlight, `:tips` command, and `:buttons health` toggle, all deleted in earlier July releases; removed along with their now-unused `e2e-helpers.js` onboarding helpers. Two real bugs surfaced in the same pass and were fixed rather than deleted: the side-rail legend test needed to reset `onboardingStartedInSession` now that the quick-start card (not the old wizard) sets it, and the Help tips test targeted a disclosure/accordion structure the Tips & tricks redesign replaced (`tests/*.spec.js`, `tests/e2e-helpers.js`). --- ## v2026.07.16 — July 2026 **Inbox triage with snooze and keyboard polish, plus Health that stays current** — Inbox gains snooze/read-later, row shortcuts, notes, and bulk clean-up; Health is always on, can re-check in the background, and Edit opens the dashboard inline editor. ### Inbox - **new** **Snooze / read later** — park a link for 3 hours, tomorrow, this weekend, or next week. Snoozed items leave All/Unread until they wake, with a **Snoozed** filter, grouped wake times, an auto-wake timer, `z` to open snooze, and **Wake now** (`inbox.go`, `inbox_handlers.go`, `dashboard-inbox.js`, `dashboard-inbox.css`, `locales/{en,nl,de,fr}.json`). - **new** **Keyboard navigation** — `j`/`k` move, `g`/`G` first/last, and row keys: `Enter`/`Space` open, `p` promote, `r` mark read, `n` note, `z` snooze, `d` delete, plus a legend under the list and Health-style selection animation (`dashboard-inbox.js`, `dashboard-inbox.css`, `dashboard.html`). - **new** **Notes on Inbox links** — add/edit a note from the row or `n`, backed by the existing PATCH endpoint (`dashboard-inbox.js`, locales). - **new** **Mark read & bulk actions** — unread rows get a mark-read button (not keyboard-only); toolbar **Mark all read** (scoped to the current filter) and **Clear read** with a single batch undo (`dashboard-inbox.js`, locales). - **fix** **Preview loading state** — freshly added items pulse a placeholder while the server enriches the preview, then a self-cancelling poll swaps it in (`dashboard-inbox.js`, `dashboard-inbox.css`). - **fix** **Promote triggers a health check** — when status checks are on, promoting an Inbox link fire-and-forgets `POST /api/health/check-url` so the new bookmark is not stuck as unchecked on Health until the next full retest (`health_check_url.go`, `dashboard-inbox.js`, `main.go`). - **fix** **Inbox toast counts** — `t()` no longer double-prefixes `dashboard.` before `formatDashboardLabel`, and fallback strings interpolate params, so bulk/clear toasts no longer show raw `{count}` (`dashboard-inbox.js`). ### Health - **new** **Health always on** — `ShowHealthDashboard` is forced on regardless of stored value; the Header & buttons Health-link checkbox, info button, autosave binding, and `:buttons` toggle are removed (`models.go`, `config.html`, `config-settings.js`, `search-commands.js`). - **new** **Optional background rechecks** — server-side periodic re-pings of status-checked bookmarks (off by default; interval 6h–weekly, default 24h) under **Config → General → Status monitoring**, with last-run persistence across restarts (`health_recheck.go`, `handlers.go`, `models.go`, `config.html`, locales). - **fix** **Edit opens the dashboard inline editor** — Health row Edit deep-links with an `edit` flag to leave the Health view, land on the bookmark’s page, and open inline edit (falls back to Config when the helper is absent) (`dashboard-health.js`, `dashboard-deep-link.js`, `dashboard-page-nav.js`). - **fix** **Deep-link filters match correctly** — `matchesFilter` now handles stale / unused / missing-preview / shortcut-conflict / healthy instead of showing the full list (`dashboard-health.js`). - **fix** **Shortcut legend declutter** — the redundant legend under the toolbar is removed; the single copy under the feed stays announced to assistive tech (`dashboard-health.js`, `health-view.css`, `dashboard.html`). - **fix** **Active Health underline** — the selected heartbeat icon’s bottom border sits square with page-nav / inbox tabs (`dashboard.css`, `layout-modern.css`). ### Developer & docs - **new** **Tests** — Go coverage for single-URL health check and background recheck scheduling (`health_check_url_test.go`, `health_recheck_test.go`); Playwright health-view legend expectations updated (`tests/health-dashboard-view.spec.js`). - **fix** **README, MANUAL & Config Help** — **v2026.07.16** notes for Inbox snooze/keyboard/bulk, Health always-on, background rechecks, and Edit → inline editor. - **fix** **MANUAL documents `Shift+H`** — Health open shortcut added on the header health entry, keyboard table (`Shift+I` / `Shift+H`), Health view intro, Essentials status overview, and `:health` / `:inbox` command rows (`MANUAL.md`). - **fix** **What's new modal** — **v2026.07.16** JSON refreshed with missing Inbox/Health fixes (toast counts, square Health underline, `Shift+H` docs) and corrected Inbox open key (`Enter`, not `o`). - **fix** **Inbox open key copy** — README, MANUAL, and Config → Help no longer list `o` for Inbox open; they match the real `Enter` / `Space` binding (and include `z` for snooze). - **fix** **Cache-bust** — `whats-new-v163` data version (`asset_versions.go`, `whats-new-stub.js`) and `2026.07-dashboard-release-v121` dashboard release token. --- ## v2026.07.15 — July 2026 **Health in the dashboard, faster keyboard entry points, and a cleaner config header** — health now opens as an in-dashboard view (alongside Inbox), `Shift+H`/`Shift+I` jump into Health/Inbox, and Config keeps a single back-to-dashboard header link. ### Dashboard - **new** **Health as an in-dashboard view** — the header heartbeat icon now opens a dedicated **Health** view inside the dashboard shell (like Inbox) instead of forcing a page jump. It keeps a calmer, keyboard-first subset: one list, quick filters, score breakdown, re-check, and row actions (`dashboard-health.js`, `dashboard.html`, `health-view.css`). - **new** **Health deep-link and active-state polish** — `#health` opens and restores the dashboard view correctly, the health header icon gets an active state aligned with page tabs, and Escape returns to the bookmarks grid cleanly (`dashboard-page-nav.js`, `dashboard-render-core.js`, `dashboard.css`). - **fix** **Keyboard flow inside the new view** — row shortcuts no longer die after changing a sort select, and page-load races no longer overwrite `#health` back to a page hash (`dashboard-health.js`, `dashboard-page-nav.js`, `dashboard-data.js`, `keyboard-navigation.js`). ### Keyboard - **new** **Shift shortcuts for views** — `Shift+H` opens Health and `Shift+I` opens Inbox directly from the dashboard, using `e.code` so physical-key behavior is layout-safe. Legacy `0` still opens Inbox for compatibility but is intentionally removed from the cheat sheet (`dashboard-setup.js`, `dashboard-ui-helpers.js`, `locales/{en,nl,de,fr}.json`). ### Config - **fix** **Config header simplified** — the config header no longer duplicates the health icon entry point; it now keeps only **← back to dashboard**. Health broken-count updates still power Status Essentials links by reading the shared health summary directly, without a header anchor dependency (`config.html`, `config-setup.js`). ### Developer & docs - **fix** **Tests** — added dashboard health-view coverage for in-place open/close behavior, keyboard controls, duplicate filtering, and `#health` deep-link restore (`tests/health-dashboard-view.spec.js`). - **fix** **Health view i18n parity** — all new health-view labels plus new cheat-sheet entries (`Shift+H`, `Shift+I`, `:health page`) are now present in `en`, `nl`, `de`, and `fr`, with localized wording tuned to each language's existing style (`locales/{en,nl,de,fr}.json`). - **fix** **Standalone health removal follow-up** — legacy `/health` now redirects to `/#health`, old standalone health assets/tests were removed, and docs/help text were aligned to dashboard-first routing while keeping **v2026.07.15** (`handlers.go`, `templates/health.html`, `static/js/health.js`, `README.md`, `MANUAL.md`, `locales/{en,nl,de,fr}.json`). - **fix** **What's new modal** — added **v2026.07.15** JSON entry with dashboard/keyboard/config highlights. - **fix** **Cache-bust** — `whats-new-v160` data version (`asset_versions.go`, `whats-new-stub.js`) and `2026.07-dashboard-release-v119` dashboard release token. --- ## v2026.07.14.2 — July 2026 **Health repairs that stick, and a score that explains itself** — the health page can clear a broken link, verify a redirect before trusting it, and show what each issue costs. Glass is retired. ### Health - **fix** **Repairs are visible immediately** — `invalidateHealthReportCache()` existed but no health handler called it (only `backup.go`), so every mutation stayed hidden behind the 3-minute report TTL: a successful ping cleared `LastError` on disk while the report kept reporting broken. All six mutating handlers now invalidate (`handlers.go`). - **fix** **Retest reaches flagged bookmarks** — the run skipped every bookmark with `checkStatus` off (the default) and still reported `completed`, so a row rendered broken and scored −60 could never be cleared from a page that exposes no `checkStatus` toggle. `scope=all` now includes rows with a recorded error, a run that tests nothing says so, and a second `CheckStatus` filter in the write-back that discarded the results is gone. Capped at 250 pings per run — they are sequential at up to 3s each (`handlers.go`, `health.js`). - **fix** **Redirects are verified before they are trusted** — `AutoHealApply` cleared `LastError` on the strength of "the URL changed" without contacting the replacement. It now pings the new URL before storing it and keeps the row red, with the reason, when it still fails (`handlers.go`, `health.js`). - **new** **Score breakdown** — the score badge expands (click or s) into the per-reason deductions and the total. Penalties travel from the server on each `HealthReason` as named constants beside the arithmetic, rather than being restated in JS where they would drift; a test pins them to `100 - score` (`models.go`, `handlers.go`, `health.js`, `health.css`). - **new** **Keyboard navigation** — the score badge was a `div` and unreachable; reaching the first row cost 27 tab stops with 8 more per row, leaving the last of 100 bookmarks unreachable. Rows now use roving tabindex mirroring `KeyboardNavigation.syncRovingTabStops`: one stop per row, `Tab` walks them and releases at either end, and `s`/`x`/`p`/`f`/`m`/`g`/`G` cover the controls that left the tab order. Filter pills became one stop with arrow keys, as their `role="toolbar"` already promised. `Enter` on a row control no longer also fires the row's edit shortcut (`health.js`, `health.css`, `templates/health.html`). - **fix** **Page cleanup** — removed a dead `if` block and the duplicate keyboard hint that listed only half the keys; the shortcut legend replaces it (`templates/health.html`). ### Appearance - **fix** **Glass layout removed** — one of three parallel layouts, each needing its own CSS for every visual change; dropping it removes ~3,100 lines. Stored settings migrate silently: `models.go` validates `layoutVersion` against the allowed list and falls back to `classic`, so dropping `glass` from that list *is* the migration, and localStorage device settings normalize the same way. Because both paths rewrite `glass` without a trace, `theme-loader` records the raw value first and a one-time toast tells the user their layout changed (`models.go`, `theme-loader.js`, `layout-beta-toast.js`). ### Dashboard - **fix** **One-time toasts no longer starve** — `runPostOnboardingPrompts` is a chain of early returns, and what's new returns until acknowledged, leaving the layout and Inbox intro toasts unreachable for anyone with an unseen release. Both own their storage keys and retry until a blocking modal closes, so they are now scheduled before the chain rather than at its tail (`dashboard/dashboard-promos.js`, `layout-beta-toast.js`, `inbox-intro-toast.js`). ### Developer & docs - **fix** **Cache-bust coverage** — 52 asset references moved onto the `Assets` system (32 were untokened, so `static_cache.go` served them `max-age=86400` and a deploy stayed invisible for up to a day — the head scripts are the sharp end, `write-api.js` carries write-token auth). Fixed a dual cache identity where `config-buttons.css` resolved to two URLs from different entry points (`asset_versions.go`, `config.css`, templates). - **fix** **E2E tests** — four specs failed on a clean tree because they outlived the code they check: `openShortcutSearch` typed `>` via `press('Shift+.')`, which sends key `.` with `shiftKey` — a chord no keyboard produces — firing collapse-all and leaving `navigableElements` at 0; the backups tab asserted 3 sections after Automatic Backups made it 4; the layout nudge asserted the Glass button removed with Glass; and category reorder identified categories by `data-category-id`, which derived buckets also carry while never being reorderable (`e2e-helpers.js`, `config-tab-consistency.spec.js`, `dashboard-grid-shortcuts.spec.js`, `dashboard-recent-and-nudge.spec.js`, `dashboard-category-reorder.spec.js`). - **new** **Tests** — 6 Go tests covering cache invalidation, retest scope, redirect verification and penalty arithmetic (`health_report_invalidation_test.go`); 21 Playwright tests covering the score breakdown, the keyboard model, tab order, and retest loop guards (`health-score-keyboard.spec.js`, `health-tab-navigation.spec.js`, `health-retest-loop.spec.js`). - **fix** **README, MANUAL & Config Help** — **v2026.07.14.2** notes. - **fix** **Cache-bust** — `whats-new-v159` data version (`asset_versions.go`, `whats-new-stub.js`), `2026.07-dashboard-release-v118` dashboard release token, and bumped `health.js` / `health.css` asset tokens. --- ## v2026.07.14.1 — July 2026 **Drag feedback for sorted categories** — dragging a bookmark in an A–Z / Recent category now explains why it can't be reordered instead of doing nothing. ### Bookmarks - **fix** **Explain why a sorted category won't drag** — categories sorted **A–Z** or **Recent** don't create a `DragReorder` instance (a manual drag would be re-sorted away), so bookmarks there aren't draggable. That previously looked broken. Sort-active lists now carry a hover tooltip and a `not-allowed` cursor, and a genuine drag gesture (press + >8px move) shows a single throttled toast telling you to switch the category back to manual order; a plain click still opens the bookmark (`dashboard/dashboard-render-core.js` `attachSortLockedDragHint`, `css/dashboard.css`, `locales/{en,nl,de,fr}.json`). ### Developer & docs - **fix** **Tests** — added an e2e case in `dashboard-bookmark-drag.spec.js` asserting the hover tooltip, the explain-why toast on a drag attempt, and silence on a plain click (forces a full render so the sort-locked hint attaches deterministically). - **fix** **README, MANUAL & Config Help** — **v2026.07.14.1** notes. - **fix** **Cache-bust** — `whats-new-v158` data version (`asset_versions.go`, `whats-new-stub.js`), `2026.07-dashboard-release-v117` dashboard release token, and bumped `dashboard.css` / render-core asset tokens. --- ## v2026.07.14 — July 2026 **Dashboard organising** — drag bookmarks by the whole row (no more column flicker), collapse or expand every category with one key, drag categories by their `//`, and create a page or category inline from the add-bookmark form. ### Bookmarks - **fix** **Drag-to-reorder from the whole row** — a bookmark can be dragged from anywhere on its row instead of only the near-invisible left grip. The row is the drag handle (`handleSelector: null`) and the row's `` is set `draggable=false` so the browser's native link-drag can no longer hijack the reorder. A single click still opens the bookmark; a stationary long-press still opens the inline editor (`dashboard/dashboard-render-core.js`, `dashboard/dashboard-bookmark-rows.js`). - **fix** **Long-press editor no longer fires mid-drag** — once a native HTML5 drag starts the browser stops sending `pointermove`, so the long-press slop check could not cancel and the inline editor opened during a drag. A `dragstart` handler now cancels the pending long-press, with a `body.bookmark-dragging` / `is-draggable` guard as a backstop (`dashboard/dashboard-inline-edit.js`). - **fix** **No column flicker when dragging across columns** — the drop relay now moves only the placeholder and hides the dragged row (`display:none`) during the drag, committing the row into the placeholder's slot at `dragend`. Moving the real row live changed a column's height, which shifted the layout under a still cursor and made `elementFromPoint` oscillate. `DragReorder`'s container `dragover` is also disabled when a document-level relay owns it, so two handlers no longer fight over the row (`dashboard/dashboard-render-core.js`, `reorder.js`). ### Categories - **new** **Collapse / expand all** — press `.` anywhere on the dashboard (or the new toolbar button) to fold every category at once; it smart-toggles (any open → collapse all; all closed → expand all) and the state is saved per page. Added a cheat-sheet entry and the `.` shortcut to the keyboard help (`dashboard/dashboard-render-core.js`, `dashboard/dashboard-toolbar.js`, `dashboard/dashboard-ui-helpers.js`, `templates/dashboard.html`, `css/dashboard.css`, `locales/{en,nl,de,fr}.json`). - **new** **Restore category drag-reorder via `//`** — the `//` prefix in a real category's title is a drag handle again and reorders whole sections, including across columns in packed layouts (a document-level relay fixes the original cross-column bug). Dragging the handle no longer toggles collapse or starts a rename; a plain click still collapses (`dashboard/dashboard-render-core.js`, `dashboard/dashboard-render-incremental.js`, `dashboard.js`, `css/dashboard.css`). ### Adding bookmarks - **new** **Inline new page / category** — the add-bookmark form's **Page** and **Category** dropdowns each carry a **+ New…** option that creates and saves the page or category on the spot (no bookmark required) and reselects it, refreshing the dashboard data. Uses the existing categories/pages APIs (`search-commands/search-commands-new.js`, `css/search-commands-new.css`, `locales/{en,nl,de,fr}.json`). ### Developer & docs - **fix** **Tests** — added `dashboard-bookmark-drag.spec.js` (whole-row handle, cross-category move, no-flicker while holding, dragstart-cancels-long-press, stationary long-press opens editor) and `dashboard-category-reorder.spec.js` (handle presence, click-does-not-collapse, reorder persists). - **fix** **README, MANUAL & Config Help** — **v2026.07.14** notes; the category-reorder and collapse-all wording in MANUAL and Config Help now points at the `//` handle and the `.` shortcut. - **fix** **Cache-bust** — `whats-new-v157` data version (`asset_versions.go`, `whats-new-stub.js`), `2026.07-dashboard-release-v116` dashboard release token, and bumped `reorder.js` / render-core / bookmark-rows / inline-edit / ui-helpers asset tokens. --- ## v2026.07.13.1 — July 2026 **Automatic-backup refinements** — restore a stored backup in one click, a totals line, a last-backup-date fix, and a same-second filename fix. ### Backups - **new** **Restore from the list** — each stored automatic backup gains a **Restore** button (`POST /api/auto-backups/restore?name=…`) that replaces all current data with that backup and reloads. The upload-import pipeline was refactored into a shared `applyStagedImport`, and the restore path unpacks the stored ZIP into staged files via `stagedFilesFromZip`, so restore and upload import go through the same atomic commit and category-save (`auto_backup.go`, `backup.go`, `main.go`). The restore button uses the destructive theme colour with a confirm dialog and marks favicons for prefetch on reload (`config/config-backup.js`, `templates/config.html`, `locales/{en,nl,de,fr}.json`). - **new** **Totals summary** — the *Automatic Backups* section shows a “{count} backups · {size} total” line under the list, hidden when empty (`config/config-backup.js`, `templates/config.html`, `locales/{en,nl,de,fr}.json`). - **fix** **Back Up Now updates the last-backup date** — an on-demand automatic backup now writes `nextdash-last-backup` and refreshes the *Last backup* label, matching the manual ZIP download (`config/config-backup.js`). - **fix** **Same-second filenames no longer collide** — `writeAutoBackup` now uses `uniqueAutoBackupName`, appending a `-2`, `-3`, … suffix when several backups are written within the same second, so a rapid *Back Up Now* no longer overwrites a just-written file. The filename regex accepts the optional suffix, and download/delete/restore share a single `resolveAutoBackupPath` validator (`auto_backup.go`). ### Developer & docs - **fix** **Tests** — added same-second uniqueness and restore round-trip coverage (plus restore name/traversal rejection) in `auto_backup_test.go`, and dropped the now-unnecessary sleeps from the rotation test. - **fix** **README, MANUAL, CHANGELOG & Config Help** — **v2026.07.13.1** notes. - **fix** **What's new modal** — **v2026.07.13.1** JSON entry with a *Backups* section (no doc-update or cache-bust item, by design). - **fix** **Cache-bust** — `whats-new-v156` data version (`asset_versions.go`, `whats-new-stub.js`) and `2026.07-dashboard-release-v115` dashboard release token. --- ## v2026.07.13 — July 2026 **Automatic weekly backups** — nextDash now keeps a rolling set of ZIP backups on the server, with download, delete, on-demand run, and a countdown, plus two link-health fixes. ### Backups - **new** **Automatic weekly backups** — a scheduler goroutine creates a full ZIP backup once a week and stores it under `data/auto-backups/`, keeping the latest 3 (the oldest is pruned when a new one is written). Backups are written atomically behind a mutex; the ZIP is built by a shared `buildBackupZip()` so downloads and automatic backups are byte-for-byte identical, and the `auto-backups/` directory is excluded from regular backups to avoid backup-in-backup (`auto_backup.go`, `backup.go`, `main.go`). - **new** **Restart-robust scheduling** — instead of a fragile 168-hour in-process timer, the scheduler re-checks every few hours and runs a backup whenever the newest one is older than 7 days, so a container that restarts often still gets its weekly backup. It stops cleanly on shutdown via a dedicated stop channel (`auto_backup.go`, `main.go`). - **new** **Enable/disable toggle** — a new `autoBackupEnabled` setting (default on) gates the automatic run; disabling it never affects the manual *Back Up Now* button or existing files. Defaulted on for fresh installs and for older settings files missing the key, matching the `allowLocalBookmarks` pattern (`models.go`). - **new** **Config → Backup UI** — a new *Automatic Backups* section lists each stored backup with its date and size, a **Download** button, and a **Delete** button (in the destructive theme colour, with a confirm dialog), plus a **Back Up Now** button and a live countdown to the next scheduled backup (`templates/config.html`, `config/config-backup.js`, `config.js`, `css/config/config-backups.css`). - **new** **API endpoints** — `GET /api/auto-backups` (list + `enabled` + `nextBackupAt`), `GET /api/auto-backups/download?name=…`, `DELETE /api/auto-backups?name=…`, and `POST /api/auto-backups/run`. Download and delete strictly validate the filename shape and reject path traversal; write endpoints go through `requireWriteAccess` (`auto_backup.go`, `main.go`). ### Link health - **fix** **Bulk delete removes the selected bookmarks** — deleting multiple broken links at once from the health dashboard now removes exactly the selected bookmarks instead of occasionally removing the wrong one. - **fix** **Health favicon URL encoding** — favicon filenames in the health dashboard are now encoded, so a filename with a space or special character loads correctly instead of failing the request. ### Developer & docs - **fix** **Tests** — added `auto_backup_test.go` covering rotation (4 → 3, oldest pruned), exclusion of `auto-backups/` from regular backups, download/delete name validation and traversal rejection, the 404 delete case, and due/not-due logic, plus `autoBackupEnabled` default and explicit-false assertions in `settings_defaults_test.go`. - **fix** **README, MANUAL, CHANGELOG & Config Help** — **v2026.07.13** notes. - **fix** **What's new modal** — **v2026.07.13** JSON entry with *Backups* and *Link health* sections (no doc-update or cache-bust item, by design). - **fix** **Cache-bust** — `whats-new-v155` data version (`asset_versions.go`, `whats-new-stub.js`) and `2026.07-dashboard-release-v114` dashboard release token. --- ## v2026.07.12 — July 2026 **Fresh defaults** — new installs open on the Kelp Drift dark theme with auto dark mode on and updated starter bookmarks, plus a couple of small dashboard polish fixes. ### Appearance - **new** **Default theme** — a fresh install now defaults to the `kelp-drift-dark` theme with `autoDarkMode` on, so the dashboard follows the system light/dark preference out of the box. Applied across the backend defaults (`models.go`, both the initial-write and the file-missing fallback) and the config/dashboard front-end defaults (`config.js`, `dashboard.js`, `config/config-settings.js`). Existing settings files are untouched. ### Bookmarks - **new** **Starter bookmarks** — the default first page now seeds a *Tech* category with Unraid and Phoronix, and a *Social* category with Bluesky, replacing the old Facebook and Instagram entries (`models.go`). Only affects brand-new installs. ### Dashboard - **fix** **Quick-add omnibox restyle** — the `&` quick-add line now uses rounded corners, a blurred-glass background, soft shadow, and a spring entrance animation matching the search/commands/finders overlays instead of the old flat box (`static/css/dashboard.css`). - **fix** **Config → Bookmarks starts on the first page** — a fresh config load now selects the first visible page (main) instead of following the dashboard's current page; the user's page choice is kept in memory for the rest of the session, so it only resets on the next fresh load (`config.js`). - **fix** **Icon URL encoding** — bookmark and category icon `` values on the dashboard now wrap the filename in `encodeURIComponent`, matching the inline editor, so a filename with a space, `#`, `?` or similar no longer breaks the URL and falls back to the letter avatar (`dashboard-bookmark-rows.js`, `dashboard-render-core.js`). The search overlay was already safe via its filename regex guard. - **fix** **Config → Bookmarks page id NaN guard** — `loadPageBookmarks` normalizes the page id once with `Number(...)` and a numeric fallback (current page, then `1`) instead of a bare `parseInt`, so a non-numeric page-selector value can never store `NaN` in `currentPageId`; the normalized id is used consistently for `loadPage` and `loadCategoriesByPage` (`config-bookmarks-controller.js`). ### Onboarding - **new** **Kelp Drift in the tour** — the onboarding auto-dark-mode step now defaults to *On*, and the mobile theme picker offers *Kelp Drift (dark)* and *Kelp Drift (light)* as the first options, with new `mobileThemeKelpDark` / `mobileThemeKelpLight` translations in all four locales (`onboarding.js`, `locales/{en,nl,de,fr}.json`). ### Developer & docs - **fix** **i18n parity** — removed orphan `helpPageTipsTitle` (de, fr) and `helpPageExtensionTitle` / `helpPageSecurityTitle` (fr) keys that had no code reference and were absent from en/nl, bringing all four locales back on par (`locales/de.json`, `locales/fr.json`). - **fix** **README, MANUAL, CHANGELOG & Config Help** — **v2026.07.12** notes. - **fix** **What's new modal** — **v2026.07.12** JSON entry with *Appearance*, *Bookmarks*, and *Dashboard polish* sections (no doc-update item, by design). - **fix** **Cache-bust** — `whats-new-v154` data version and `data-revision-5` (`asset_versions.go`, `whats-new-stub.js`), `2026.07-dashboard-release-v113` dashboard release token, and `omnibox-glass-1`, `kelp-drift-default-1`, `kelp-drift-bookmarks-page-1`, `icon-url-encode-1` asset query strings on the changed CSS/JS. --- ## v2026.07.11.4 — July 2026 **Smoother dialogs** — a polish pass on dialog windows so keyboard and screen-reader focus is handed back cleanly on close, with no console warnings. ### Accessibility - **fix** **Modal focus** — closing a modal no longer sets `aria-hidden="true"` on the overlay while a button inside it still holds focus, which Chrome flagged in the console ("focus must not be hidden from assistive technology"). Focus is now moved back to the opener (or blurred when the opener can't take focus) before the overlay is hidden (`modal.js`). - **fix** **Modal buttons** — the confirm/cancel buttons now set `type="button"` so they can never submit an enclosing form by default (`modal.js`). - **fix** **Modal initial focus** — the opening modal now focuses its first control via a double `requestAnimationFrame` instead of a fixed `setTimeout`, so it no longer depends on a hard-coded transition duration and skips focusing if the modal was closed again first (`modal.js`). ### Compatibility - **fix** **PWA meta tag** — added the standard `mobile-web-app-capable` meta tag alongside the Apple-specific one to silence Chrome's deprecation warning (`templates/dashboard.html`, `templates/config.html`, `templates/health.html`). ### Developer & docs - **fix** **Cheat-sheet scroll test** — the keyboard-scroll e2e test now focuses a non-typing element before pressing PageDown (the scroll handler intentionally ignores scroll keys while an input is focused) and polls for the final scroll position instead of a single fixed timeout, fixing a false failure (`tests/dashboard-overlay-focus.spec.js`). - **fix** **Inline-edit save test** — the "save commits inline edit changes" e2e test restored the original name with the wrong save-API shape (page in the body instead of the `?page=` query, and a single bookmark instead of the full page array), which returned 400 and then awaited a refresh that never resolved, timing the test out. The cleanup now GETs the page array, patches the name, and POSTs it back (`tests/dashboard-inline-edit.spec.js`). - **fix** **PWA install handlers** — documented that the `beforeinstallprompt` `preventDefault()` call suppresses Chrome's default banner in favour of the app's own install UI, so Chrome's "Banner not shown" console message is expected (`pwa-install-hint.js`, `config/config-pwa-install.js`). - **fix** **What's new modal** — **v2026.07.11.4** JSON entry with *Dialogs* and *Browser & PWA* sections covering the dialog focus, opening-focus, form-submit, and PWA meta-tag fixes (user-facing wording only). - **fix** **Cache-bust** — `whats-new-v153` data version (`asset_versions.go`, `whats-new-stub.js`), `2026.07-dashboard-release-v112` dashboard release token, and a `modal-focus-aria-1` query string on `modal.js` so the modal fixes are refetched. --- ## v2026.07.11.3 — July 2026 **Bulk tags** — the config bookmarks bulk toolbar can now add, replace, or remove tags across every selected bookmark at once. ### Bookmarks - **new** **Bulk tags** — select bookmarks in *Config → Bookmarks* and the bulk toolbar gains a *Tags* group: a comma-separated tag input (with `TagAutocomplete` seeded from all loaded bookmarks) and an Add/Replace/Remove mode select. `bulkApplyTags(bookmarks, tags, mode)` normalizes to lower-case, trims, and dedupes, then mutates the selected bookmarks in place and clears the selection, saving through the existing config dirty/save flow like the other bulk actions (`config-bookmarks.js`, `config-setup.js`, `templates/config.html`, locales). The three new controls are disabled when nothing is selected. ### Developer & docs - **fix** **README, MANUAL, CHANGELOG & Config Help** — **v2026.07.11.3** notes. - **fix** **What's new modal** — **v2026.07.11.3** JSON entry (no doc-update item, by design). - **fix** **Cache-bust** — `whats-new-v150` data version and `2026.07-dashboard-release-v111` dashboard release token; `bookmarks-bulk-tags-1` asset query strings on `config-bookmarks.js` and `config-setup.js`. --- ## v2026.07.11.2 — July 2026 **Tags within reach & smarter collection rules** — the Tags field moves above the fold in the bookmark forms, the dashboard inline editor is reordered to match, and building a custom collection now autocompletes rule values. ### Bookmarks - **new** **Tags above the fold** — in the quick-add modal (`&`) the Tags field moves out of `More options` to a dedicated section right under the Page/Category row (`nbm-wizard-step-2-panel`); in the config bookmark form it moves out of `More options` to sit directly below Category. The `More options` hint no longer lists "tags" (EN/NL/DE/FR). Tags label/placeholder in the modal are now localized via `config.detailTagsLabel` + a new `config.commaSeparatedShort` key (`search-commands-new.js`, `templates/config.html`, locales). - **fix** **Inline editor field order** — the dashboard inline bookmark editor now appends fields in a fixed order (Shortcut → Page → Category → Tags → Note, above the Pinned/Status checks) instead of the previous scattered order; field definitions and their listeners are unchanged (`dashboard-inline-edit.js`). ### Collections - **new** **Autocomplete on rule values** — the custom-collection rule editor reuses `TagAutocomplete` on each rule's value field, suggesting the tags, categories, or shortcuts already in use (field-aware). A new single-value mode (`{ single: true }`) replaces the value on accept with no trailing comma; suggestions keep their original casing so shortcuts show as `G`, `GI` (`tag-autocomplete.js`, `config-collections.js`). Fixed the `+ Add collection` button passing the wrong manager to the editor, which left the suggestion pool empty (`config-setup.js`). Config → Help *Tags & collections* now mentions rule-value autocomplete (EN/NL/DE/FR). ### Polish - **fix** **Back/Forward cache** — the dashboard and config HTML responses dropped `no-store` (kept `no-cache, must-revalidate`), so the browser bfcache works again and Back/Forward navigation stays instant while clients still pick up the latest `?v=` asset URLs (`handlers.go`). ### Developer & docs - **fix** **README, MANUAL, CHANGELOG & Config Help** — **v2026.07.11.2** notes. - **fix** **What's new modal** — **v2026.07.11.2** JSON entry (no doc-update item, by design). - **fix** **Regression coverage** — the collection autocomplete e2e test now drives the real `#add-collection-btn` so it guards the wrong-manager fix (`tests/config-collections-autocomplete.spec.js`). - **fix** **Cache-bust** — `whats-new-v149` data version and `2026.07-dashboard-release-v110` dashboard release token; `search-commands-new-3-tags-above-fold`, `collections-ac-1/2`, and `inline-edit-field-order-1` asset query strings. --- ## v2026.07.11 — July 2026 **Clearer General settings** — the busiest General config sections are split into small labelled sub-groups so related options sit together and the page is easier to scan. ### Config → General - **new** **Labelled sub-groups** — a new `.general-card-group` / `.general-card-group-label` pattern (a dimmed accent-dashed `— group` opener, one level below the `//` section heading, in the existing terminal aesthetic) splits the busiest Essentials sections into scannable groups: Localization → *language* / *date & time*; Appearance & Style → *theme* / *text* / *extras*; Layout → *grid* / *spacing* / *extras*. Same settings, same tabs — nothing moved; the tier switcher and quick-links are unchanged. Seven new group-label i18n keys across EN/NL/DE/FR (`templates/config.html`, `config-forms.css`, locales). - **fix** **Config tours default off for Stats/Pages/Tags/Theme** — these four config tab tours no longer auto-start on first visit; an `autoStart: false` flag plus an `isAutoStartEnabled` gate in `scheduleManualTour`/`maybeStart` blocks the auto path while leaving `force` triggers (the existing Reset/Start buttons in Config → General → Tours & onboarding) working. General/Bookmarks/Finders/Categories/Collections are unchanged (`config-tab-tours.js`). ### Accessibility & polish - **fix** **Spinner accessible names** — the six config number-input spinners (tag-collections min count, offline retries, retry delay) were bare `▲`/`▼` buttons with no accessible name; added generic `increaseValueAria` / `decreaseValueAria` i18n keys (EN/NL/DE/FR) wired via `data-i18n-aria` (`templates/config.html`, locales). - **fix** **Health skip link** — the health page gained a keyboard skip-to-content link targeting `#health-main`, matching dashboard/config, with the `.skip-to-content` style added to `health.css` (health doesn't load `dashboard-enhancements.css`). - **fix** **Lazy category icons** — uploaded category-header icons now set `loading="lazy"`, consistent with bookmark-row favicons (`dashboard-render-core.js`). - **fix** **No-JS fallback** — the dashboard clears its skeleton only from JS, so with JavaScript disabled it shimmered forever; a `