## Demo: client-only ### ClientOnly.svelte ```svelte
Mounting in the browser…

The animation runs on requestAnimationFrame with a live fps counter, scaled to window.devicePixelRatio — browser APIs read at the top of the component's script. This paragraph, by contrast, sits outside the island — it ships with the SSR HTML and doesn't move when the component mounts.

Scroll down — the island below is marked mochi:clientOnly:visible, so it stays a fallback until it reaches the viewport, then mounts in the browser.

Lazy client-only with mochi:clientOnly:visible

Mounts when scrolled into view…

Same browser-only mount as above, but deferred: an IntersectionObserver holds off the mount() until the placeholder enters the viewport, and the component's bundle and CSS load only then. Open the console to see it mount as you scroll.

``` ### BrowserCanvas.svelte ```svelte ``` ### MountClock.svelte ```svelte
{label}: mounted on scroll {seconds}s ago.
``` ### routes.ts ```ts import { Mochi } from 'mochi-framework'; import type { MochiRouteValue } from 'mochi-framework'; export const routes: Record = { '/demos/client-only': Mochi.page('./src/demos/client-only/ClientOnly.svelte'), }; ``` ### index.ts ```ts import { Mochi, logger } from 'mochi-framework'; import { routes } from './routes'; await Mochi.serve({ port: 3333, development: process.env.MODE === 'development', routes, }); logger.info('Server running at http://localhost:3333'); ```