🍡 mochi

SSR framework for Svelte 5 + Bun with islands-based selective hydration

Why Bun?

Mochi targets the Bun runtime, not Node. Bun ships a bundler, transpiler, file API, HTTP and WebSocket server, glob, hashing and compression in its standard library — features that on Node typically arrive as esbuild/vite + express + node:fs + glob + zlib + crypto. Building on top of those built-ins keeps the framework small (there are no transitive bundler or server dependencies), starts fast (no separate build step in dev), and means there is exactly one thing to install before you can bun run dev.

What Mochi uses Bun for

Bun APIWhere it shows up in the framework
Bun.serve()The HTTP and WebSocket server backing every route declared with Mochi.serve().
Bun.build() + Bun.TranspilerBundles client-side islands and transpiles .ts / .svelte on demand during SSR.
Bun.file() / Bun.write()Reads the HTML shell and component sources, writes built assets, serves static files.
Bun.GlobDiscovers routes, docs, and raw CSS files without an extra glob package.
Bun.hashGenerates content-hashed filenames for cache-busted bundles and CSS.
Bun.gzipSync / Bun.deflateSyncCompresses HTTP responses, and packs signed server-island prop payloads into URLs.
Bun.resolveSyncResolves npm modules (devalue, mitt) injected into generated client code.
Native .ts execution + auto .envRun sources directly with bun run — no ts-node, no dotenv.

What this means for your app

When you write app code on top of Mochi, prefer Bun’s built-ins over their Node equivalents:

  • Use Bun.serve / bun:sqlite / Bun.file instead of express / better-sqlite3 / node:fs.
  • Don’t add dotenv — Bun loads .env automatically.
  • Run .ts files directly with bun run — no separate transpile step.

The tradeoff

Mochi will not run on plain Node. That is deliberate: the framework’s surface area stays small precisely because the runtime does the heavy lifting.