--- description: Frontends build with vp build in Vite app mode, keeping the exact output paths the Rust backend and HTML expect; emptyOutDir false when outDir holds committed files --- `deno bundle` was replaced by `vp build` in **Vite app mode** (not `build.lib`). Behavior must not change, so the output keeps the file names and locations the backend serves and the HTML references. Typical shape for the Rust-backed frontends (home, eximium, stockvibe, memona-home), where `frontend/` builds into `backend/static`: ```ts build: { outDir: "../backend/static", emptyOutDir: false, // the folder holds committed files (index.html, ...) rollupOptions: { input: { bundle: "src/index.ts" }, output: { entryFileNames: "js/[name].js" }, // -> js/bundle.js }, }, ``` - **Fixed names, no hashes:** set `entryFileNames` (and `assetFileNames` where assets are emitted) explicitly. Vite's hashed defaults would 404, since Rust and the templates request `js/bundle.js` and `css/theme.css`. - **`emptyOutDir: false` whenever `outDir` is outside the Vite root or holds committed files.** Never let it default to true there: it would wipe them. - Output stays gitignored, so `.gitignore`, `.containerignore`, and the Rust side need no edits; home's startup check for `js/bundle.js` and `css/theme.css` keeps passing. - **CSS is never imported from TS** (no `import "./theme.css"`); the HTML links the stylesheet. How the CSS file is produced is per repo; read the repo's `vite.config.ts` before changing it. - Copy whole `js/` and `css/` directories in Containerfiles, not single files, so code-split chunks ship too ([[app-containers-and-ci]]). - Where a repo serves an `index.html` entry (brain's dashboard), use plain app mode with `index.html` as input, `base` set to the mount path, and `outDir: "dist"` with the default `emptyOutDir`. - `vp dev` must work too, and the decorators plugin must cover build, dev, and test ([[decorators-standard-accessor]]). Check the repo's own migration PR for its final values before editing; these are the conventions it followed, not a config to paste.