CHANGELOG.md
Rama main · réplica de lectura del repositorio original.
# Changelog
Notable user-visible changes to NasDash will be recorded here.
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and published versions will follow [Semantic Versioning](https://semver.org/).
## [Unreleased]
## [0.3.8] - 2026-11-08
### Upgrading from 0.3.7
- Pull and recreate NasDash with the same data mount; nothing to migrate. Roll back by recreating the recorded `0.3.7` image.
- Viewers limited to chosen widgets do not see the new ones until you add them in **Settings → Users and access**; viewers without a limit see them on the pages they can open.
- Updating containers from the Container updates widget needs a What's Up Docker account with the `rw` role and a Docker or Docker Compose trigger in WUD; with a read-only account the widget only lists updates.
### Added
- **Syncthing** widget: whether each folder is up to date, how far a sync has gone and what is left, folders in error, the connected devices and the transfer rate. Full or compact, every folder or only the active ones, folders of your choice hidden. Read only, with Syncthing's API key.
- **Internet speed** widget (Speedtest Tracker): the latest download, upload, ping and jitter, the curve of the recent speeds or pings and, for administrators, a button that starts a test. Full or compact, Mbit/s or MB/s, and the share of your subscription's speed the latest test reached. Needs an API token that reads results (and runs tests, for the button).
- **Container updates** widget (What's Up Docker): which containers have a newer image, from the current version to the new one, major jumps first, with app icons and the release notes when the registry gives them; how many rows show is set with a slider, the others one click away. Administrators update one container or all of them from the widget, through WUD's Docker or Docker Compose trigger, after a confirmation that warns about major versions (it can be turned off). Needs a WUD account with the `rw` role when WUD has authentication.
- **Notes**: a short note written in place by an administrator, with headings, lists, bold and links. **To-do**: a short list ticked, added to and cleared in place. **Countdown**: the days left until a date, or a timer that rings in the browser, with three durations at hand, any other typed on the spot, durations kept or removed in edit mode, and three looks (standard, large, and animated: a little tomato walking to its flag, still when paused). **Web page**: another site inside the dashboard, sandboxed, from 160 to 4,000 pixels high; it loads once on screen, stays loaded five minutes after its page is left, then is unloaded (sites that refuse to be framed stay blank, and an http page cannot show inside an https dashboard).
- The three new connections have their own sections in **Settings → Integrations** and their place in the first-start guide; the public demo shows every new widget with fictional data.
- For contributors, the **integration kit**: one data route, one widget shell and one list of families shared by service integrations, `npm run new:integration` to write a new one, and `scripts/i18n-add.mjs` to add interface texts to the five languages at once (`src/integrations/README.md`).
## [0.3.7] - 2026-10-29
### Upgrading from 0.3.6
- Pull and recreate NasDash with the same data mount; nothing to migrate. Roll back by recreating the recorded `0.3.6` image.
- If you use an uploaded wallpaper, it now shows on the sign-in screen, so anyone who can open that page can see this one image. Choose a bundled wallpaper, or none, to keep it behind sign-in.
### Changed
- The sign-in screen looks like the dashboard behind it: its theme, and its wallpaper, an uploaded one included (served alone by `/api/setup/wallpaper`, every other upload stays behind sign-in), or the theme's background when it has none.
- While the dashboard loads, the wallpaper of the last visit shows instead of the theme's background.
## [0.3.6] - 2026-10-29
### Upgrading from 0.3.5
- Pull and recreate NasDash with the same data mount; nothing to migrate. Existing installations keep their settings, security mode, accounts and pages, and do not enter the first-run guide. Roll back by recreating the recorded `0.3.5` image.
- Only new installations start private, ask for the setup code printed once in the container logs, and open the guide.
### Added
- First start: a new installation opens on a sign-in screen asking for the **setup code** the container prints once (`Setup code: XXXX-XXXX-XXXX`), then a five-step guide: your administrator password, language and look (light or dark, wallpaper), integrations, the widgets of Home, and access (private or open to read). The guide can be skipped once the password is set; `NASDASH_ADMIN_PASSWORD` still sets the first password instead of the code.
- Five wallpapers drawn for NasDash in its colours (aurora, dusk, mist, waves and a light dawn), generated by `scripts/generate-wallpapers.mjs` under the project's licence, offered in the guide and in **Settings → Appearance → Wallpaper**. The sign-in screen shows the chosen one when it is a provided wallpaper, else the default one: an uploaded image is never shown before signing in.
- A short tour of the dashboard after the guide: the page darkens, one button stays lit, and a bubble explains pages, widgets, edit mode, adding a widget, settings and hiding sensitive information. Skippable from every bubble, replayable from **Settings → Help**.
- **Settings → Appearance → Wallpaper veil** darkens the wallpaper (lightens it in light mode) so widgets stand out. With a background blur, surfaces now get light translucent hairlines and keep the wallpaper's colours, like the sign-in card.
- Empty pages: administrators get a dashed slot where the first widget will go; it enters edit mode and opens the widget library.
- Public demo: one page per theme (Home, Services, Machines, Docker, Network, Media, Downloads, Music, Feeds) showing every widget type, on the aurora wallpaper with the glass appearance, widget titles shown. Its welcome now uses NasDash's own glass and buttons, says what is safe to try, and offers the dashboard tour or free exploration.
### Changed
- New installations start private, without sample devices, services or Docker host, on one Home page holding a clock and the weather, with a wallpaper, its veil, surface blur, transparent cards and the Lucide icon set. Existing installations keep their settings, mode and pages.
- The sign-in screen and the guide use the dashboard's own fonts, buttons, fields, settings layout, widget-library cards and glass (read from Appearance), so arriving on the dashboard does not change the look.
- No `viewer` account is created on a new installation: it is created when public mode is chosen (in the guide or in Settings), since its permissions are what anonymous visitors see. Existing viewer accounts are unchanged.
- The sign-in screen is redrawn: the wallpaper, the logo and name, the time, one card, and the documented recovery command behind **Forgot it?**.
### Removed
- The **Getting started** checklist on Home, replaced by the first-run guide and the tour.
### Fixed
- The container list shows exactly the number of rows chosen in its settings; the next container no longer peeks out at the bottom.
- In edit mode, Network tools no longer shows a second title above its own; its refresh button joins the widget's controls.
- The network map's edit tools sit above the map instead of covering its top.
- Several Gluetun, NUT and apcupsd connections can be saved; adding one no longer replaces the previous one.
## [0.3.5] - 2026-10-28
### Upgrading from 0.3.4
- Pull and recreate NasDash with the same data mount; nothing to migrate. Roll back by recreating the recorded `0.3.4` image.
- A Proxmox node that **Test and list the machines** added a second time can be removed from the device list; it is no longer offered again.
### Fixed
- Proxmox: **Test and list the machines** no longer offers, and adds a second time, a node already added from the device editor (#142). A denied metrics request now also says where Proxmox grants the API token its own permission.
## [0.3.4] - 2026-10-28
### Upgrading from 0.3.3
- Back up the data directory, then pull and recreate NasDash with the same data mount. No data migration is required; accounts, integrations and saved pages are preserved.
- The new VPN and UPS widgets need a connection under **Settings → Integrations** (VPN tunnel, UPS). Gluetun's control server must be published with an API key whose role reads the VPN status, public IP and port forwarding; a NUT or apcupsd server must allow NasDash's address. See the documentation pages *Gluetun (VPN)* and *UPS (NUT, apcupsd)*.
- Recreating a Gluetun container leaves the containers that use its network without network until they are recreated too; the VPN widget now names them.
- Rolling back to the recorded `0.3.3` image preserves the data format; saved VPN and UPS connections and widgets are then ignored.
### Added
- VPN widget for Gluetun: whether the tunnel holds, the city and country where traffic leaves it, the public address, the exit network and the forwarded port; administrators can restart the tunnel after a confirmation. Connect Gluetun's control server under **Settings → Integrations → VPN tunnel** with an API key, a username and password, or no authentication. NasDash only reads the VPN status, public IP and port forwarding routes, never Gluetun's settings route, which contains private keys. The address and the port can be hidden per widget; viewers need the VPN widget permission. It lists the containers that go through Gluetun (`network_mode: service:gluetun`), read from the saved Docker hosts for viewers who may read containers, and names those left without network after Gluetun was recreated, until they are recreated too. When Gluetun could not look up the exit address again after a restart, the tunnel shows as connected with the address said to be unknown.
- UPS widget, for units read through Network UPS Tools (Synology, QNAP, TrueNAS, Unraid, Proxmox, Linux or a NUT container; thousands of USB models, including those without any display) or apcupsd: on mains or on battery, battery charge and runtime, load in watts, line voltage, the estimated time before the automatic shutdown (from the server's thresholds), time on battery, the last switch to battery, and plain warnings for a battery to replace, an overload or a lost UPS. Connect it under **Settings → Integrations → UPS** with the server's address; reading is read-only and needs no account. A NUT server with several UPS lets each widget choose one. It has a full or a compact style; each part can be hidden (battery bar, runtime, automatic shutdown, load, line voltage, power events); optional details show output and battery voltage, line frequency and temperature. Both widgets stay readable at their narrowest width. An implausible UPS output voltage (some CyberPower units report a raw register through NUT) is left out.
### Changed
- The weather widget's rain falls as separate drops on two depths instead of a sliding stripe pattern, and follows how hard it rains: drizzle and light showers, steady rain, downpours and storms.
### Fixed
- Downloads: a paused download no longer drops out of the widget behind seeding torrents, so it can be resumed from the Downloads widget and the queue keeps showing its real state.
- Downloads: after **Pause all**, the button offers **Resume all** for every torrent client. qBittorrent 5.2+ pauses its session (each torrent keeps its state); Transmission and Deluge stop each torrent; torrents already stopped are started again by **Resume all**. Per-item buttons are hidden while a whole SABnzbd or NZBGet queue is paused, since they could not resume it.
- qBittorrent 5.2+ with a username and password connects again (new login answer and session cookie name).
- LibreHardwareMonitor: Intel integrated graphics now appear (usage of the busiest engine, such as video decoding while a media server transcodes, and temperature when reported). Glances: Intel graphics named after their chip are recognised as integrated graphics.
- Info bubbles (ⓘ) no longer stay on screen after the pointer has left: a focus left by a click, coming back with the window, no longer reopens them, and scrolling under a still pointer or tapping elsewhere closes them. The keyboard still opens them; Escape closes them.
- Music activity: in covers mode, played tracks are shown as covers like the albums, and the display choice is offered for every content.
- Now playing: the search button sits in the card's corner and the first line of text keeps clear of it on narrow widgets and phones.
- Weather settings: a city search that finds nothing now says so (in the demo, which cities it offers) instead of showing an empty list.
## [0.3.3] - 2026-10-27
### Upgrading from 0.3.2
- Back up the data directory, then pull and recreate NasDash with the same data mount. No data migration is required; accounts, integrations and saved pages are preserved.
- A Proxmox HTTP 403 still requires the appropriate read permissions on the Proxmox user and API token. Use **Test metrics** on the selected machine to check them.
- Rolling back to the recorded `0.3.2` image preserves the data format but restores the older dependencies, including the security advisories fixed below.
### Security
- Update Next.js to 16.4.3 to address the image optimization, Server Actions and cache advisories (GHSA-2464-fhr4-w9xw, GHSA-p3m5-59mp-jv5r, GHSA-673q-mjm6-r5xr). Update the vulnerable transitive Zod dependency to 4.6.7; production and development dependency audits pass.
### Fixed
- Proxmox devices can test the selected node or VM/LXC metrics directly, independently of machine discovery. A denied metrics request now explains the required `Sys.Audit` or `VM.Audit` permission and the API token's separate permissions (#142). Storage access remains optional; granting remote permissions is still an operator action.
## [0.3.2] - 2026-10-22
### Upgrading from 0.3.1
- Pull and recreate NasDash with the same data mount; nothing to migrate. Roll back by recreating the recorded `0.3.1` image.
### Fixed
- Much less CPU in the browser on pages with media widgets: poster loading sweeps no longer run forever on posters out of view (a page of media widgets went from about 14 % of a CPU core to under 1 % at rest, measured). Loading sweeps, rain, snow and the status pulse now animate with `transform`/opacity only, which the GPU handles without repainting.
## [0.3.1] - 2026-10-22
### Upgrading from 0.3.0
- Back up the data directory, then pull and recreate NasDash with the same data mount; no data migration. Saved pages, widgets and settings are kept; the new **Below** choice of Recently added starts as a row, as before.
- To roll back, recreate the recorded `0.3.0` image with the same data mount; it ignores the new setting.
### Added
- Widget library: pick several widgets, then add them together; they are placed one after the other without overlapping.
- Header menu in edit mode: drag pages into order, rename a page in place (pencil on hover, or a double click) and create a new page with the **+** at the end, without opening settings.
- **Recently added** in the featured display: the titles below scroll with arrows when there are more than fit, or show as a grid (**Below**: row or grid).
### Changed
- **Coming soon** is marked **experimental** in the widget library: its sources and matching are still being refined.
### Fixed
- **Recently added**: the featured display showed only the titles that fit (the row could not be scrolled with a mouse); the featured title counts as one of the chosen number.
- **Playlists** (Jellyfin, Emby): opening a playlist now reads it as an account allowed to (its owner or one it is shared with) instead of the first account, which the server could refuse; a refused read says so instead of looking empty.
- **Photo library stats** and the other figure rows (*arr status, queue, indexers, music library) adapt to narrow widgets: no stray separator when figures wrap, storage and totals wrap instead of being cut, per-account figures go under the name.
## [0.3.0] - 2026-10-22
### Upgrading from 0.2.5
- Back up the complete data directory, then pull and recreate NasDash without deleting data or volumes. Accounts, credentials, integrations and saved pages are preserved; no automatic data migration is introduced. New connections and settings are added only when you use them.
- Readers whose accounts list allowed widgets explicitly do not see the new Media, Music, Downloads, Photos and Custom API widgets until an administrator grants them in **Settings → Users and access**; readers without a list are unaffected. Music playback and download controls need a signed-in account; pause and resume are for administrators.
- When the new widgets are configured, the NasDash server contacts the saved media, music, photo, *arr and download servers and custom APIs. **Coming soon** with catalogues also contacts `api.tvmaze.com`, `kitsu.app`, `graphql.anilist.co` and, with a TMDB connection, `api.themoviedb.org` (only TVDB/IMDb ids and searched titles leave the server). Allow these destinations if outbound traffic is restricted.
- Requests that change something (saving, controls) must now come from the exact host and port NasDash is served on. Behind a reverse proxy, keep the original `Host` header (the default of common proxies).
- To roll back, recreate the recorded `0.2.5` image with the same data mount. Version 0.2.5 ignores the new widgets, connections and settings; remove those widgets first for a clean page, or restore the pre-upgrade backup if the exact earlier state is required.
### Added
- **Media** widgets for Jellyfin, Emby and Plex: **Recently played** (what plays now large over its art, then what was watched lately with where it stopped), **Media library** (totals, one card per library with rotating covers and what arrived this week) and **Coming soon**.
- **Coming soon** reads up to three sources in a chosen priority: the *arr calendars (episodes, movies with their cinema/digital/physical release, albums), the series of a Jellyfin, Emby or Plex library (next episodes from TVMaze) and public catalogues (TVMaze, Kitsu, AniList, TMDB with a TMDB connection) as a watchlist searched from its settings or as discovery; **Airing** and **Announced** tabs, pages.
- **Downloads** widgets, in their own section of the widget library, with Sonarr, Radarr, Lidarr, Prowlarr and qBittorrent, Transmission, Deluge, SABnzbd, NZBGet connections: **Download queue** (progress and state read live from the download client, last imports at rest), **Download clients** (speeds, items, space), **Indexers** (Prowlarr requests, grabs and failures) and **\*arr status** (versions, health, free space per media root folder).
- Administrators pause and resume a download, or a whole client, from the queue and the client widgets.
- **Music** widgets for Jellyfin, Emby, Plex and Navidrome (and other Subsonic servers): **Listening** (the track over a blur of its cover, what comes next), **Music activity** (albums added, albums played, tracks played, or all three as pages), **Music library** (artists, albums, tracks, hours, genres, the week's albums), **Most played** (albums, tracks, or both as pages) and **Playlists**.
- **Music playback** in the browser for signed-in users: play an album, a playlist or a track from any music widget; **Listening** shows it with its controls, seek and queue, searches tracks, albums and playlists, and steers Jellyfin and Emby players. Each music widget can turn its play buttons off.
- **Photos** widget for Immich and PhotoPrism (slideshow, grid, mosaic, strip; random, recent, favorite, album or "on this day") and **Photo library stats** (photos, videos, albums, people, storage, photos per year, the last 30 days) with new **Piwigo** and **LibrePhotos** connections.
- **Custom API** widget (experimental): any JSON API saved in Settings → Integrations, its values picked by clicking them in the API's answer and shown as figures, gauges, lists or tables.
- **Bookmarks** widget with folders (up to eight levels, icons and notes) as a folding tree, tiles or icons, with search and drag and drop.
- **Technitium DNS Server** as a third source of the DNS widget, which now names the server (and Technitium node) its figures come from (#130).
- Markets: symbols are put in order by drag and drop.
### Changed
- News feeds, Recently added and Recently played spread their rows in columns when the widget is wide.
- Content widgets ask their service only once they are first on screen; photos stop changing while the browser tab is in the background.
- Deleting a bookmarks folder keeps what it holds by default (moved up one level).
- Settings dialogs: segmented choices drawn inside one frame; a connection named after its service no longer reads "Jellyfin · Jellyfin". Numbers follow the interface language.
### Fixed
- Loading indicators (action buttons, searches, play buttons) were invisible: they spin again.
- Media and *arr widgets read a cleared setting as unset: turning **Show who is watching** off works.
- Posters keep a day in the browser cache; widgets dim their previous answer while a changed setting loads.
- Requests to services name their client (`User-Agent: NasDash`): APIs such as GitHub's refused them.
- Site icons of bookmarks and feeds are sharp; bookmark icons show in edit mode for a widget not saved yet.
- The Immich connection test only needs the permission the widget uses (`asset.read`).
- Emby, Plex, Immich, Piwigo, Deluge and SABnzbd requests checked against their APIs: paged Emby users and folders, Plex search and music sorting, Immich paging, Piwigo counting photos and videos together, no daily figure shown as a total.
### Security
- Requests that change something must come from the same host and port: a page served by another service on the same machine can no longer act with a NasDash session.
- Photos, covers and audio are served only through the widget that listed them, to accounts allowed to see it; library addresses and links are sent to administrators only.
- Custom API samples never show the configured credentials; public catalogue answers are size-bounded and service requests never follow redirects.
## [0.2.5] - 2026-10-15
### Upgrading from 0.2.4
- Back up the complete data directory, then pull and recreate NasDash without deleting data or volumes. Accounts, credentials, integrations and saved pages are preserved; no automatic data migration is introduced. New settings (feeds, market watchlist, quotes) are added only when you use them.
- Readers whose accounts list allowed widgets explicitly do not see the new Ad blocking (DNS) widget until an administrator grants it in **Settings → Users and access**; readers without a list are unaffected.
- The network map's editing tools moved from the page header into the map, in edit mode.
- When content widgets are configured, the NasDash server contacts the saved feeds, `query1.finance.yahoo.com` (markets and currency rates), `zenquotes.io` (optional quotes) and the saved Pi-hole/AdGuard Home servers. Allow these destinations if outbound traffic is restricted.
- To roll back, recreate the recorded `0.2.4` image with the same data mount. Version 0.2.4 ignores the new widgets and settings; remove those widgets first for a clean page, or restore the pre-upgrade backup if the exact earlier state is required.
### Changed
- Machine widgets name measures by their kind only (CPU, RAM, GPU, iGPU, Disk); disk and GPU names appear only when a machine has several, and full names stay in tooltips. Integrated graphics are shown as iGPU, and the Device widget can hide either graphics chip when a machine has both.
- Measure names always sit on the left and values on the right: when they collide, values move to the next line, spread from edge to edge, and a name too long for its line is shortened with an ellipsis instead of wrapping. One-measure widgets keep the machine name visible beside a disk or GPU name.
- The Docker hosts widget now includes the running/stopped container counters. Existing pages keep their counters widget until it is removed (a button offers it in edit mode); new Docker pages no longer add it.
- Docker image and volume rows are more compact on small screens, and expanded details use the same background as the search fields.
### Added
- Docker hosts can be edited (an empty API key keeps the saved one) and reordered by drag and drop from the Docker hosts widget.
- Content widgets (#98 for markets): **News feeds** (RSS/Atom; list, headlines, cards, magazine), **Markets** (stocks, indices, currencies and crypto from Yahoo Finance; list, bars, chart, tiles, ticker), **Quotes** (your own quotes and an optional online source, six typographic styles) and **DNS blocking** (Pi-hole v6 and AdGuard Home; bars, chart, ring, compact, complete, with pause and resume for administrators).
- Feeds, the market watchlist and quotes are saved once in Settings → Widgets; each widget picks what it shows. Pi-hole and AdGuard Home connections are added in Settings → Integrations, several of each if needed.
- Market symbols are found by searching a name (Bitcoin, Apple, CAC 40…). Cards and tiles show page by page or in a scrolling row, with an adjustable number per page.
- Every content widget can be resized down to the narrowest width, and its dialog links to its shared settings.
- Markets can show prices in each symbol's own currency or converted into one of 16 currencies (US dollar, euro, pound, Swiss franc, yen…) at the current rate; the percentage stays the market's own.
- The Ad blocking (DNS) widget lets you choose its figures: total queries, blocked queries, blocked share, listed domains, active clients.
### Changed
- Widgets that are not set up yet show a short explanation and one button to the place to configure them.
- The network map's editing tools (node, group, link, generate) moved from the page header into the map, in edit mode. The empty map explains that it can be drawn by hand and that generation needs services or machines and gives a first draft.
### Security
- Visitors no longer receive the addresses of saved feeds or of Pi-hole, AdGuard Home, Immich and PhotoPrism connections. The DNS widget has its own visitor permission, like Tailscale. Content widgets only fetch sources saved by an administrator.
### Fixed
- Network ports seen both as a NasDash service and as a Docker container port appear once, under the service name; stopped containers are listed last under their own heading (#115). Thanks to @emile-bodin for the report and the proposed fix (#116).
- The weather widget no longer replaces the forecast with an error after a brief network failure: it keeps the last forecast, retries within minutes and asks the weather service less often.
- Main action buttons (Save, Done…) keep their colour on hover in every theme instead of turning dark.
- Market rows with aligned columns no longer leave an empty column when the widget is narrow or curves are hidden.
- Adding a saved connection and copying a quote work when NasDash is opened over plain HTTP on a LAN address.
- Show progress while a Docker host is added, opened or removed: a new host is selected at once, its chip shows a spinner while its containers load and an alert when it cannot be reached, and confirmation buttons show a spinner while they run.
## [0.2.4] - 2026-10-13
### Upgrading from 0.2.3
- Back up the complete data directory, then pull and recreate NasDash without deleting data or volumes. Accounts, credentials, integrations and saved pages are preserved; no automatic data migration is introduced.
- The supplied Compose examples now make the Docker proxy optional. Existing proxy installations must retain their current Compose service or use `--profile docker-proxy` when recreating the supplied stack. Portainer, Dockhand and Docker-compatible API/socket connections work without this proxy; keep the existing data mount.
- Forwarded client addresses are trusted for rate limits only when `NASDASH_TRUST_PROXY=true` is explicitly set behind a trusted proxy. Direct installations need no override.
- Existing temperature selections now refer to CPU temperature; GPU temperature has its own choices and alerts when available. Demo edits survive reloads: use Reset to restore the fictional workspace.
- To roll back, recreate the recorded `0.2.3` image with the same data mount; restore the pre-upgrade backup if the exact earlier state is required. Rollback also restores the earlier behavior and omits this release's security and reliability fixes.
### Maintenance
- Refresh compatible React, service telemetry, UUID and browser-test dependencies; retain the Node 22 baseline.
### Fixed
- Require explicit trusted-proxy configuration for forwarded rate-limit identities and limit failed login attempts per account independently.
- Tighten explicit reader allowlists and private configuration recovery; keep private assets and calendar connection details protected while preserving existing access-list compatibility.
- Preserve related configuration files on reported save failures, validate local calendar dates and upload filenames, and record the application version in standalone backups.
- Refresh monitoring connection contexts after endpoint or credential changes, recover Glances API-version changes, preserve independent storage volumes, reject invalid responses, and prevent older collections from overwriting newer readings.
- Keep failed machine collections visibly unavailable with stale readings, and show calendar feed and initial configuration failures instead of indefinite loading or a silent empty view.
- Parse iCalendar time zones, recurrence rules and exceptions with bounded expansion, including folded and escaped text.
- Translate Docker diagnostics and operation errors across all five languages; distinguish denied socket access, invalid responses and unavailable sources. Preserve forms after failed saves or deletions and show inspect/action errors.
- Resolve Docker actions to an exact container, restrict fictional engine/device data to demo mode, and compare normalized image identities before offering removal.
- Normalize Docker resource responses across HTTP APIs, Unix sockets, Portainer and Dockhand; retain visible image tags, digests and identifiers, including untagged images, and refresh image/volume confirmations and presentation.
- Keep integration form fields labelled for assistive technology, support media address copying on trusted HTTP LANs, and prevent secondary-link tooltip overflow on narrow screens.
### Changed
- Keep Device and Metrics bar/chart names on the left and all statistics on the right, on one line when they fit. Wrap within the available width while preserving readable captions and full values.
- Unify dashboard dropdowns with the existing NasDash selector, improve popup positioning and keyboard focus (including Tab immediately after opening), and label every selector. Place Docker page selection in the responsive table header and usage counts beside Refresh, replace the repeated footer explanation with the existing information bubble beside the image/volume title and remove its decorative icon, use red for unused resources, and default to five rows on mobile while retaining explicit page-size choices. Remove duplicate CPU/GPU metric captions; keep the GPU-model option where it adds information.
- Rework Docker image/volume lists with search, usage filters, sorting, 5/10/25/50-item pagination, expandable metadata and page-scoped selection. Keep deletion confirmations readable, preserve only failed targets for retry, and adapt to narrow widgets and mobile widths using the existing appearance tokens. Include fictional unused resources in the isolated demo.
- Keep fictional demo edits in a temporary browser-tab workspace across reloads and server-worker changes, with serialized requests and an explicit Reset restoring fixtures. Browser session storage is required for reload retention; direct cookie-only demo API clients keep temporary process-local state.
- Separate CPU and GPU temperature choices in device and metric widgets when the source supplies GPU temperature. Keep existing temperature selections as CPU temperature, with independent display options and thresholds; preserve readable labels in narrow layouts.
- Make the local Docker socket proxy an optional Compose profile. Portainer, Dockhand and Docker-compatible API/socket connections remain alternatives; document their configuration, permissions and resource operations in all five guide languages. Existing proxy users must keep their Compose configuration or enable the profile when recreating the stack, without changing the data mount.
## [0.2.3] - 2026-10-12
### Upgrading from 0.2.2
- No new data migration is introduced. Existing accounts, credentials, integrations, configuration and customized pages are preserved. Back up the complete data directory, then pull and recreate the container without deleting data or volumes.
- Storage defaults to host grouping; choose **By usage** to restore the previous fullest-first order, or **Manual** to arrange volumes with handles. Metric and display-group orders are saved per widget with the page.
- To roll back, stop NasDash and recreate the previous `0.2.2` image or recorded digest with the same data. That version ignores manual reading/group order and uses its previous Storage presentation. Restore your pre-update backup if you need the exact earlier configuration; upgrades from 0.1.x still follow the [0.2.0 migration guidance](#020---2026-09-30).
### Fixed
- Close secondary service-link bubbles after opening a destination or leaving the dashboard tab, while preserving hover and keyboard access. Match the pointer's hover border to the bubble and respect the ping-details setting for each secondary address, including legacy Tailscale links; show a loading state until its own result arrives.
- Recognize Glances' unnamed `k10temp` CPU temperature sensors on Synology DSM. Ignore non-temperature sensors and invalid readings while preserving existing CPU sensor priorities.
- Keep demo calendar trials in the current browser tab, so adding, editing and deleting fictional events work across stateless hosting instances. Reloading or resetting restores demo events; installed calendars retain server persistence. Exercise all five demo locales in required production browser CI without a calendar API.
- Edit or delete local events from calendar details on any page, including the upcoming-event list, and choose the date when adding or editing. Preserve event duration, reset each form, refresh the widgets after successful changes and keep failed changes open with a localized error. ICS events and viewer access remain read-only.
- Translate wallpaper and appearance-profile delete confirmations in all five languages; extend the interface-copy gate to confirmation labels with regression fixtures.
### Changed
- Reorder the Ring, Figure, Bar and Chart groups in the single-machine widget with named handles, without changing metric display formats. Keep the initial layout until a group is moved; save group order with the page, retaining positions for hidden groups. Charts move together with their history and range controls.
- Reorder readings within CPU, RAM, GPU, temperature, load, network and single-machine widgets in page edit mode, using mouse, touch or keyboard handles in figure/bar/ring displays. Storage adds **Manual** volume order; host/usage modes and charts disable dragging. Orders are saved per widget with the page, preserve temporarily missing readings and do not reorder the shared machines.
- Remove the doubled separator between shown-value options and danger alerts in machine-widget settings.
- Group Storage volumes by host and naturally sorted volume name by default, including existing widgets. Choose **By usage** in widget settings to restore the global fullest-first order. Keep each host's chart colour stable when volume usage or the sort mode changes; no data migration is required.
### Documentation
- Centralize user/operator guides on the dedicated documentation site, align all five languages with current integrations, composable pages, backups and first-install behavior, and replace duplicate repository guides with canonical links.
- Open the Custom CSS guide in the selected interface language and link startup permission diagnostics to the published installation procedure.
## [0.2.2] - 2026-10-10
### Upgrading from 0.2.1
- No new storage migration is introduced. Existing accounts, passwords, keys, integrations, configuration and customized names are preserved. Back up the complete data directory, then pull and recreate the container without deleting data or volumes.
- Startup now stops immediately when the configured runtime UID/GID cannot access the data directory, logos or existing files. On Synology, check the dedicated DSM account and shared-folder ACLs; a Compose `user: "UID:GID"` override must match the permitted identity. See [installation and permissions](https://docs.nasdash.lucas-homelab.fr/en/docs/getting-started/docker-installation).
- Generated initial passwords are logged once after their hashes are saved. Restarting or rebuilding never resets an existing account. If its password is lost, stop NasDash and use the offline recovery helper from 0.2.2 or later; recovery revokes that account's existing sessions and preserves the rest of the data.
- To roll back, stop NasDash and recreate the previous `0.2.1` image or recorded digest with the same data. That image retains the old first-login password initialization and has no offline recovery helper. Keep your backup for an exact pre-update restoration; upgrades from 0.1.x still follow the [0.2.0 migration guidance](#020---2026-09-30).
### Fixed
- Initialize local accounts and persist their password hashes at server startup, so generated initial passwords appear before readiness or the first browser connection. Never announce a generated password after a failed account write; preserve existing passwords across restart.
- Abort Docker startup with an actionable runtime UID/GID diagnostic when the data directory, logos directory or existing files are inaccessible. Respect `NASDASH_DATA_DIR`, initialize files atomically, and retain non-root operation with supported Compose `user` overrides.
### Added
- Offline password recovery with hidden input and session revocation, preserving other accounts, access rules, keys, integrations and configuration.
- Synology/Container Manager installation, ACL, UID/GID and log guidance; a dedicated GitHub user-feedback template; required container regression checks for first-start credentials, recovery, custom UID/GID and denied mounts.
## [0.2.1] - 2026-10-10
### Upgrading from 0.2.0
- No new storage migration is introduced by this release. Existing pages, settings, integrations, credentials and customized names are preserved. English example names apply to fresh installations; saved French example names remain yours to rename.
- Back up the complete `data` directory before updating, then pull and recreate the container. Do not delete the data directory or run `docker compose down -v`.
- To roll back, stop NasDash, select the previous `0.2.0` image or its recorded digest and recreate the container using the same data. Italian is unavailable in 0.2.0; select another supported interface language before rolling back. Keep the backup if you need to restore the exact pre-update configuration.
- Upgrades from 0.1.x still follow the migration and rollback guidance under [0.2.0](#020---2026-09-30).
### Added
- A complete Italian interface, including the public demo, widgets, dialogs, settings and locale-aware formatting. Italian is saved as the instance language and accepted by the demo's `?lang=it` handoff; the website and all 54 documentation pages also maintain Italian versions.
### Changed
- Use English startup, authentication, persistence, backup and monitoring diagnostics. Supply English machine/service/topology names and translated official page labels on new installations, preserving existing customized names and files. The required i18n gate now checks log/default copy, and the container smoke test exercises English initialization and preservation across restart.
- Enable Vercel Web Analytics on the public Vercel-hosted demo; normal self-hosted installations and local demos keep analytics disabled.
- Refresh README, website and documentation previews from the current isolated demo, with reproducible capture and synchronization scripts.
- Patch Next.js and image/source-map dependencies to pass the production security audit. The full CI audit has one explicitly approved, development-only `braces` exception expiring on 24 October 2026; see `docs/DEPENDENCY_AUDIT.md`.
## [0.2.0] - 2026-09-30
The first release of the new NasDash: every page is a free grid of widgets, the whole interface is redesigned (Calme), integrations have their own page, machines get detailed metrics, and phones get their own layout.
### Upgrading from 0.1.x
- **Your data is migrated on first start, automatically.** Services, devices, Docker hosts, Tailscale and your pages are kept. The earlier files stay next to the new ones: `config.pre-integrations.json`, `config.pre-sources.json` and `pages.v*.json` / `pages.previous.json`.
- **Back up before upgrading:** `npm run data:backup` (or a copy of the `data` folder); from this version, Settings → Tasks and backups can also do it.
- **Rolling back:** stop NasDash, restore the backup with `npm run data:restore -- --from <folder> --force`, then start the `0.1.4` image again (0.1.x does not read the migrated configuration, so the restore is needed).
- The Classic interface is gone; the old `designStyle` setting is ignored.
- A Proxmox connection with a self-signed certificate needs "Accept a self-signed certificate" on its connection (Settings → Integrations).
### Added
- **First steps** on the Home page for admins: add services, connect a monitoring source, add machines, connect Docker, choose the weather, make it yours. Each step ticks itself from the configuration and opens the right place; the card can be closed (Settings → Help shows it again) and disappears once everything is done. Visitors of a dashboard not set up yet get one welcome card with a log-in button.
- **Phone and tablet order.** Each page has its own order for phones and tablets (`page.mobile`), separate from the desktop layout, which never changes. In edit mode on a phone or tablet, the page shows as a list: each widget moves with its handle (dragged within the list) or its arrows, can go to the top, and can be hidden on phones and tablets; "Automatic order" goes back to the default. Until an order is chosen, pages read column by column, as they are built on desktop (a wide widget with nothing beside it ends the columns above it).
- **Tablets** (700 to 1,000 px of page width) show two columns in that order, each widget going into the shorter one.
- Settings → **Media** replaces Wallpaper and keeps it, and adds the logo and icon library: import, where each file is used (services, secondary links, header), copy its address, delete (with a warning when still in use), filter the unused ones.
- Settings → **Tasks and backups**: the background tasks (machine readings, service pings, 24 h history save, backups) with their state, last run and rhythm. Machine readings (dashboard open / nobody watching) and pings can be slowed down or sped up. Backups of the whole data folder as a `.tar.gz` (same layout as `npm run data:backup`, restorable with `npm run data:restore`): back up now, automatic daily or weekly backups keeping the last 3 to 30 (manual ones are never removed), download and delete. Admins only; off in the public demo.
- Settings → **Help**: the documentation by topic in the interface language, and where to report a problem.
- Device and metric widgets: a **Danger alerts** switch turns every threshold off (they are kept for when it is turned back on).
- Docker container list: in edit mode, choose how many containers show before it scrolls (default 7, 4 to 16, or all).
- Service categories get a settings button in edit mode (pings shown on all layouts, list layouts only or none; address or ping and latency under the name).
- In edit mode, a widget title is renamed by clicking it (Enter or leaving the field saves, Escape cancels, empty brings the default name back); the title is kept with the page.
- The Docker hosts widget has a button, in edit mode, that opens the Docker section of the Integrations page to set up its hosts.
- Every page (Home, Docker, Networks, Widgets and your own pages) is now a free grid of widgets. Official pages remain ready to use and can be rearranged, duplicated, restored or deleted like any other page.
- New interface **Calme** (quiet tinted neutrals, one sparing accent, Geist Mono, hairline cards, calmer titles, buttons, fields and dialogs), applied as a separate layer (`src/app/design-calme.css`). It replaces the previous look entirely: the **Classic** style, its components and its CSS are removed (an older `designStyle` setting is simply ignored). The historical default radius, card opacity and font count as not customised; values you chose still apply, as do all themes. Widgets get their Calme version one by one (clock, then weather: same locations, styles and refresh; new line icons with quiet animations, a discreet scene following the sky and the time of day at the location — day, night with stars, dawn, dusk, clouds, rain, snow, storm, fog — and a layout that drops secondary parts in narrow blocks instead of overflowing; motion stops when the system asks for reduced motion). In edit mode, widget controls appear on hover and no longer cover Calme widget titles; entering or leaving edit mode re-places widgets in the same frame (heights are measured before the browser paints), so they never overlap during the switch. Service categories take the Calme title style and, unless a position was chosen, show their title above the card; service rows and pings are unchanged. The weather scene stays at the top of its card and fades out. The devices widget uses the Calme container (title above, thin flat gauges) with all its settings, styles and reordering unchanged. The calendar has a Calme version (quiet month grid, today in accent, a dot on days with events, upcoming events beside the grid from 520 px wide, event titles in the days from 760 px); days and events open the same dialogs. The overview widget shows four quiet figures. The Docker, network, Tailscale and port widgets get a shared Calme shell (title above, flat block, no coloured title icon), and Docker lists, tabs, stats and logs are calmer (status shown by the dot, selection without glow). Second Calme pass: services in bento and logo layouts have a single level (no frame around each tile, a quiet surface on hover); the weather card drops the sky label (kept as the icon tooltip); the clock is a large light time with a hairline filling as the day goes by (its clock styles still apply); the overview shows the number of services with a bar split by category. The latency graph, Docker containers (short uptime, start/stop on hover, same host choice, pagination and automatic scrolling), Docker actions, Tailscale (online devices first), the ports widget (the signature line still toggles hidden categories for admins), the Network page tools and the Docker counters get their own Calme versions. Settings in the Calme style, following the D-Settings mock-up:
- Navigation:
- a short text navigation (Personalisation: Appearance, Wallpaper, Header, Mobile, Tabs and dock; Dashboard: Pages, Widgets; System: Users and access, Developer);
- a search field that also finds each widget's options;
- one "Widgets" hub listing every widget with the pages where it is placed.
- Each section has a breadcrumb, a large title and one short line.
- Explanations moved into small ⓘ tooltips, and the demo notice is a small tag.
- Every section, and each widget's options, is rebuilt as a few airy blocks with one line per setting: segmented choices, sliders with their value, plain switches, and ordered lists with arrows for the header elements and the dock tabs.
- New accent colour setting (six swatches or the theme's own).
- Existing section links still work, the phone view keeps its menu then section drill-down.
- Users and access: the user list and a simple editor, with the role as a two-way choice and allowed tabs and widgets as chips.
- Calme dialogs:
- calmer titles and labels;
- demo notices as quiet text;
- buttons at their natural width, grouped on the right, with the delete action apart;
- lists as hairline rows;
- a plain left-aligned confirmation;
- a lighter widget library.
- Fixes:
- drop-down lists stayed transparent: a low card opacity, then the rule that flattens nested boxes, made them see-through. They are now opaque and open upward when there is no room below. Header menus are opaque too;
- ⓘ tooltips are no longer cut by scroll areas;
- text buttons keep their icon beside the label.
- Appearance has two new options:
- Outlines: remove the thin border around widgets, cards and dialogs;
- Background blur: a slider that frosts what shows through translucent surfaces when there is a wallpaper.
- The theme and icon gallery opens inside the settings (the navigation stays): quiet theme thumbnails with search and dark/light filter, and icon styles shown as a row of samples.
- The network map dialogs (node, group, link, automatic generation) are rebuilt on a shared Calme dialog frame (`CalmeDialog`), with segmented choices for the category, direction and attachment points, a check list for group members, and explanations in ⓘ tooltips.
- The service, category, device, Docker action, Docker host, new event and event dialogs use the same Calme dialog frame:
- fields one under the other, with their explanations in ⓘ;
- segmented choices (action type, connection);
- check lists for target containers;
- expandable rows for the services of a category;
- a footer with the delete action apart.
- Widgets can be resized from all around: sides change the width, top and bottom the height (a minimum the block stretches to; the content can still make it taller, and dragging back below the natural height returns to automatic), and corners both, with matching cursors.
- The clock and the overview drop their gauges. The Docker container list gets its light outline back, and the Docker containers widget has more room between rows.
- The latency graph is smoother, with a line fading in from the left, the average as a faint dashed line and a live dot. Average, range, jitter and quality became an option of the widget (Settings → Widgets → Network graph), off by default.
- The edit bar at the bottom of the page is a calm translucent pill with ghost buttons.
- Fixes:
- edit controls no longer stay visible after closing a dialog opened from them;
- the background blur now works (the finished entry animation kept widgets isolated from the page).
- Calme harmonisation:
- one surface for every block: widgets, categories, the Docker detail, logs and container list, the network map, header controls and the edit bar. The same colour, card opacity, blur and outlines apply everywhere, and what sits inside a surface is transparent;
- with outlines off, inner elements (stats, ports, hosts, map nodes and groups, choices, fields) get a very light fill instead of a border;
- other themes stay translucent: they are no longer mixed with the opaque page colour.
- Resizing works from all around (sides, top, bottom, corners) but changes the width only; the height follows the content again.
- Categories can take any width (2 to 24 columns) to line up with their neighbours.
- Dragging a widget drops it exactly where it is released, even on a quick flick. GridStack measured the grab offset from the first move and refused large jumps; the drop is now computed from the pointer and the grab point, and neighbours are pushed down.
- Services: bigger logos in lists. In the grid with names, the tile is the logo background with the logo and the name inside.
- Performance:
- entering or leaving edit mode takes about 50 ms instead of about 200 ms (grid moves applied in one batch);
- pings no longer restart when an unrelated setting is saved, and pause while the tab is in the background;
- the latency graph and the clock do no work on hidden pages;
- a page is shown sooner after its widgets are measured.
- Services: logos in lists sit on a light translucent tile without outline. The four grid layouts (with names, and large, medium and small logos) share the category width in as many columns as fit, without the heavy tile background.
- The header search field and buttons line up exactly with the outer edges of the widgets. Edit controls sit flush in the widget's top-right corner, on its title row.
- With a background blur, blocks no longer fade in, so the blur is there at once on page changes (a fading block cannot blur what is behind it).
- Themes under Calme:
- cards are fully opaque at 100 % card opacity, in the theme's own card colour. Before, they were half-transparent and, with the default opacity, fell back to the default theme's colour;
- secondary tones that some themes do not define (secondary backgrounds, logo tiles, progress bars) are derived from the theme's text colour, which fixes the black active header button and dark controls;
- sliders keep a visible track on light themes.
- Logo tiles are more visible, and logos are bigger in the grid layouts.
- The edit controls of a widget are a small solid pill again, flush in its corner.
- The resize arrow follows the edge: vertical on top and bottom, diagonal on corners. The resize still changes the width only.
- New **Settings → Integrations** page: every connection of the dashboard in one place, in the order a newcomer needs them. It starts with two steps (connect a monitoring source, then add your machines) ticked when done, then one block per category with the connections already set up (real logos, their state tested when the page opens, the machines using them) and the tiles to add one:
- **machine monitoring**: Glances, Netdata, Beszel, Prometheus, Proxmox VE and Libre Hardware Monitor, each with its connections, the machines using them, a test and edit/remove;
- **Docker containers**: the Docker/Podman engines;
- **private network**: Tailscale or Headscale, in a dialog (the Tailscale widget settings now link there).
A monitoring connection is saved once and shared: machines on the same Beszel, Prometheus or Proxmox server use one connection. Its test lists the server's machines, so they can be added at once when saving, and the device form picks the machine from that list instead of typing it. Single-machine sources (Glances, Netdata, LHM) can create their machine when the connection is saved.
- The device form no longer asks for addresses and credentials: it picks the source of its measures (with a link to manage the sources), and on a server the machine; with no source yet it explains the first step and links to the Integrations page. Existing devices are migrated on start (previous file kept as `config.pre-sources.json`); a device whose address cannot be read keeps its former connection. Connection addresses are no longer sent to non-admin users.
- Device widget defaults follow what the machines report: the Fleet shows the GPU by default as soon as one of its machines has one, and the widget dialog marks the measures none of the chosen machines reports ("not reported").
- In edit mode, the note beside a widget title ("2 / 4 online") keeps a gap before the widget's buttons.
- Widgets that cannot work yet show their first steps with direct links, in order: the machine widgets (connect a source, then add the machines), the Docker widgets (add an engine) and the Tailscale widget (connect Tailscale or Headscale). Visitors are told an administrator sets this up.
- Device widgets are set up in a real dialog (✎ in edit mode) instead of a drop-down menu; Docker Containers too (items per page, automatic scrolling). One model, shared by every device widget:
- the machines to show (one for Device) and the measures to show: CPU, RAM, GPU, temperature (hottest part), load, network, disks and, for Device, the CPU + RAM history;
- the display: figure, bar, ring or chart, the same for every measure or one per measure (a throughput is a figure or a chart);
- a colour per measure, chosen in a small colour dialog: preset colours, favourites kept in the settings and shared by all widgets (`favoriteColors`), a free colour or its hex code, or back to the default;
- a danger threshold per measure, with defaults (90 % for CPU, RAM, GPU and disks, 80 °C, a load of 1× per core, none for the network) and one danger colour for the widget: past its threshold a measure (bar, ring, figure, line of the Fleet) takes that colour, and charts show the threshold dashed. Colours are only ever hex values.
The layout follows the width by itself: Device groups rings and figures side by side, bars below and charts across, with rings and charts sized to the widget (rings now show as rings at every size), and resizes down to 3 columns. The Fleet lays each machine's measures beside its name, or under it when they do not fit.
- New one-measure widgets: **CPU**, **RAM**, **GPU**, **Temperatures**, **Load** and **Network**, a figure, bar or ring per machine or one chart with a line per machine and the danger threshold; **Storage** is now the disk version (every disk, the fullest first). The machines chart gains the same dialog (measure, style, height, machines, colour, threshold).
- Device widgets, third pass:
- the machines chart leaves the library: the one-measure widgets drawn as charts cover it, and the machines charts already placed show as the one-measure widget of their measure, with their machines, style and height;
- when a measure (or all of them) is drawn as a chart, its dialog offers the chart type (filled area, line, bars) and height (small, medium, large);
- switching from one display per measure to one for all and back gives each measure its own display again (each keeps its own choice and chart options);
- one-measure widgets give each machine its own colour (a distinct one by default on charts), and their dialog sets, for the whole widget, how RAM and disks are written (percentage, used size or free size) and the extra figures: CPU temperature and load, GPU temperature and video memory, upload, load averages and cores, the part a temperature comes from;
- RAM and Storage show any of their share, used size, free size and total size (several can be ticked, only those are shown, a size is followed by the total: `210 Go / 500 Go`); by default the share and the total;
- the 1 h / 24 h switch and the default period only appear where something is drawn as a chart;
- in the settings dialogs, each machine has a button to its own settings (the changes made in the dialog are kept);
- rings are centred in their cell, the name of a machine or disk sits under the ring (short names like CPU stay inside), and long texts are shortened.
- Very narrow blocks no longer force a minimum width on container and action lists.
- Drop-down lists are drawn above the page, positioned on their field: dialogs and scroll areas can no longer cut them (the monitoring API list of the device dialog was hidden at the top). They open downward, or upward when there is more room, never taller than the room they have.
- Dropping a widget just under another no longer swaps them: when the dropped widget's top edge lands in the lower half of the one above, it settles right below it; in the upper half, it takes its place as before. The drop is decided from the layout as it was when the drag started.
- New device widgets, drawn with a shared Calme chart kit (`src/components/charts`: smooth time chart with a gradient, live dot, dashed cursor and a tooltip that stays inside its block; thin rings; stretchable sparklines; usage bars). One colour per kind of measurement everywhere (CPU accent, RAM violet, disk amber, GPU green) and an orange alert tone only for parts at 80 °C or more and disks at 90 % or more:
- **Device**: one machine in detail. Wide, it shows CPU and RAM rings, temperature, load against the core count, received and sent throughput, GPU, CPU + RAM over 1 h or 24 h with exact values under the pointer, and disks with free space. Below 440 px it shows one line per measurement with its curve, a network and load line, and the disks;
- **Machines chart**: CPU, RAM, GPU, temperature or network for several machines, one line each, all values in the tooltip;
- **Storage**: every disk of every machine, the fullest first, with free space and the total in the title;
- under Calme, the **Devices** widget becomes the **Fleet**: one line per machine with state, CPU and RAM bars, the CPU trend of the last hour (from 520 px) and the hottest temperature (from 400 px); below 300 px the name sits above the bars. Offline machines are dimmed and its choice of devices is kept. It now resizes up to the full width.
Widgets showing the same machine share one reader, which polls every 10 s only while one of them is visible, and each widget's options (machine, measure, machines, default period) sit in its edit-mode menu. The 1 h / 24 h switch sits inside the block, so it stays reachable when widget titles are hidden.
- Devices now have a server-side history: every poll for the last hour and one averaged point with its peak per minute for 24 hours, saved to `data/metrics-history.json` so a restart keeps the day. Monitoring starts with the server and keeps polling once a minute when nobody is watching (every 10 s while a dashboard is open), so charts can open already filled. `GET /api/devices/<id>/history?range=1h|24h&since=<ms>` returns the current reading, the new vitals and the series; the demo computes repeatable moving curves.
- Device integrations report vitals besides usage gauges: uptime, load average, CPU count and network throughput (physical interfaces only) for Glances, Netdata, Prometheus (queries now sent together), Beszel (total bandwidth), Proxmox (uptime and load of a node; throughput of a guest from its counters) and Libre Hardware Monitor (adapter throughput).
- Appearance → Soft edges (0–20 px): widgets and blocks fade softly into the page instead of ending on a sharp edge, header controls included (half as wide); the outline gives way while it is on and the content is untouched.
- Network map rebuilt:
- the historical structure is kept, with room to breathe: infrastructure, machines and network services in a left column (one card per row), a wide corridor, then the application groups on aligned rows (two cards per row); cards widen or narrow a little so the applications keep their columns;
- links are bundled by source: the links of a machine leave from one point, share a trunk down the corridor and branch off into the side of each group, while other sources keep to their own lanes; two elements facing each other over a free gap are joined by a straight line (without arrowheads between close neighbours); for other links, a single search tries every sensible pair of sides at once and keeps the cheapest path (length, bends, crossing other lanes), around every card, group title and layer heading, always leaving and entering a card straight from its side; attachment sides chosen in the link dialog are kept when they cost about the same, and otherwise replaced rather than drawing a line through the cards (sides saved for an older layout no longer force loops);
- port lists are no longer written along links (automatic generation stops adding them): each card shows its full address with the port (the linked service's local address, or its IP and first port) and, outside edit mode, opens it; other link labels take a free spot along their link, or show while the link is lit;
- the layers are told apart by a coloured dot on their heading and a tinted tile behind each node's icon (no more coloured edge on one side);
- the mouse wheel keeps scrolling the page over the map;
- hovering a node lights the links it sends (and two-way links; the links it receives only when it sends none) and dims the rest; linked groups light up with their cards; search dims non-matching nodes;
- in edit mode, a node, a group or a link opens its dialog, and the small handle of a node draws a new link onto another node or group;
- the map fills the width of its block and never shrinks below a readable size: a wider map is panned sideways by dragging the background, or zoomed with the buttons;
- narrow blocks and phones open on a list view (one section per layer, each node with its links), with the map one tap away;
- about 1,800 lines of the previous routing are gone, with no new dependency; layout tests check that cards and groups never overlap, applications stay right of the network layers, links end on their targets and never cross a card, and 240 random maps (widths, card sizes, fixed sides, labels) are checked for lines through cards, U-turns, hidden arrows and entries from inside; a 70-node map is laid out in about 130 ms (a 60-node homelab map in about 50 ms). Under Calme, cards of the other themes are blended with the page background so they stand out less.
- Service pings reach HTTPS services with a self-signed certificate (Proxmox, NAS interfaces…): the ping retries without the certificate check (also when an http:// address redirects to such an HTTPS address), since it sends no credentials, and shows “OK · self-signed certificate”. Refused connections are reported consistently by both ping routes.
- Docker hosts can be a Portainer environment (relayed Docker API, API key) or a Dockhand environment (its API translated to Docker's); their keys are encrypted on disk, masked for admins and never sent to other users.
- The Security settings list the widgets that can be granted from the widget definitions, and pages created by admins from the pages themselves (the removed custom-tabs endpoint is no longer called).
- New monitoring integrations: Netdata, Beszel (one device per Beszel system) and Prometheus with node_exporter (one device per `instance`); Headscale can feed the Tailscale widget (the connection saved last is used). Docker hosts can also be reached through a Unix socket mounted into the container (Docker or Podman) or over HTTPS. Any HTTPS device or Docker host can accept a self-signed certificate (Proxmox's default), with a clear message when a certificate is refused. `npm run fake:integrations` now also serves Netdata, Beszel, Prometheus, Headscale, Docker (TCP and socket) and a self-signed HTTPS case.
- Each widget type now lives in `src/widgets/<type>/` (`definition.ts` for name, access and sizes; `view.tsx` for the display); the widget catalogue, sizes table and two render switches are replaced by these files.
- Tailscale credentials are now a saved connection in `config.integrations` (secrets encrypted on disk, masked for admins, never sent to other users) instead of `settings`; existing configurations are migrated automatically and the previous file is kept as `config.pre-integrations.json`. The Tailscale settings form is drawn from its integration description. `npm run fake:integrations` starts local fake Glances and Libre Hardware Monitor servers (plus error cases) to try integrations without installing them.
- Device monitoring integrations (Glances, Proxmox VE, Libre Hardware Monitor) now live in `src/integrations/`: each one declares its form fields and endpoint in a manifest and reads its API in a collector that returns structured metrics. The device form, request validation, configuration API and background polling all read one registry, so adding a monitoring source no longer means editing them. The devices route now answers with these metrics and the Devices widget formats them itself (units in the interface language, colours by metric type) instead of re-reading display strings; devices without an integration keep their hand-written stats. Saved "visible stats" selections keep working.
- Edit mode works the same on every page: press anywhere on a widget and drop it anywhere on the 24-column grid, horizontally and vertically; widgets in the way move aside with an animation, and empty space is kept. Drag either side or any corner (a small triangle marks the bottom-right one) to change the width: it jumps between the formats of the widget (for example 3, 4, 6 or 8 columns for the clock, 12 to 24 for the topology), and formats narrower than the widget's minimum usable width at the current screen width are skipped, so a widget is never left in a width its content does not support; widgets in the way move down while resizing and come back if it shrinks again. The height always fits the content, with no inner scrollbar, including while resizing. On the first visit of a page the grid appears once its widgets are measured, without widgets jumping into place. Vertical gaps are kept when heights change: titles shown in edit mode push the widgets below down, and leaving edit mode brings them back without leaving space. Each widget shows its controls (its own buttons, configure, remove) in its top-right corner while editing; hidden widgets can be shown again from the library. A searchable library adds widgets at the first free spot, and changes support undo/redo (Ctrl+Z / Ctrl+Shift+Z) with an explicit Save or Cancel. Below 700 px the page becomes one read-only column where heights follow the content.
- Service categories, the Docker page blocks (hosts, counters, container list, explorer) and the network tools and topology are now widgets that can be placed on any page. Docker widgets on the same page stay linked to the same host and container.
- Settings → Pages creates a page, either blank or as a copy of an official page.
### Changed
- **Secret mode is respected everywhere:** the widget library only offers secret categories while they are revealed (tagged "secret"), and the Overview counts and the Ports list leave secret services out when hidden.
- **The dashboard signature is the page footer:** "NasDash — Private dashboard" sits centred under the last widgets (at the bottom of the screen on short pages) on every page, and toggles the secret categories for admins. The Ports widget no longer carries it, and it hides itself when there is no port to list.
- **A richer public demo:**
- five machines on four sources (NAS, Proxmox host, Raspberry Pi, gaming PC whose GPU crosses its danger threshold, cloud VPS);
- 32 services in five categories, one of them offline, each with its container and its node on the network map;
- a month of calendar events;
- a Machines page showing the device and metric widgets;
- "Try a theme" in the introduction.
The first steps card is not shown in the demo, and narrow calendars keep their event titles readable.
- Edit mode on phones and tablets has two views: **Widgets** (the widgets with their usual controls: rename, settings, remove, their own buttons) and **Order** (the list that sets the phone order and what is hidden on phones and tablets, without touching the desktop layout). Controls sit on their own row above each widget so titles stay whole. The mobile menu stays above the widget controls in edit mode.
- The header lines up with the widgets on phones too (it was 8 px narrower on each side).
- Phone settings: a lone switch stays on its label's line and sliders take the full width.
- On phones, settings take the whole screen and dialogs rise from the bottom as sheets; buttons in dialogs keep a 40 px touch height. The mobile menu's Edit button now closes the menu.
- Settings → Tasks and backups is laid out like the Integrations page: one row per task (name with ⓘ, state, last run and result, rhythm), a backup plan card (automatic schedule, number kept, next backup), the saved backups, and a restore box in three steps. A task where some machines or services did not answer shows "Partial" (orange) instead of "Problem", which is kept for a task that failed.
- Themes no longer tint the secondary text (some made it teal, purple, cyan or green): it is always the theme's text colour blended into its background; accent and hover states keep the theme.
- The Docker hosts widget uses the Calme widget shell: its title follows "hide titles" and can be renamed, and hosts are neutral chips (only the chosen one takes the accent).
- The secondary link of a service shows as a small opaque pill: its icon, what it is, where it goes (hidden in privacy mode) and an exit arrow.
- The public demo no longer polls its fictional machines on the server.
- Appearance → no outlines now also removes the borders of the header buttons and search (a more specific header rule kept them).
- While a widget is dragged, the slot shows exactly where it will land, even after a quick move across other widgets, and the other widgets stay where the drop will leave them. A widget can also be dragged by its title again.
- Fields, the chosen Docker host and the network map cards use the same recessed background as the Docker logs and stats instead of near-black.
- Multi-platform Docker images build the app once on the machine's own platform instead of under arm64 emulation (the image publish goes from about 11 to about 5 minutes); the release check also builds and starts the arm64 image.
- The interface fonts (Outfit, Space Grotesk, Syne, Righteous, Montserrat, Geist, Geist Mono) ship with the source in `src/app/fonts` (OFL, see `LICENSES.txt`): builds no longer download them from Google Fonts, which made Docker and Vercel builds fail intermittently.
- The Docker container list scrolls inside again after about seven containers, instead of stretching the page (guarded by an end-to-end check).
- With background blur, the ping marks of services in list layouts stay sharp.
- In the Docker explorer, container stats and logs sit on a darker background so they stand out.
- Header buttons and search follow the corner setting like the cards.
- Page layouts are stored in `pages.json` in the data directory, created automatically from the existing configuration on first start. `config.json`, `services.json` and `custom_tabs.json` are not modified, so the previous version still runs on the same data. Earlier development formats of `pages.json` are converted once, and the original is kept as `pages.v1.json`, `pages.v2.json`, `pages.v3.json` or `pages.v4.json`. Spacer widgets are no longer needed and are removed from converted pages. Deleting a page or restoring an official one keeps the prior pages in `pages.previous.json`. An edit made at the same time in another tab is detected and never silently overwritten.
- Widget settings no longer contain on/off switches or panel positions: a widget appears where it is placed, and each settings screen shows the pages that use it. Home-only options moved to Settings → Services, network map options to Settings → Network topology.
- The custom tab row/column builder and its `/api/custom-tabs` endpoint are replaced by pages and `/api/pages`.
- Treat `.env` as an optional advanced override while preserving generated first-start credentials when it is absent.
- Let Docker Compose derive stack and container names, avoiding fixed global names and allowing multiple installations to coexist.
- Keep every copy-ready Compose example on `./data`. A named volume is an optional new-install alternative, not the default: switching an existing folder install to `nasdash-data` leaves the real files unused.
- Refresh README product screenshots from the isolated English public demo, with the intro dialog closed and additional views of Docker, networks, widgets, settings, theme variants, layout options, and mobile.
### Security
- Moving a saved connection (monitoring source, Headscale) to another address now asks for its password or key again, so a stored secret is never sent to an address it was not given for; the connection test follows the same rule, and a device still using its own connection drops its stored token when its address changes.
- Proxmox node names are encoded in API paths, and VM ids and types are checked, so a machine can only read its own node or guest.
- Users other than admins no longer receive the address and account of devices that still use their own connection (only its type).
- Update Next.js to `16.3.4` and pin patched Vitest/js-yaml so the protected dependency audit can pass.
## [0.1.4] - 2026-09-08
### Changed
- Keep the default Compose file literal and copy-ready: it now names the published GHCR image directly and relies on NasDash's persisted first-start credential generation instead of optional interpolation variables.
## [0.1.3] - 2026-09-08
### Changed
- Simplify the default Compose files to the settings NasDash actually needs, while preserving the established Docker host port `2504`, persistence and restricted Docker socket proxy.
- Use matching port `2505` on both sides of the isolated public-demo proxy mapping; the production application remains on `2504:2504`.
## [0.1.2] - 2026-09-08
### Changed
- Compose now pulls the published image and uses Docker's standard all-interface port mapping by default. Use `127.0.0.1:2504:2504` for localhost-only publication; source builds use the explicit build override.
- No configuration or persistent-data migration is required; operators recreating an existing container should review the new LAN-reachable port default.
## [0.1.1] - 2026-09-06
### Security
- Restrict service ping requests to administrator-configured targets instead of accepting arbitrary outbound destinations.
- Restore normal TLS certificate verification for Proxmox requests and document custom-CA trust through the runtime environment.
- Render custom CSS without an HTML injection sink and remove unsafe previews of untrusted logo URLs.
### Changed
- Add complete dependency auditing and a non-regression lint ceiling to the protected quality gates.
## [0.1.0] - 2026-09-06
### Added
- The first deliberately maintained NasDash release line.
- A self-hosted homelab cockpit for services, hosts, Docker, network topology, widgets, tabs and theming.
- A consistent repository, quality, security, and release foundation.
- A maintained English, French, Spanish, and German interface with persisted language selection and locale-aware formatting.
- Versioned configuration and backup formats, atomic persistence, encrypted integration credentials and tested backup/restore tooling.
- Multi-architecture container images with health checks, SBOM, provenance and immutable commit-SHA rollback tags.
Earlier development remains available in Git history; this changelog does not invent releases that were never deliberately published.
[Unreleased]: https://github.com/lucas-lepajollec/nasdash/compare/v0.3.8...HEAD
[0.3.8]: https://github.com/lucas-lepajollec/nasdash/compare/v0.3.7...v0.3.8
[0.3.7]: https://github.com/lucas-lepajollec/nasdash/compare/v0.3.6...v0.3.7
[0.3.6]: https://github.com/lucas-lepajollec/nasdash/compare/v0.3.5...v0.3.6
[0.3.5]: https://github.com/lucas-lepajollec/nasdash/compare/v0.3.4...v0.3.5
[0.3.4]: https://github.com/lucas-lepajollec/nasdash/compare/v0.3.3...v0.3.4
[0.3.3]: https://github.com/lucas-lepajollec/nasdash/compare/v0.3.2...v0.3.3
[0.3.2]: https://github.com/lucas-lepajollec/nasdash/compare/v0.3.1...v0.3.2
[0.3.1]: https://github.com/lucas-lepajollec/nasdash/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/lucas-lepajollec/nasdash/compare/v0.2.5...v0.3.0
[0.2.5]: https://github.com/lucas-lepajollec/nasdash/compare/v0.2.4...v0.2.5
[0.2.4]: https://github.com/lucas-lepajollec/nasdash/compare/v0.2.3...v0.2.4
[0.2.3]: https://github.com/lucas-lepajollec/nasdash/compare/v0.2.2...v0.2.3
[0.2.2]: https://github.com/lucas-lepajollec/nasdash/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/lucas-lepajollec/nasdash/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/lucas-lepajollec/nasdash/compare/v0.1.4...v0.2.0
[0.1.4]: https://github.com/lucas-lepajollec/nasdash/compare/v0.1.3...v0.1.4
[0.1.3]: https://github.com/lucas-lepajollec/nasdash/compare/v0.1.2...v0.1.3
[0.1.2]: https://github.com/lucas-lepajollec/nasdash/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/lucas-lepajollec/nasdash/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/lucas-lepajollec/nasdash/releases/tag/v0.1.0