--- description: Containerfiles build the frontend in a node:24-alpine stage with npm ci and vp build; CI uses setup-vp and runs vp check, vp build, vp test (plus lit-check) --- ## Containerfiles - The frontend build stage is `docker.io/library/node:24-alpine`, replacing `denoland/deno:alpine`. Vite+ publishes `linux-x64-musl` binaries, so Alpine works. (`ghcr.io/voidzero-dev/vite-plus` is a glibc alternative that would need a pinned digest; not used.) - The stage copies `package.json` and `package-lock.json` first, runs `npm ci`, then copies the sources and configs and runs `npx vp build`. - The runtime stage copies the built `js/` and `css/` directories (not single files) from the node stage. - No Deno binary, `deno install`, or `deno task` remains in any stage. ```dockerfile FROM docker.io/library/node:24-alpine AS frontend WORKDIR /src/frontend COPY frontend/package.json frontend/package-lock.json ./ RUN npm ci COPY frontend/ ./ RUN npx vp build ``` ## CI - GitHub repos (temeddix): `.github/workflows`. Capsulizers repos (Gitea): `.gitea/workflows`. Don't move a repo's CI between hosts. - Install with `voidzero-dev/setup-vp`, then run `vp check`, `vp build`, and `vp test`; Lit repos also run `npm run lit-check` ([[lit-analyzer-ts6]]). - Repos that ran CI on a self-hosted runner keep it. - Until `@cunarist/eslint-plugin-*` are on npm, `npm ci` fails in CI. That is expected and stated in the PR; run `npm install` once they are published and commit the refreshed lockfile.