github jordibrouwer/nextdash v1.17.5

4 hours ago

Config → Overview names the running version in a panel of its own, with a dot that says whether it is the newest release. The update check uses the Containers GitHub token, waits out GitHub's hourly limit and says why it failed. v1.17.5 leads the What's new window, and the five releases held back before it (v1.17.4, v1.17.3, v1.17.1, v1.15.4 and v1.15.1) now show under it.

Config

  • new — a Version panel on the overview. It sits between Latest news and New in nextDash and reads You're running v1.x.y of nextDash, with links to the full changelog and the manual on GitHub, each opening in a new window. The text has the same size as the other panels. The panel appears once the update check knows the running version, also when the site's news is switched off (renderOverviewVersionWidget in dashboard-config.js, config-view.css).
  • new — green or red for the running version. The dot before the panel title is green on the newest release and red when a newer one is out, also after the update notice was dismissed; no dot when GitHub was not asked or could not be reached. When behind, a second line in red says which release is available, its tag a link to the release on GitHub.
  • fix — the "Running vX" note under New in nextDash is gone; the Version panel says it instead.
  • fix — the section rail no longer slides under the section band. Once a long section was scrolled, the sticky band (title, description, Only changed, the settings filter) covered the rail's heading and half of Overview. The rail kept a flat top: 8px from before config had a sticky band; it now sticks at the band's height plus 8px. The band's height is published as --lvs-header-height on .config-view and re-measured when its description wraps (trackShellHeaderHeight in dashboard-config.js, config-view.css).
  • new — choose the pages Fresh shows on. Config → Structure → Collections → Collection scope has a “Fresh” pages row beside Today, Recent, Stale and Most used. The dashboard already read smartFreshPageIds, but Settings had no such field, so the save dropped it and Fresh stayed on every page. The field is now in Settings, both defaults blocks and the missing-key handling in GetSettings (models.go), and in the client defaults and load normalisation (dashboard.js, dashboard-data.js, COLLECTION_SCOPES in dashboard-config.js).
  • fix — the MCP panel names a script or another tool. Data & backups → Webhooks called it Assistant access. It is now MCP access, for a script or another tool, and the toggle reads Answer MCP clients at this address (dashboard-config.js, overview-features.json, the v1.4.0 note in What's new, MANUAL.md §23.6).
  • fix — Data & backups opens with a line that fits every tab. The band above the tabs read Back up your data, restore an earlier snapshot, or move it in and out of nextDash. on all six tabs, though only Backups & data does that. It now reads Keep your data safe, move it in and out, and manage what nextDash stores on this disk. (config.dataBackupsIntro, in all six languages).
  • fix — the line under a tab strip follows the open tab. In Data & backups, Bookmarks and Help, switching tabs repainted only the body, so the note under the strip kept describing the tab the section opened on. A shared syncSectionTabNote now swaps, adds or drops the note on every tab switch, as Stats already did (dashboard-config.js).

Update check

  • fix — the check no longer runs into GitHub's hourly limit as often. Without a token GitHub allows 60 requests an hour per public address, shared with the container changelogs, other tools on the network and, behind CGNAT, the neighbours; past it the check failed with "Could not reach GitHub". It now sends the GitHub token from Config → Containers → Updates when one is set (5000 an hour), and asks the release listing with If-None-Match, so an unchanged answer comes back as a 304 that does not count against the limit. A token GitHub refuses is dropped for that request instead of failing the check (update_check.go).
  • fix — on GitHub's limit the check waits for the reset. It reads X-RateLimit-Reset and tries again then, instead of every 15 minutes; Check now and the /releases/latest fallback no longer spend a request to hear the same answer. When nextDash's own outbound limiter turned the request down, it tries again after a minute.
  • new — a failed check says why. /api/update-status adds errorCode (rate-limited, local-limit, unreachable, http), retryAt and authenticated. The Version panel and the What's new bar name the reason: the hourly limit with the time of the next try and, without a token, where to set one; GitHub out of reach; or GitHub's own answer (update-notice.js, dashboard-config.js).

Widgets

  • new — choose a widget's page in its settings. Config → Widgets → Settings has a Page select above Width when there is more than one page. Choosing another page moves the widget there straight away, at the end of that page, with its id, credential and collapsed state; unsaved changes in the panel ask first. It uses the bulk bar's move (moveWidgetsToPage now takes the ids, moveOneWidgetToPage and renderWidgetPage in dashboard-config.js).
  • fix — the Custom widget counts the services it offers. Config → Widgets → Types said 45 services in four groups: PRESETS.length counted the three retired presets (Readarr, Pi-hole v5, TrueNAS) and qBittorrent's two entries. It now says 41 services in five groups. qbittorrent-key carries variantOf: 'qbittorrent', and a new serviceCount() in dashboard-widget-presets.js leaves out retired presets and variants.
  • fix — the widgets tour's preset step said twenty-eight services. It now says forty-one, names monitoring beside the other kinds, and its chips show Uptime Kuma instead of the retired TrueNAS, with "…and twenty-two more" after them (widgets-tutorial.js).

Dashboard

  • fix — with less motion, the pages and recents panels stay on the strip. When the system asks for reduced motion, or Animations is off, the reduced-motion rule for every modal and the app-wide no-animations rule cleared transform, and with it the translateX(-50%) that centres a header sheet on the strip: the pages panel (,) ran off the right edge of the window and the recents panel (*) sat half its width to the right. The header sheets are left out of those rules and keep their centring; they still open without animation (modal.css, dashboard.css).
  • fix — unticking a notes box right after ticking it is saved. Ticking saves the line but does not redraw the tile, and the box kept the line as it was drawn; a second click on the same box found no such line, redrew the tile and lost the click, so the box jumped back. After a save the box now holds the line as saved (onTask in dashboard-widget-notes.js).
  • fix — Re-check on the selection bar counts what each check answered. Every ticked row was counted as re-checked, also when the dashboard's own ping limit (429) or the network refused it, and a refused row was never asked again. recheckIssue now answers ok, skipped, failed or a rate limit with its Retry-After; the dashboard's bar and the Bookmarks view's bulk Re-check pass it to BulkSweep, which waits out the limit and asks once more (dashboard-health.js, dashboard-multi-select.js, dashboard-health-multi-select.js).
  • fix — a tablet shows the time once. With a touch screen wider than a phone, the header drew the clock and, under it, the mini status line repeating the same time before the page name and bookmark count; a 768px window did the same. The mini status no longer copies the clock and keeps the page name and the count (updateMiniStatusLine in dashboard-toolbar.js).
  • fix — the pages panel opened a second time puts the cursor on your page again. Closed with Escape and opened again, it came up with the focus on nothing, so the arrow keys and Enter did not reach the list. AppModal focuses a dialog's chosen element two frames after it opens, once; reopened straight after closing, the overlay is still visibility: hidden at that moment and focus() does nothing. The chosen element now gets the same few tries across the fade as the fallback already had (_focusInitialElement in modal.js), which covers every dialog that names one.
  • fix — a setting you change while the dashboard refreshes stays changed. When another device saves settings, the dashboard reads them again. Changing one here while that read was still on the wire let its answer, taken before your save, replace the settings on screen: the header went back to its old style while the server held the new one, and stayed that way until a reload, because your save had already told the poll there was nothing left to fetch. loadData now looks at when this tab's last settings write left: sent after the read, it reached the server after whatever the read saw and carries the whole object, so the settings on screen are kept; already on its way when the read left, the order is unknown, so it waits for the write and reads again; otherwise the answer is applied (saveSettings and loadData in dashboard-data.js). A first try counted any save still running as crossing the read, and backlog-batch-three.spec.js caught it in CI: a save that had already landed before the other device's change kept that change off the screen.
  • fix — a spread category keeps its names as wide as a plain one. The gap between spread columns fell between every track of the repeated row pattern, so the name track lost about two seams per column and Weather radar came out Weather r…. Each row in a spread list now lays out its own tracks inside one track per column (dashboard.css, dashboard-category-span.js).
  • fix — a Notes widget you removed stays removed. The one-time step that puts a Notes widget on the first page recorded itself in a marker that Settings had no field for, so the next settings save dropped it and the widget came back after a restart. NotesWidgetSeeded is now a field and survives a save like the other markers (models.go).

Server

  • fix — Retry on a stopped feed fetches that feed only. It reset the feed and then polled every feed on the install while the request waited, up to a minute; a limited round now takes only the reset feeds and leaves the scheduled round's time alone (pollFeeds and RetryFeed in feeds.go).
  • fix — page template imports run one at a time. A new page's id was read before it was written, and an empty page checked before it was filled, so two imports at once (two tabs) took the same id or filled the same page and the second overwrote the first. The import now holds a lock from those checks to its last write (ImportPageTemplate in page_template.go).
  • fix — template labels are cut by character. A host label over 60 bytes was cut mid-character, which showed as � in the file and the import dialog; it is now cut at 60 characters (truncateRunes).
  • fix — /api/notify/quiet loads the time zone once. Working out when the quiet hours end read the zone file once per minute stepped, up to 2880 times a request (quietEndsAt in notify_quiet.go).

Bookmarks

  • fix — Unsorted is called Unsorted, not 999999. In Bookmarks → Unsorted grouped by page, the group header read 999999 and so did the location line in the side panel. Kept links live on a hidden page that is not in the page list, and pageLabel fell back to its id. It now returns Unsorted (config.bmViewUnsorted) for that page, which also fixes the row crumb, the Usage tab and the bulk category list for kept links (dashboard-config.js).

First start

  • new — a new install asks what you run. A card at the top of the first page, before the quick-start checklist, offers three bundled templates — Homelab (Proxmox, a NAS, Pi-hole, Home Assistant, Portainer, Uptime Kuma, Nginx Proxy Manager, the router), Media server (Jellyfin, Jellyseerr, Sonarr, Radarr, Lidarr, Bazarr, Prowlarr, qBittorrent) and Developer (Gitea, Woodpecker CI, a container registry) — or Keep these links. One server address fills in every service with its usual port; More lists them to change one, and a scheme or port typed in the address wins. While main is still the untouched seed the template replaces it, otherwise it comes as a new page; the line under the button says which. The answer is kept in quickStart.templatePicked, and Show quick-start card again clears it (first-start-templates.js, dashboard-quickstart.js, dashboard-quickstart.css; bundled_templates.go with the three files under internal/app/bundled_templates/, GET /api/page-templates/bundled, GET /api/page-templates/bundled/{id}, POST /api/onboarding/template).
  • new — after a template, the first steps use your own services. The quick-start checklist's first task becomes opening one of them by its shortcut (Open Jellyfin from the dashboard — type j), and the dashboard tour's search and shortcut steps name it as their example (templateService in dashboard-quickstart.js, exampleBookmark in dashboard-tutorial.js).
  • new — the template import dialog offers the three as well. Or start from: under Import a page… loads Homelab, Media server or Developer, and for a template whose addresses follow {server}, Where do these run? fills them all from one address; a field you change by hand stops following it (dashboard-config.js).

Inbox

  • fix — the inbox keeps every link. It held 500 by default (inboxMaxItems, a setting only the settings file had), and past that a new link from the extension, a share, the bookmarklet or an undo pushed the oldest one out without a word. An import stopped at the cap and said inbox full. The cap is gone: every way in adds the link and drops nothing, and an import adds every row that is not a duplicate. inboxMaxItems is removed from Settings, its defaults and the missing-key handling (models.go, inbox_handlers.go, share_capture.go, importInbox in dashboard-inbox.js, device-settings-merge.js).

Tests

  • tests — update_check_test.go covers the rate-limit wait, the conditional request and the token with its fallback; tests/config-overview-release.spec.js reads the version from the Version panel and covers the behind line and the failure reason.
  • tests — tests/config-widgets-tab.spec.js moves a widget through its Settings page select and checks it left the source page and landed, same id, on the other.
  • tests — tests/config-widgets-tabs.spec.js checks the Custom section's count against the offered presets, one per service name, and that it says five groups.
  • tests — tests/header-sheet-reduced-motion.spec.js opens the pages and recents panels with their keys under reduced motion and with Animations off, and checks that each sits inside the window, on the strip's centre line, without an animation.
  • tests — tests/unsorted-page-label.spec.js keeps a link from the inbox, opens #unsorted, groups by page and checks that the group header and the side panel's location say Unsorted.
  • tests — tests/config-rail-sticky.spec.js opens Config → Behavior from the dashboard, scrolls it at 1440 and 800px wide, and checks that the rail starts below the band.
  • tests — tests/header-one-clock.spec.js counts the visible clocks at 820×1180 with a coarse pointer and at 1440×900 (one each) and at 390×844 (at most one).
  • tests — settings_merge_test.go saves smartFreshPageIds through the store and reads it back, and loads an old settings file as an empty list; tests/config-collection-scope.spec.js ticks a Fresh page in Collection scope, reloads, and finds it still ticked.
  • tests — tests/dashboard-widget-notes.spec.js ticks a box and unticks it with two plain clicks, and checks both saves.
  • tests — tests/bulk-actions-parity.spec.js answers one re-check with a 429 and one with a 502, and checks the first is asked again and the summary says one.
  • tests — feeds_retry_test.go retries one of two feeds and checks only that one is fetched and LastPoll stays.
  • tests — page_template_test.go cuts a long label in another script and expects whole characters.
  • tests — page_template_test.go runs four imports at once and expects four pages.
  • tests — tests/page-overview-panel.spec.js (no filter with a few pages, a filter with many) failed on every run, in CI and alone: it reopens the panel and expects the cursor on the current page. It passes again with the modal.js fix and fails without it.
  • tests — tests/inbox-mark-read-failure.spec.js failed now and then in CI with a ten-second wait for its probe row. Its POST went to the server while the dashboard's own inbox read was still on the wire; opening the view joined that read (fetchItems keeps one in flight) and never asked again. A first try waited for a read in flight before the POST, and CI failed it again: the dashboard reads the inbox on its own while the page settles, so a read could leave between that wait and the POST. The spec now reads the list itself after the POST, before the view opens.
  • tests — tests/header-button-style.spec.js (on a glass theme, plain controls stand on the band) failed three times in one CI run and never locally. Its chooseStyle POSTed the settings by hand and slept 300ms; the dashboard, still settling from the reload before it, had its own save and a revision check on the wire, and the header kept the old style. It now saves through the dashboard's own saveSettings, waits for the header to carry the new style, and polls for the glass.
  • tests — tests/config-help-health.spec.js expected the inbox's 500 cap in Help; it now checks that Help says the inbox has no limit and no longer mentions dropping links.
  • tests — tests/config-bookmarks-unsorted-view.spec.js (Delete on a selection in the Unsorted view) timed out once in CI on a checkbox that stayed hidden: the tick shows on hover, and a repaint after the search drew the row anew away from the pointer. It hovers again until the tick takes.
  • tests — tests/settings-refresh-race.spec.js holds the settings read of a refresh, changes and saves the header style meanwhile, then lets the old answer land, and expects the new style in the settings and on the header. It fails without the loadData change. A second test lets this tab's save land, holds its answer, has another device save after it, and expects the screen to match the server; it fails with the first try.
  • tests — tests/first-start-templates.spec.js answers the card with each choice and checks what lands on the page; bundled_templates_test.go covers the three files, the address expansion and replace-or-add; notes_marker_test.go saves settings and finds the notes marker still set. tests/fixtures.js answers the card as Keep these links for every other spec, so the grid starts where it did.
  • tests — inbox_limits_test.go adds a link to a full inbox and an undo, and checks that nothing older is dropped (TestAddInboxItemNeverDropsAnOlderLink, TestUndoPushesNothingOutAndDropsADeadIcon); inbox_capacity_test.go follows; tests/inbox-view-fixes.spec.js imports into an inbox that already holds links and checks every row is added and the old links stay.
  • tests — tests/config-tab-note-follows-tab.spec.js switches tabs in Data & backups, Bookmarks and Help and checks the note under the strip each time.
  • tests — tests/dashboard-spread-name-width.spec.js compares a name's width in a spread category with the same category in one column; tests/dashboard-category-width.spec.js follows the new track layout.

Docs

  • docs — MCP copy in all six languages: mcpTitle, mcpSummary, mcpNote, mcpEnabledLabel, mcpAddressLabel, overviewNewFeatureWebhooksHow and overviewNewFeatureWebhooksEnable name a script or another tool.
  • docs — locale keys overviewVersionLine, overviewVersionHere and overviewVersionTitle in all six languages. The behind line reuses the translated updateCheckModalAvailable. The six update-check reasons (updateCheckRateLimited, updateCheckRateLimitedAt, updateCheckTokenHint, updateCheckLocalLimit, updateCheckUnreachable, updateCheckFailedWith) are in all six languages too. go run scripts/gen-asset-hashes.go refreshed asset_hashes_gen.go.
  • docs — locale keys widgetPageNote, widgetMoved, widgetMoveDiscardBody and widgetMoveDiscardOk in all six languages; the label reuses the translated widgetsPageLabel.
  • docs — preset counts in all six languages: widgetCustomRefPresetsBody says five groups, and widgetsTutorialStep5Title, widgetsTutorialStep5Body1 and widgetsTutorialPresetsMore give the new numbers and name monitoring.
  • docs — Config → Help in all six languages: helpConfigBody names the Version panel on the overview and that the Containers GitHub token serves the update check too; helpContainersConfigBody says the same under the token; helpWidgetAddingBody names the Page select in a widget's settings; helpVersionBody points to the Version panel and its dot.
  • docs — README and MANUAL catch up. The README's links into the manual carried the section numbers from before the manual was renumbered (§13.4 for Collection health, §11.5 for the Custom widget, and eleven more); they now name the sections they open. The alert list on top names Apprise, and the Unraid widgets list names the overview. MANUAL §15.2 names the Page select in a widget's settings.
  • docs — the inbox's limit is gone from Config → Help → Inbox (helpInboxSettingsBody, all six languages): the line listing inboxMaxItems among the settings-file-only options, and the paragraph on undo at the cap, where the oldest link made way. MANUAL §13.1 says the inbox has no limit.
  • docs — the first-start card in Help and the manual. Config → Help → Getting started (helpStartBody) has a paragraph on What do you run?, and Structure & bookmarks (helpWorkspaceBody) names the three bundled templates in the import dialog, in all six languages. MANUAL §2 First launch opens with the card and says how the quick-start and the tour change after a template; §9.8 names the three in the import dialog. The card's text, Or start from: and Where do these run? in the import dialog, the two tour lines and the checklist's service task had no locale keys and showed in English in every language; the new firstStart group, config.pageTemplateServer, config.pageTemplateStartFrom, dashboard.dashTourS2Try, dashboard.dashTourS3Try, quickstart.itemOpenService and quickstart.itemOpenServiceHint are in all six languages.
  • docs — static/data/whats-new/v1.17.5.json and its index entry. hideFromModal is gone from v1.17.4, v1.17.3, v1.17.1, v1.15.4 and v1.15.1, so the modal lists every release. whats-new-stub.js: DASHBOARD_RELEASE moved to 2026.10-dashboard-release-v1.17.5, so the window opens once more, and NEXTDASH_WHATS_NEW_DATA_VERSION to whats-new-v321; tests/whats-new-hidden-release.spec.js follows both and expects no held-back release.
  • docs — a spotlight for the Version panel in overview-features.json with since: "v1.17.5", so it shows in the overview's news and under About → News & features; its five overviewNewFeatureVersionPanel* keys are in all six languages.
  • new — the manual is easier to find your way in. Contents with start-here routes and every subsection, a glossary of 100 key terms linked into the text, "in short" notes per chapter, three diagrams and 94 screenshots beside the text they show, element crops and full pages, many folded away, the Custom widget section in full with all 42 presets, and the manual caught up with features up to v1.17.5.

Don't miss a new nextdash release

NewReleases is sending notifications on new releases.