🍡 mochi

🍡 mochi

An experimental SSR framework for Svelte 5 and Bun.

Render everything on the server; ship JavaScript only where it earns its place.

What is Mochi?

Mochi is a lightweight, server-first framework for Svelte 5 on Bun. Mochi websites render server-side on every request and ship as plain HTML. Components only ship JavaScript when you explicitly mark them as islands.

Quick start

Requires Bun >= 1.3.14. Why Bun? Supports macOS Supports Windows Supports Linux

Documentation

Setup, hydration modes, routes, hooks, forms, cookies — everything in one place.

Start reading →

Demos

Each demo lives on its own page. Pick one below to see the feature in isolation.

Basic

The simplest possible Mochi page — pure server-rendered Svelte. The same component rendered five ways — eager, lazy, visible, rootMargin-tuned, and deferred server island. Drop <ViewTransitions /> into a shared layout to animate full-page navigations with zero JavaScript. Bring your own @keyframes to <ViewTransitions /> via custom={{ in, out }} — here, a funky 3D spin. Two separate islands sharing the same reactive $state. Components marked mochi:defer render server-side on demand after the initial page is delivered. How props travel from a server-rendered parent into a hydrated island — Date, Map, Set, BigInt, URL, typed arrays, and even cyclic refs survive devalue’s round-trip. Components marked mochi:clientOnly skip SSR entirely and mount in the browser — a fallback snippet fills in until then. Islands marked mochi:hydrate:visible hydrate and load their CSS only when scrolled into view. Server islands marked mochi:defer:visible only fetch when the wrapper scrolls into view. Ship fonts via @fontsource packages or standalone .woff2 files — automatically bundled and linked from the page head. A .md file compiled through mdsvex and rendered as a Svelte component, with an embedded <script> block. A five-level recursive tree — hydrating the root carries the whole subtree in one island. Islands inside islands — a mochi:defer server island wrapping mochi:hydrate components, and a server island nesting both a deferred and a deferred-hydrated server island. A chain of mochi:defer server islands nested four levels deep — each fetches the next on demand, and the prebuild precompiles the whole chain. Nine islands, three unique payloads — each set serialized once and referenced via props-ref. Svelte's native $props.id() inside islands — SSR-consistent, unique per instance, namespaced in server islands. HTML entities in a static island prop (label="Tom &amp; Jerry") decode to their characters — identical on the server and after hydration.

Data & serialization

Define serverProps on Mochi.page() to pass fresh data into a Svelte page on every request. Server-side fetch from PokéAPI cached via MochiCache and rendered at request time. Compute a value once on the server with hydratable(); the hydrated island reads it from <head> instead of re-running the async work. Read and write cookies on the server and the client through one MochiCookieJar API. One import for the current URL — reads from the request on the server, window.location on the client. Subscribe to MochiCache lifecycle events through mochiEvents and log them to the server console. The <Image> component — named sizes, ThumbHash blur-up placeholders, a gallery, and island usage. It only mints an encrypted URL; the endpoint does the work. Clear a cached image on demand with invalidateImage() — hard-evict the shared original and watch every named size re-fetch in lockstep. Declare resize / rotate / flip / modulate / format transforms once as named sizes; getImageUrl mints a deferred URL and getImage runs one inline for bytes + metadata. Subscribe to image:store / image:delete on mochiEvents to mirror the <Image> cache to durable storage like S3. Every request gets a UUID v7 — read it server-side via getRequestContext().requestId; the same id rides every lifecycle event for correlation. A page that sets Vary: Cookie on its response — useful for testing cookie-partitioned cache keys.

Endpoints & realtime

Forms

Errors

Demo sites