🍡 mochi
SSR framework for Svelte 5 + Bun with islands-based selective hydration
Environment constants
Import build-time constants from the virtual mochi-framework module:
import { isServer, isBrowser, isDev } from 'mochi-framework';| Constant | Server | Browser | Description |
|---|---|---|---|
isServer | true | false | True during server-side rendering |
isBrowser | false | true | True in the browser |
isDev | varies | varies | True when development: true in config |
Auto-injected props
The preprocessor injects two props on every component used with mochi:hydrate, mochi:hydrate:visible, or mochi:defer mochi:hydrate:
| Prop | Type | Description |
|---|---|---|
islandId | string | Stable id matching the wrapping <mochi-hydratable-island island-id> attribute. |
isHydratable | true \| undefined | true for hydratable invocations; absent on plain SSR-only invocations. |
Use isHydratable to branch SSR-only behavior off the same call site that hydrates client-side — e.g. peek the request’s form snapshot only when the client won’t take over:
<script>
import { isServer, getRequestContext } from 'mochi-framework';
let { isHydratable } = $props<{ isHydratable?: boolean }>();
// Hydrated: the client will fill state via the enhance attachment. Plain SSR: read
// the post-submit form snapshot so the rendered HTML reflects the last
// action result.
const initial = isHydratable || !isServer ? null : peekForm();
function peekForm() {
const f = getRequestContext().form;
return f && f.ok && typeof f.data.value === 'number' ? f.data.value : null;
}
</script>See the Forms demo for a side-by-side comparison of hydrated and SSR-only render paths.