## Demo: rate-limit ### RateLimit.svelte ```svelte
Requests used
{used} of {limit}
Window resets in
{resetIn}s

Reload this page. This route allows {limit} requests per minute per IP — after the {limit}th reload you'll get a 429 error page. Wait for the window to reset, then reload to get back in.

``` ### routes.ts ```ts import { mkdirSync } from 'node:fs'; import { Mochi, getRequestContext, sqliteStore } from 'mochi-framework'; import type { MochiRouteValue } from 'mochi-framework'; // Persist rate-limit counters to SQLite so they survive restarts — the default // store is in-memory (and sqliteStore() without a path is too). bun:sqlite won't // create the parent dir, and ./db is gitignored. mkdirSync('./db', { recursive: true }); const store = sqliteStore({ path: './db/rate-limit.sqlite' }); export const routes: Record = { '/demos/rate-limit': Mochi.page('./src/demos/rate-limit/RateLimit.svelte', { rateLimit: { limit: 5, window: '1m', store }, serverProps: () => { const rateLimit = getRequestContext().rateLimit; return { used: rateLimit ? rateLimit.limit - rateLimit.remaining : 1, limit: rateLimit?.limit ?? 5, resetIn: rateLimit?.resetIn ?? 60, }; }, }), }; ``` ### 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'); ```