Board scaling: no sideways scrolling - Revert the pannable narrow canvas. The canvas fits the viewport again and `.viewport` goes back to `overflow: clip`, so a board can never widen the document or scroll horizontally. - Fix the unreadable-narrow-board regression at the real cause instead: cap the inverse UI compensation at 2x (50% canvas scale). Down to 50% text and controls keep their physical size; below it the board zooms out as a whole, so a 200x200 logical tile hosts at most 28px logical text rather than 96px and content stops overlapping its neighbours. Touch editing - Add `touch-action: none` to `.board-grid-entry`, the dnd-kit draggable and its own drag handle. The 200ms touch activation delay is useless if the browser has already handed the gesture to page panning and emitted `pointercancel`. Only edit mode renders this element. Custom widgets - Memoize the merged `data`/`status`/`options` passed to `CustomJsxRenderer`. They were rebuilt every render, so the compiled-template memo never hit and the new reference-identity boundary key changed on every render, resetting the error boundary and forcing an extra reconciliation of the widget subtree. - Keep the cache key when the shared Redis cache is unavailable so the process-local cache still absorbs polling instead of sending every widget refresh upstream. - Reclaim the shared cache's LRU/size/byte bookkeeping for TTL-expired entries and touch the LRU in the same script, so expired ghosts stop consuming the 64 MiB budget and a read costs one round trip instead of two. Forwarded IP - Restore `ipAddressFromHeaders` to the full forwarding chain and add `trustedIpAddressFromHeaders` for the last hop. Repointing the shared helper had collapsed MCP failed-auth rate limiting into a single bucket for every client behind a reverse proxy and replaced the client IP with the proxy IP in API-key auth logs. Runtime and restore - Make the new /appdata ownership migration best-effort. Under `set -e` a mount that rejects chown (CIFS/SMB, fixed-uid NFS) turned into a container that refuses to start, and /appdata was never chowned before. - Report malformed metadata.json as such instead of blaming the archive.
Homarr web application
This workspace contains Homarr's Next.js application. It consumes the shared API, authentication, database, board, widget, translation, and UI packages from this monorepo.
Run commands from the repository root:
pnpm install --frozen-lockfile
cp .env.example .env
Keep infrastructure running in the first terminal:
pnpm docker:dev
Apply migrations and start the application in a second terminal:
pnpm db:migration:sqlite:run
pnpm dev
The app listens on http://127.0.0.1:3000. Configure an absolute writable DB_URL, AUTH_SECRET, and
SECRET_ENCRYPTION_KEY in .env before first startup.
To test Custom Widgets against a local Community Workshop, start PocketBase and the docs in separate terminals:
pnpm docker:workshop
WORKSHOP_API_URL=http://127.0.0.1:8090 pnpm dev:docs
Then set:
HOMARR_WEBSITE_URL=http://127.0.0.1:3003
WORKSHOP_API_URL=http://127.0.0.1:8090
WORKSHOP_WEB_URL=http://127.0.0.1:3003/workshop
Server-rendered runtime configuration exposes those URLs to the browser, so changing a production container's environment does not require rebuilding the Next.js bundle.
See apps/docs/docs/advanced/development/getting-started.mdx
for the full contributor setup.