🍡 mochi
SSR framework for Svelte 5 + Bun with islands-based selective hydration
Passing props to islands
Any component marked with mochi:hydrate, mochi:hydrate:visible, or mochi:defer becomes an island, and its props have to cross the SSR → client boundary. Mochi serializes them with devalue, which preserves richer types than JSON.stringify.
<!-- Parent runs only on the server -->
<script>
const user = { name: 'Ada', id: 42 };
const visitedAt = new Date();
const tags = new Set(['svelte', 'bun']);
</script>
<!-- Child is the island; props travel via devalue -->
<UserCard mochi:hydrate {user} {visitedAt} {tags} />How it works
- During SSR,
devalue.stringifyserializes the props object. - The serialized string is placed on the
<mochi-hydratable-island>custom element as apropsattribute. When multiple islands on the same page share an identical payload, it’s hoisted into a shared<script type="application/json">block and each island gets aprops-refpointer instead. - In the browser, the custom element reads the attribute (or the referenced script block) and runs
devalue.parseon it. - The reconstructed props are passed to Svelte’s
hydrate(...), and the island takes over.
For mochi:defer server islands the flow is similar, except props are HMAC-signed and passed as a query parameter to a per-island endpoint — see Server islands.
Supported types
- Plain objects and arrays
- Primitives: strings, numbers, booleans,
null Date,RegExp,Map,Set,URL,URLSearchParamsBigInt, typed arrays (Uint8Array, etc.)undefined,Infinity,NaN,-0- Repeated and cyclic references (identity is preserved)
Not supported
- Functions
- Class instances (the constructor is lost — only own enumerable properties survive)
Symbol
If you need any of these, compute them after hydration or pass a plain-data representation that the island can rebuild from.