## Demo: runed
### Runed.svelte
```svelte
Runed needs no special setup — it's a plain Svelte 5 runes library, so you install it and import from
runed. In Mochi it bundles straight into whichever island imports it.
Then import a utility and use it like any rune — e.g. the Debounced value driving the first card:
Explore the full toolkit at runed.dev .
Reactivity & timing
Debounced, Throttled, Previous, and watch — one input, four derived views.
Elements & observers
ElementSize + useResizeObserver, IsInViewport, activeElement, and IsFocusWithin.
```
### Reactivity.svelte
```svelte
Type here
live {text || '—'}
Debounced (400ms) {debounced.current || '—'}
Throttled (400ms) {throttled.current || '—'}
Previous {previous.current ?? '—'}
watch() change log
{#if log.length === 0}
Waiting for the debounced value to settle…
{:else}
{#each log as entry (entry.id)}
{entry.text}
{/each}
{/if}
```
### StateCard.svelte
```svelte
StateHistory
undo / redo any $state
count--}>−
{count}
count++}>+
Undo
Redo
{history.log.length} snapshot{history.log.length === 1 ? '' : 's'} recorded
PersistedState
localStorage · survives reload · syncs tabs
persisted.current--}>−
{persisted.current}
persisted.current++}>+
Reload the page — the value sticks. Open a second tab to watch it sync.
IsMounted
false during SSR, true after hydration
{#if isMounted.current}
mounted (client)
{:else}
not mounted (server)
{/if}
```
### Elements.svelte
```svelte
ElementSize + useResizeObserver
drag the corner of the box
{Math.round(size.width)} × {Math.round(size.height)}
{resizes} resize event{resizes === 1 ? '' : 's'}
IsInViewport
scroll the target in and out
{#if inViewport.current}
visible
{:else}
hidden
{/if}
activeElement + IsFocusWithin
tab through the fields
focused: {activeElement.current?.localName ?? 'none'}
{#if focusWithin.current}
focus within
{/if}
```
### Sensors.svelte
```svelte
PressedKeys
hold any keys — try Ctrl + Shift
{#if keys.all.length === 0}
No keys pressed
{:else}
{#each keys.all as key (key)}
{key}
{/each}
{/if}
IsIdle
stop moving the mouse for 2s
{#if idle.current}
idle
{:else}
active
{/if}
Last active: {new Date(idle.lastActive).toLocaleTimeString()}
```
### AsyncFsm.svelte
```svelte
FiniteStateMachine
_enter hooks auto-advance via .debounce()
{light.current}
light.send('next')}>Next →
{auto ? 'Pause' : 'Resume'}
resource
debounced fetch with cancellation
{#if search.loading}
Loading…
{:else if search.error}
Error: {search.error.message}
{:else}
{search.current?.matches.length ?? 0} match{search.current?.matches.length === 1 ? '' : 'es'}
{/if}
{#each search.current?.matches ?? [] as fruit (fruit)}
{fruit}
{/each}
```
### routes.ts
```ts
import { Mochi, getRequestContext } from 'mochi-framework';
import type { MochiRouteValue } from 'mochi-framework';
const FRUITS = ['apple', 'apricot', 'banana', 'blueberry', 'cherry', 'grape', 'lemon', 'mango', 'orange', 'peach', 'pear', 'plum'];
export const routes: Record = {
'/demos/runed': Mochi.page('./src/demos/runed/Runed.svelte'),
'/api/runed/search': Mochi.api(() => {
const { url } = getRequestContext();
const q = (url.searchParams.get('q') ?? '').toLowerCase();
const matches = q ? FRUITS.filter((f) => f.includes(q)) : FRUITS;
return Response.json({ matches });
}),
};
```
### 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');
```