SSR framework for Svelte 5 + Bun with islands-based selective hydration
On this page
Production builds
mochi-framework build writes a self-contained build to .mochi/ (see the CLI reference). This page covers what that build gives you once it is deployed: it relocates cleanly from where you built it to where you run it, it can be hosted under a sub-path, and its image cache can survive container restarts. For where to run it, see Deployment options; to containerize it, see Building a Dockerfile.
Relocatable builds
A manifest holds no absolute paths — artifacts are written relative to the out-dir, sources relative to the project root — so you can build in one place and run in another. Build in a CI stage, copy .mochi/ into the final image, and point the runtime at wherever it landed:
Mochi.serve({ outDir: './.mochi' }); // default — or wherever you copied itPaths resolve against the manifest’s own directory, so pointing manifest at a relocated build works on its own:
Mochi.serve({ manifest: '/srv/app/build/manifest.json' });Sub-path and static hosting
Mochi writes absolute URLs for everything it owns: /_mochi/client/…, /_mochi/css/…, the island component-url, and the import specifiers inside the client chunks. To host under a sub-path such as https://example.com/my-app/, bake the prefix in at build time:
mochi-framework build --asset-prefix /my-app/_mochiThe value lands in manifest.json and every emitted URL carries it. Mochi.serve({ assetPrefix }) sets the same thing for on-demand compilation, but once a manifest exists its value wins and a differing serve() value only logs a warning.
The same prefix is what makes a hand-rolled static export work: copy .mochi/svelte-client to <host>/my-app/_mochi/client and .mochi/svelte-css to <host>/my-app/_mochi/css, save each prerendered page, and nothing needs rewriting.
Rewriting URLs yourself
Since: 0.10.0 (not released yet): Before 0.10.0 a relative component-url resolved against the island loader module (/_mochi/client/), not the page.
If you post-process the HTML into page-relative URLs instead, treat component-url like any other attribute: it resolves against the page, so ../_mochi/client/… on /my-app/writing/ loads from /my-app/_mochi/client/, the same place a <link href="../_mochi/css/…"> on that page does.
Persistent image cache
Mochi’s image cache is written to disk under cacheDir (default ./.mochi/image-cache). In a container that directory is recreated on every restart, so each redeploy starts with a cold cache and re-fetches and re-transforms every image. To keep the transformed bytes across restarts, point cacheDir at a dedicated path and mount a volume there:
Mochi.serve({
image: { cacheDir: process.env.MOCHI_IMAGE_CACHE_DIR /* , sizes: … */ },
});services:
site:
image: your-app
environment:
MOCHI_IMAGE_CACHE_DIR: /data/image-cache
volumes:
- image-cache:/data/image-cache
volumes:
image-cache:A plain docker run -v image-cache:/data/image-cache your-app mounts the same volume. Keep the mount off ./.mochi — its build cache is rebuilt on every boot and must not persist. If the container runs as a non-root user, pre-create the directory owned by that user in your Dockerfile so the mounted volume is writable.