Now ignored via .gitignore; the workspace-root pnpm-lock.yaml is the
single source of truth. These files were never tracked in git and
caused --frozen-lockfile to reject installs in the docker containers.
Mounting only ./backend and ./frontend into /app made pnpm look for a
per-package lockfile (stale) and miss the workspace-root one entirely,
so --frozen-lockfile failed and root pnpm.onlyBuiltDependencies didn't
apply. Mount the whole repo at /repo, install with --filter from root,
and use the canonical workspace lockfile. Drop the per-package
onlyBuiltDependencies overrides — pnpm warns they're ignored outside
the workspace root.
Pin node:22-bookworm: node:lts now resolves to Node 24, for which
isolated-vm@5.0.3 has no prebuild and won't compile (V8 headers
require C++20).
Gitignore stray per-package lockfiles so they don't drift again.
Per-package onlyBuiltDependencies so pnpm 10 actually compiles native
modules (isolated-vm, argon2, sqlite3, sharp) — root workspace config
isn't visible when compose mounts a single package into /app.
Frontend container now installs with devDeps (so tsc/vite exist),
prunes after build, and gains a `start` script that serves the build
via vite preview on 0.0.0.0:3000.
Drop obsolete compose `version` key.
Split the 316-line vendors index into VendorToolbar, VendorGrid,
VendorList, and PerPageSelector under components/vendors/. Page now
owns only search-param state and query orchestration.
Replace generic Error throws in lib/directus.ts with a DirectusError
class carrying status, statusText, collection, url, and parsed body.
Surface useLocalStorage read/write failures via console.warn instead
of swallowing them.