[
  {
    "file": "pages/api-components.md",
    "title": "Component API",
    "section-id": "api-reference",
    "keywords": "defineComponent, ref, computed, watch, component API, reactive",
    "description": "Complete reference for the Velox component API \u2014 defineComponent, ref, computed, and watch",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Component API\n\nThis page documents the core component primitives exported from `velox/client`.\n\n## `signal(initialValue)`\n\nCreates a reactive signal \u2014 a value container that triggers DOM updates when changed.\n\n```typescript\nimport { signal } from 'velox/client';\n\nconst count = signal(0);\ncount.value;        // read: 0\ncount.value = 5;    // write: triggers reactive updates\ncount.peek();       // read without tracking (no reactive subscription)\n```\n\n### Type Signature\n\n```typescript\nfunction signal<T>(initialValue: T): Signal<T>;\n\ninterface Signal<T> {\n  value: T;\n  peek(): T;\n  subscribe(listener: (value: T) => void): () => void;\n}\n```\n\n## `computed(fn)`\n\nCreates a derived reactive value. Re-evaluates lazily when accessed and a dependency has changed.\n\n```typescript\nimport { signal, computed } from 'velox/client';\n\nconst price = signal(100);\nconst taxRate = signal(0.2);\nconst total = computed(() => price.value * (1 + taxRate.value));\n\ntotal.value; // 120\nprice.value = 200;\ntotal.value; // 240\n```\n\nComputed signals are read-only \u2014 attempting to set `.value` throws.\n\n## `effect(fn)`\n\nRegisters a reactive side effect. Runs immediately, then again whenever its signal dependencies change.\n\n```typescript\nimport { signal, effect } from 'velox/client';\n\nconst query = signal('');\n\nconst dispose = effect(() => {\n  console.log('query =', query.value);\n  // runs now, then on every change to query.value\n});\n\n// Clean up manually (effects inside components clean up on unmount):\ndispose();\n```\n\nReturn a cleanup function from the effect to run before the next execution or on disposal:\n\n```typescript\neffect(() => {\n  const controller = new AbortController();\n  fetchData(query.value, controller.signal);\n  return () => controller.abort();\n});\n```\n\n## `batch(fn)`\n\nGroups multiple signal writes into a single reactive update pass:\n\n```typescript\nimport { batch } from 'velox/client';\n\nbatch(() => {\n  a.value = 1;\n  b.value = 2;\n  c.value = 3;\n  // Only one round of re-renders happens\n});\n```\n\n## `untrack(fn)`\n\nExecute a function without tracking its signal reads as dependencies:\n\n```typescript\nimport { signal, effect, untrack } from 'velox/client';\n\nconst a = signal(1);\nconst b = signal(2);\n\neffect(() => {\n  // Only subscribes to `a`, not `b`\n  const result = a.value + untrack(() => b.value);\n  console.log(result);\n});\n```\n\n## Lifecycle Hooks\n\nLifecycle hooks must be called synchronously during component initialisation (similar to React rules of hooks, but without the runtime check overhead).\n\n### `onMount(fn)`\n\nCalled after the component's DOM is inserted into the document:\n\n```typescript\nimport { onMount } from 'velox/client';\n\nonMount(() => {\n  // safe to access DOM, start timers, etc.\n  const input = document.querySelector('#my-input') as HTMLInputElement;\n  input.focus();\n});\n```\n\n### `onCleanup(fn)`\n\nCalled before the component unmounts, or before an effect runs again. Use to cancel subscriptions, abort requests, and clear timers:\n\n```typescript\nimport { onMount, onCleanup } from 'velox/client';\n\nonMount(() => {\n  const timer = setInterval(tick, 1000);\n  onCleanup(() => clearInterval(timer));\n});\n```\n\n### `onDestroy(fn)`\n\nLike `onCleanup`, but only runs when the component is permanently destroyed (not before re-renders):\n\n```typescript\nimport { onDestroy } from 'velox/client';\n\nonDestroy(() => {\n  analytics.trackLeave(route);\n});\n```\n\n## `createContext` / `useContext`\n\nCreate a context for dependency injection without prop drilling:\n\n```typescript\nimport { createContext, useContext } from 'velox/client';\n\n// Create context with a default value\nconst ThemeContext = createContext<'light' | 'dark'>('light');\n\n// Provide a value to a subtree\n<ThemeContext.Provider value=\"dark\">\n  <App />\n</ThemeContext.Provider>\n\n// Consume in any descendant\nfunction Button() {\n  const theme = useContext(ThemeContext);\n  return <button class={`btn--${theme}`}>Click</button>;\n}\n```\n\n## `ref()`\n\nCreate a DOM element reference:\n\n```typescript\nimport { ref, onMount } from 'velox/client';\n\nexport default function TextInput() {\n  const inputRef = ref<HTMLInputElement>();\n\n  onMount(() => {\n    inputRef.current?.focus();\n  });\n\n  return <input ref={inputRef} type=\"text\" />;\n}\n```\n\n## `defineComponent(options)`\n\nThe explicit component definition API \u2014 useful when you need named components for debugging or when defining components programmatically:\n\n```typescript\nimport { defineComponent, signal } from 'velox/client';\n\nconst Counter = defineComponent({\n  name: 'Counter',\n  props: {\n    initialValue: { type: Number, default: 0 },\n    step: { type: Number, default: 1 },\n  },\n  setup(props) {\n    const count = signal(props.initialValue);\n    const increment = () => { count.value += props.step; };\n    const decrement = () => { count.value -= props.step; };\n\n    return { count, increment, decrement };\n  },\n  render({ count, increment, decrement }) {\n    return (\n      <div class=\"counter\">\n        <button onClick={decrement}>\u2212</button>\n        <span>{count"
  },
  {
    "file": "pages/api-config.md",
    "title": "Config API",
    "section-id": "api-reference",
    "keywords": "config API, velox.config.ts, defineConfig, types, TypeScript reference",
    "description": "Full TypeScript type reference for velox.config.ts and all configuration options",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Config API\n\nThis page provides the complete TypeScript type reference for `velox.config.ts`. All types are exported from the `velox` package.\n\n## `defineConfig(config)`\n\nThe primary export. Accepts a `VeloxConfig` object and returns it with full type checking:\n\n```typescript\nimport { defineConfig } from 'velox';\n\nexport default defineConfig({\n  // VeloxConfig object\n});\n```\n\nYou can also pass a function for dynamic configuration:\n\n```typescript\nexport default defineConfig(async (env) => {\n  const secrets = await loadSecrets();\n  return {\n    app: {\n      name: 'My App',\n      baseUrl: secrets.BASE_URL,\n    },\n  };\n});\n```\n\n## `VeloxConfig`\n\n```typescript\ninterface VeloxConfig {\n  app?: AppConfig;\n  server?: ServerConfig;\n  build?: BuildConfig;\n  routes?: RoutesConfig;\n  assets?: AssetsConfig;\n  css?: CSSConfig;\n  i18n?: I18nConfig;\n  middleware?: MiddlewareConfig[];\n  plugins?: VeloxPlugin[];\n  experimental?: ExperimentalConfig;\n  errorHandler?: ErrorHandler;\n}\n```\n\n## `AppConfig`\n\n```typescript\ninterface AppConfig {\n  /** Application display name. Used in page titles and error pages. */\n  name: string;\n\n  /** Canonical base URL. Required in production. Example: 'https://example.com' */\n  baseUrl: string;\n\n  /** Default locale for i18n. Default: 'en' */\n  defaultLocale?: string;\n\n  /** Whether to append trailing slashes to all routes. Default: false */\n  trailingSlash?: boolean;\n\n  /** Custom 404 page route. Default: '_error' */\n  notFoundPage?: string;\n}\n```\n\n## `ServerConfig`\n\n```typescript\ninterface ServerConfig {\n  /** TCP port. Default: 3700 */\n  port?: number;\n\n  /** Bind hostname. Default: 'localhost' */\n  host?: string;\n\n  /** HTTPS configuration for the development server */\n  https?: {\n    cert: string;   // path to PEM certificate\n    key: string;    // path to PEM private key\n  };\n\n  /** CORS policy */\n  cors?: {\n    origin: string | string[] | ((origin: string) => boolean);\n    credentials?: boolean;\n    methods?: string[];\n    allowedHeaders?: string[];\n    exposedHeaders?: string[];\n    maxAge?: number;\n  };\n\n  /** Compression. Default: true in production */\n  compress?: boolean;\n\n  /** Trust proxy headers (X-Forwarded-For, etc.). Default: false */\n  trustProxy?: boolean | number;\n}\n```\n\n## `BuildConfig`\n\n```typescript\ninterface BuildConfig {\n  /**\n   * Deployment target.\n   * - 'node': Outputs a Node.js server (default)\n   * - 'edge': Outputs a Web-API-compatible edge bundle\n   * - 'static': Full static export \u2014 no server required\n   */\n  target: 'node' | 'edge' | 'static';\n\n  /** Output directory. Default: '.velox/output' */\n  outDir?: string;\n\n  /** Source map generation. Default: false in production */\n  sourcemap?: boolean | 'external' | 'inline';\n\n  /** Minify output. Default: true in production */\n  minify?: boolean;\n\n  /** Enable code splitting. Default: true */\n  splitting?: boolean;\n\n  /** Emit a bundle analysis HTML report */\n  analyze?: boolean;\n\n  /**\n   * Routes to explicitly pre-render as static HTML.\n   * Supports globs. e.g. ['/blog/*', '/about']\n   */\n  prerender?: string[];\n\n  /** External dependencies (not bundled). */\n  external?: string[];\n\n  /** Environment variables to inline into the client bundle */\n  define?: Record<string, string>;\n}\n```\n\n## `RoutesConfig`\n\n```typescript\ninterface RoutesConfig {\n  /** Routes directory relative to project root. Default: 'routes' */\n  dir?: string;\n\n  /** File extensions treated as routes. Default: ['.velox', '.tsx'] */\n  extensions?: string[];\n\n  /** Glob patterns to exclude from routing */\n  exclude?: string[];\n\n  /** Prefix all generated routes with this base path */\n  base?: string;\n}\n```\n\n## `AssetsConfig`\n\n```typescript\ninterface AssetsConfig {\n  /** Static assets directory. Default: 'public' */\n  publicDir?: string;\n\n  imageOptimisation?: {\n    enabled: boolean;\n    /** Output formats to generate. Default: ['webp'] */\n    formats?: ('webp' | 'avif' | 'jpeg' | 'png')[];\n    /** JPEG/WebP/AVIF quality 1\u2013100. Default: 80 */\n    quality?: number;\n    /** Maximum width in pixels before downscaling */\n    maxWidth?: number;\n  };\n\n  fonts?: {\n    /** Emit <link rel=\"preload\"> for fonts. Default: true */\n    preload?: boolean;\n    /** Unicode range subsets. Example: ['latin', 'latin-ext'] */\n    subsets?: string[];\n  };\n}\n```\n\n## `I18nConfig`\n\n```typescript\ninterface I18nConfig {\n  /** Supported locale codes. Example: ['en', 'fr', 'de'] */\n  locales: string[];\n\n  /** Default locale. Default: 'en' */\n  defaultLocale: string;\n\n  /** Strategy for locale in URL. Default: 'prefix-except-default' */\n  routing?: 'prefix' | 'prefix-except-default' | 'domain';\n\n  /** Domain mapping for 'domain' routing strategy */\n  domains?: Record<string, string>;\n\n  /** Path to translation files. Default: 'messages' */\n  messagesDir?: string;\n}\n```\n\n## `MiddlewareConfig`\n\n```typescript\ninterface MiddlewareConfig {\n  /** Route path glob to match. Use '*' for global middleware */\n  path: string;\n\n  /** Path to the middleware module (relative to project root"
  },
  {
    "file": "pages/api-hooks.md",
    "title": "Hooks API",
    "section-id": "api-reference",
    "keywords": "hooks, useRequest, useSession, useCookies, useEnv, server hooks",
    "description": "Reference for Velox server-side hooks \u2014 useRequest, useSession, useCookies, and useEnv",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Hooks API\n\nVelox provides server-side hooks for accessing request context, sessions, cookies, and environment variables within route server blocks and middleware. These hooks are only available in server-side contexts.\n\n## `useRequest()`\n\nReturns the current `VeloxRequest` object:\n\n```typescript\nimport { useRequest } from 'velox/server';\n\nconst request = useRequest();\n\nconst method = request.method;\nconst pathname = new URL(request.url).pathname;\nconst userAgent = request.headers.get('User-Agent');\n```\n\nThis is equivalent to the `request` variable that is automatically available in server blocks, but `useRequest()` is useful in helper functions that are called from a server block without threading `request` through manually.\n\n### Full Request Object Reference\n\n```typescript\ninterface VeloxRequest extends Request {\n  params: Record<string, string>;         // route dynamic params\n  query: URLSearchParams;                 // parsed query string\n  cookies: RequestCookies;               // parsed cookies\n  context: Map<string, unknown>;         // middleware-set values\n  ip: string | null;                      // client IP address\n  geo: GeoInfo | null;                   // geographic info (if available)\n}\n```\n\n## `useSession()`\n\nReads and writes the server-managed session. Sessions are stored server-side (in memory, Redis, or a database depending on your `session.store` configuration) and identified by a signed cookie.\n\n```typescript\nimport { useSession } from 'velox/server';\n\nconst session = await useSession<{ userId: string; role: string }>();\n\n// Read\nconst userId = session.data.userId;\nconst role = session.data.role;\n\n// Write \u2014 persists changes to the session store\nawait session.set('userId', '123');\nawait session.set('role', 'admin');\n\n// Update multiple at once\nawait session.update({ userId: '123', role: 'admin' });\n\n// Destroy the session (logout)\nawait session.destroy();\n\n// Regenerate session ID (after privilege change \u2014 prevents fixation)\nawait session.regenerate();\n```\n\n### Session Configuration\n\nConfigure the session store in `velox.config.ts`:\n\n```typescript\nimport { defineConfig } from 'velox';\nimport { RedisSessionStore } from '@velox/session-redis';\n\nexport default defineConfig({\n  session: {\n    secret: process.env.SESSION_SECRET!,\n    cookieName: 'velox.session',\n    maxAge: 60 * 60 * 24 * 7,       // 7 days\n    httpOnly: true,\n    secure: process.env.NODE_ENV === 'production',\n    sameSite: 'lax',\n    store: new RedisSessionStore({\n      url: process.env.REDIS_URL!,\n    }),\n  },\n});\n```\n\n## `useCookies()`\n\nRead and write cookies. Returns a `CookieJar` object:\n\n```typescript\nimport { useCookies } from 'velox/server';\n\nconst cookies = useCookies();\n\n// Read\nconst theme = cookies.get('theme')?.value ?? 'light';\nconst hasConsented = cookies.get('consent')?.value === 'true';\n\n// Write (adds Set-Cookie header to the response)\ncookies.set('theme', 'dark', {\n  path: '/',\n  maxAge: 365 * 24 * 60 * 60,  // 1 year\n  sameSite: 'lax',\n});\n\n// Delete\ncookies.delete('old-cookie', { path: '/' });\n```\n\n### Cookie Options\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `domain` | `string` | Cookie domain |\n| `path` | `string` | Cookie path. Default: `/` |\n| `maxAge` | `number` | Expiry in seconds |\n| `expires` | `Date` | Expiry as a date |\n| `httpOnly` | `boolean` | Prevent JavaScript access |\n| `secure` | `boolean` | HTTPS only |\n| `sameSite` | `'strict' \\| 'lax' \\| 'none'` | SameSite policy |\n\n## `useEnv(key, defaultValue?)`\n\nType-safe environment variable access:\n\n```typescript\nimport { useEnv } from 'velox/server';\n\nconst dbUrl = useEnv('DATABASE_URL');           // throws if not set\nconst port = useEnv('PORT', '3700');            // returns default if not set\nconst debug = useEnv.boolean('DEBUG', false);  // parse as boolean\nconst timeout = useEnv.number('TIMEOUT', 30);  // parse as number\n```\n\n### `useEnv` Methods\n\n| Method | Description |\n|--------|-------------|\n| `useEnv(key)` | Return string value, throw if missing |\n| `useEnv(key, default)` | Return string value or default |\n| `useEnv.boolean(key, default?)` | Parse as boolean (`'true'` / `'1'` = `true`) |\n| `useEnv.number(key, default?)` | Parse as float |\n| `useEnv.json(key, default?)` | Parse as JSON |\n| `useEnv.url(key, default?)` | Validate and return as URL string |\n\n## `useHeaders()`\n\nAccess and modify response headers from within a server block or middleware:\n\n```typescript\nimport { useHeaders } from 'velox/server';\n\nconst headers = useHeaders();\n\n// Read request headers\nconst accept = headers.request.get('Accept');\n\n// Set response headers\nheaders.response.set('Cache-Control', 'public, max-age=3600');\nheaders.response.set('X-Custom-Header', 'value');\n```\n\n## `useLocale()`\n\nReturns the current request locale (resolved by the i18n middleware):\n\n```typescript\nimport { useLocale } from 'velox/server';\n\nconst { locale, locales, defaultLocale } = useLocale();\n\n// locale: 'fr'  (current request locale)\n// locales: ['en', 'fr"
  },
  {
    "file": "pages/api-router.md",
    "title": "Router API",
    "section-id": "api-reference",
    "keywords": "router, useRouter, navigate, Link, createRouter, programmatic navigation",
    "description": "Complete API reference for the Velox router \u2014 createRouter, useRouter, navigate, and Link",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Router API\n\nThe Velox router provides both declarative and programmatic navigation. This page documents the full public API surface of `@velox/router`.\n\n## `useRouter()`\n\nThe `useRouter` hook returns the current router instance. It is available inside any client-side component:\n\n```typescript\nimport { useRouter } from 'velox/client';\n\nconst router = useRouter();\n```\n\n### Router Instance Properties\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `pathname` | `string` | Current URL pathname, e.g. `/blog/my-post` |\n| `search` | `string` | Current query string including `?`, e.g. `?page=2` |\n| `hash` | `string` | Current hash fragment including `#` |\n| `params` | `Record<string, string>` | Dynamic route parameters |\n| `query` | `URLSearchParams` | Parsed query parameters |\n| `state` | `unknown` | History state object (if provided to `navigate`) |\n\n### Router Instance Methods\n\n#### `navigate(href, options?)`\n\nPerforms client-side navigation to the given href:\n\n```typescript\nrouter.navigate('/dashboard');\n\n// With options:\nrouter.navigate('/profile/edit', {\n  replace: true,           // replace current history entry\n  state: { from: '/dashboard' }, // pass arbitrary state\n  scroll: false,           // don't scroll to top after navigation\n});\n```\n\n#### `back()` / `forward()`\n\nNavigate through the browser history stack:\n\n```typescript\nrouter.back();\nrouter.forward();\n```\n\n#### `prefetch(href)`\n\nManually prefetch a route (downloads the JS bundle and optionally data):\n\n```typescript\nrouter.prefetch('/heavy-page');\n```\n\n#### `refresh()`\n\nRe-run the current route's server block and update the page without a full navigation:\n\n```typescript\nrouter.refresh();\n```\n\n## `<Link>` Component\n\nThe `<Link>` component renders an accessible `<a>` element with client-side navigation and built-in prefetching:\n\n```tsx\nimport { Link } from 'velox/client';\n\n<Link href=\"/about\">About</Link>\n```\n\n### Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `href` | `string` | required | Destination URL |\n| `prefetch` | `'hover' \\| 'viewport' \\| false` | `'hover'` | Prefetch strategy |\n| `replace` | `boolean` | `false` | Replace history entry instead of pushing |\n| `scroll` | `boolean` | `true` | Scroll to top after navigation |\n| `state` | `unknown` | `undefined` | History state object |\n| `activeClass` | `string` | `'active'` | CSS class applied when href matches current pathname |\n| `exactActiveClass` | `string` | `'exact-active'` | CSS class applied only on exact pathname match |\n\n```tsx\n<Link\n  href=\"/blog\"\n  prefetch=\"viewport\"\n  activeClass=\"nav-link--active\"\n  exactActiveClass=\"nav-link--exact\"\n>\n  Blog\n</Link>\n```\n\n## `createRouter()`\n\nFor testing or server-side use, create a router instance manually:\n\n```typescript\nimport { createRouter } from 'velox/router';\n\nconst router = createRouter({\n  base: '/app',               // base path prefix\n  history: 'hash',            // 'browser' (default) | 'hash' | 'memory'\n  scrollRestoration: 'auto',  // 'auto' | 'manual'\n});\n```\n\n## `useParams()`\n\nAccess current route parameters in any component:\n\n```typescript\nimport { useParams } from 'velox/client';\n\nconst { slug, category } = useParams<{ slug: string; category: string }>();\n```\n\n## `useSearchParams()`\n\nRead and update the URL search parameters reactively:\n\n```typescript\nimport { useSearchParams } from 'velox/client';\n\nconst [searchParams, setSearchParams] = useSearchParams();\n\n// Read\nconst page = searchParams.get('page') ?? '1';\n\n// Update (triggers navigation without full page reload)\nsetSearchParams({ page: String(currentPage + 1) });\n\n// Merge with existing params\nsetSearchParams(prev => {\n  prev.set('sort', 'date');\n  return prev;\n});\n```\n\n## `usePathname()`\n\nReactively access the current pathname:\n\n```typescript\nimport { usePathname } from 'velox/client';\n\nconst pathname = usePathname();\n// pathname is a Signal<string>\n```\n\n## `useNavigate()`\n\nA lightweight hook that returns only the `navigate` function, without the full router object:\n\n```typescript\nimport { useNavigate } from 'velox/client';\n\nconst navigate = useNavigate();\nnavigate('/login');\n```\n\n## Navigation Events\n\nSubscribe to router lifecycle events:\n\n```typescript\nimport { useRouter } from 'velox/client';\n\nconst router = useRouter();\n\nconst unsubscribe = router.on('beforeNavigate', ({ to, from, cancel }) => {\n  if (hasUnsavedChanges && !confirm('Leave without saving?')) {\n    cancel();\n  }\n});\n\n// Clean up\nonCleanup(unsubscribe);\n```\n\nAvailable events: `beforeNavigate`, `afterNavigate`, `navigationError`.\n\n## `redirect()` (Server)\n\nUsed inside server blocks and API route handlers:\n\n```typescript\nimport { redirect } from 'velox/server';\n\n// Temporary redirect (302)\nthrow redirect('/login');\n\n// Permanent redirect (301)\nthrow redirect('/new-url', 301);\n\n// With custom headers\nthrow redirect('/dashboard', 302, {\n  'Set-Cookie': 'session=...; Path=/',\n});\n```\n\n## `notFound()` (Server)\n\nTrigger the nearest `_error.velox"
  },
  {
    "file": "pages/api-server.md",
    "title": "Server API",
    "section-id": "api-reference",
    "keywords": "server API, createServer, defineHandler, Response helpers, server-side",
    "description": "Reference for Velox server-side APIs \u2014 createServer, defineHandler, and Response helpers",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Server API\n\nThe Velox server API provides utilities for API route handlers, middleware, and server-side logic. All exports documented here come from `velox/server`.\n\n## `defineHandler(fn)`\n\nWraps an API route handler with type inference and error handling:\n\n```typescript\nimport { defineHandler } from 'velox/server';\n\nexport const GET = defineHandler(async (request) => {\n  return Response.json({ status: 'ok' });\n});\n```\n\nThe handler receives a `VeloxRequest` object (an extension of the standard `Request`) and must return a `Response` or `Promise<Response>`.\n\n### `VeloxRequest`\n\nThe enhanced request object passed to handlers:\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `url` | `string` | Full request URL |\n| `method` | `string` | HTTP method (uppercase) |\n| `headers` | `Headers` | Request headers |\n| `params` | `Record<string, string>` | URL route parameters |\n| `query` | `URLSearchParams` | Parsed query string |\n| `cookies` | `RequestCookies` | Parsed cookies |\n| `context` | `Map<string, unknown>` | Values set by middleware |\n| `json()` | `Promise<unknown>` | Parse body as JSON |\n| `text()` | `Promise<string>` | Parse body as text |\n| `formData()` | `Promise<FormData>` | Parse body as form data |\n| `arrayBuffer()` | `Promise<ArrayBuffer>` | Parse body as binary |\n\n## Response Helpers\n\nVelox exports a set of `Response` factory helpers for common responses:\n\n### `json(data, init?)`\n\nReturn a JSON response with appropriate `Content-Type` header:\n\n```typescript\nimport { json } from 'velox/server';\n\nreturn json({ users }, { status: 200 });\nreturn json({ error: 'Not found' }, { status: 404 });\n```\n\n### `text(body, init?)`\n\nReturn a plain text response:\n\n```typescript\nimport { text } from 'velox/server';\n\nreturn text('Hello, World!');\nreturn text('Not Found', { status: 404 });\n```\n\n### `html(body, init?)`\n\nReturn an HTML response:\n\n```typescript\nimport { html } from 'velox/server';\n\nreturn html('<h1>Hello</h1>');\n```\n\n### `redirect(url, status?, headers?)`\n\nReturn a redirect response:\n\n```typescript\nimport { redirect } from 'velox/server';\n\nreturn redirect('/login', 302);\nreturn redirect('/new-location', 301);\n```\n\n### `notFound(message?)`\n\nReturn a 404 response:\n\n```typescript\nimport { notFound } from 'velox/server';\n\nreturn notFound('User not found');\n// Returns: Response with status 404 and JSON body\n```\n\n### `unauthorized(message?)`\n\nReturn a 401 response:\n\n```typescript\nimport { unauthorized } from 'velox/server';\n\nreturn unauthorized('Please log in');\n```\n\n### `forbidden(message?)`\n\nReturn a 403 response:\n\n```typescript\nimport { forbidden } from 'velox/server';\n\nreturn forbidden('You do not have access to this resource');\n```\n\n### `badRequest(message?, details?)`\n\nReturn a 400 response with optional validation details:\n\n```typescript\nimport { badRequest } from 'velox/server';\n\nreturn badRequest('Validation failed', { field: 'email', message: 'Invalid format' });\n```\n\n### `stream(generator, init?)`\n\nStream a response body using an async generator:\n\n```typescript\nimport { stream } from 'velox/server';\n\nexport const GET = defineHandler(async () => {\n  return stream(async function* () {\n    for await (const chunk of getLargeDataset()) {\n      yield JSON.stringify(chunk) + '\\n';\n    }\n  });\n});\n```\n\n## `createServer(options)`\n\nBootstrap a standalone Velox server programmatically (useful for testing):\n\n```typescript\nimport { createServer } from 'velox/server';\n\nconst server = await createServer({\n  root: '/path/to/project',\n  port: 3700,\n  mode: 'development',\n});\n\nawait server.start();\nconsole.log(`Server running on port ${server.port}`);\n\n// Later:\nawait server.stop();\n```\n\n### `VeloxServer` Methods\n\n| Method | Description |\n|--------|-------------|\n| `start()` | Start the HTTP server |\n| `stop()` | Gracefully shut down the server |\n| `getUrl()` | Returns the server base URL as a string |\n| `inject(request)` | Inject a synthetic request for testing without a network |\n\n## Cookies\n\n### Reading Cookies\n\n```typescript\nconst session = request.cookies.get('session');\nconst userId = request.cookies.get('userId')?.value;\n```\n\n### Setting Cookies\n\nUse the `ResponseCookies` API on the response object, or the `setCookie` helper:\n\n```typescript\nimport { setCookie, deleteCookie } from 'velox/server';\n\nconst response = json({ ok: true });\nsetCookie(response, 'session', token, {\n  httpOnly: true,\n  secure: true,\n  sameSite: 'lax',\n  path: '/',\n  maxAge: 60 * 60 * 24 * 7, // 7 days\n});\n\nreturn response;\n```\n\n### Deleting Cookies\n\n```typescript\nconst response = redirect('/login');\ndeleteCookie(response, 'session');\nreturn response;\n```\n\n## `useEnv(key, defaultValue?)`\n\nType-safe environment variable access with optional validation:\n\n```typescript\nimport { useEnv } from 'velox/server';\n\nconst dbUrl = useEnv('DATABASE_URL');           // throws if missing\nconst port = useEnv('PORT', '3700');            // returns defaultValue if missing\nconst apiKey = useEnv.required('SECRET_KEY');   // alias for useEn"
  },
  {
    "file": "pages/components.md",
    "title": "Components",
    "section-id": "core-concepts",
    "keywords": "components, props, slots, lifecycle, tsx, velox components, islands",
    "description": "The Velox component model, including props, slots, lifecycle hooks, and the islands architecture",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Components\n\nVelox components are TypeScript/TSX files that describe a piece of UI. They are the fundamental building blocks of a Velox application \u2014 reusable, composable, and by default rendered entirely on the server.\n\n## Defining a Component\n\nA basic Velox component is a TypeScript function that returns JSX:\n\n```tsx\n// components/Greeting.tsx\ninterface GreetingProps {\n  name: string;\n  formal?: boolean;\n}\n\nexport default function Greeting({ name, formal = false }: GreetingProps) {\n  const salutation = formal ? 'Good day' : 'Hello';\n  return <p>{salutation}, {name}!</p>;\n}\n```\n\nUse it in a route or another component:\n\n```tsx\n---\nimport Greeting from '../components/Greeting.tsx';\n---\n\n<main>\n  <Greeting name=\"Alice\" />\n  <Greeting name=\"Bob\" formal />\n</main>\n```\n\n## Props\n\nProps are typed using TypeScript interfaces or types. All props are validated at compile time \u2014 no runtime prop checking overhead.\n\n```tsx\ninterface CardProps {\n  title: string;\n  description: string;\n  href?: string;\n  variant?: 'default' | 'featured' | 'compact';\n  children?: VeloxNode;\n}\n\nexport default function Card({\n  title,\n  description,\n  href,\n  variant = 'default',\n  children,\n}: CardProps) {\n  return (\n    <div class={`card card--${variant}`}>\n      <h3>{href ? <a href={href}>{title}</a> : title}</h3>\n      <p>{description}</p>\n      {children && <div class=\"card__body\">{children}</div>}\n    </div>\n  );\n}\n```\n\n### Default Props\n\nSet default values directly in the destructuring parameter, as shown above. Velox does not use a separate `defaultProps` mechanism.\n\n### Required vs Optional Props\n\nBy TypeScript convention, optional props are marked with `?`. Omitting a required prop is a compile-time error.\n\n## Slots\n\nThe `children` prop is the default slot \u2014 content placed between the opening and closing tags of a component:\n\n```tsx\n<Card title=\"Welcome\" description=\"Get started\">\n  <p>This is the card body.</p>\n</Card>\n```\n\n### Named Slots\n\nFor more complex component APIs, use named slot props:\n\n```tsx\ninterface ModalProps {\n  title: VeloxNode;\n  footer?: VeloxNode;\n  children: VeloxNode;\n}\n\nexport default function Modal({ title, footer, children }: ModalProps) {\n  return (\n    <div class=\"modal\">\n      <div class=\"modal__header\">{title}</div>\n      <div class=\"modal__body\">{children}</div>\n      {footer && <div class=\"modal__footer\">{footer}</div>}\n    </div>\n  );\n}\n```\n\nUsage:\n\n```tsx\n<Modal\n  title={<h2>Confirm Delete</h2>}\n  footer={\n    <>\n      <button onClick={cancel}>Cancel</button>\n      <button onClick={confirm}>Delete</button>\n    </>\n  }\n>\n  <p>Are you sure you want to delete this item?</p>\n</Modal>\n```\n\n## Server vs Client Components\n\nBy default, all Velox components run on the server. They have no JavaScript bundle size on the client and cannot use browser APIs or client-side reactivity.\n\nTo make a component interactive on the client, use the `client:*` hydration directive when you include it in a route:\n\n```tsx\n---\nimport Counter from '../components/Counter.tsx';\nimport LazyChart from '../components/LazyChart.tsx';\n---\n\n<!-- Hydrate immediately when page loads -->\n<Counter client:load />\n\n<!-- Hydrate when browser is idle -->\n<Counter client:idle />\n\n<!-- Hydrate when the component enters the viewport -->\n<LazyChart client:visible />\n\n<!-- Hydrate only when a media query matches -->\n<Sidebar client:media=\"(max-width: 768px)\" />\n```\n\n### Writing Client Components\n\nClient components can use signals, effects, and browser APIs:\n\n```tsx\nimport { signal, effect, onMount, onCleanup } from 'velox/client';\n\nexport default function LiveClock() {\n  const time = signal(new Date().toLocaleTimeString());\n\n  onMount(() => {\n    const interval = setInterval(() => {\n      time.value = new Date().toLocaleTimeString();\n    }, 1000);\n\n    onCleanup(() => clearInterval(interval));\n  });\n\n  return <p>Current time: {time}</p>;\n}\n```\n\n## Lifecycle Hooks\n\nClient-side components can use the following lifecycle hooks:\n\n| Hook | When it runs |\n|------|-------------|\n| `onMount(fn)` | After the component is first rendered and inserted into the DOM |\n| `onUpdate(fn)` | After every re-render (reactive signal change) |\n| `onCleanup(fn)` | Before the component unmounts or before the next `onUpdate` call |\n| `onDestroy(fn)` | When the component is permanently unmounted |\n\n```tsx\nimport { signal, onMount, onUpdate, onCleanup } from 'velox/client';\n\nexport default function DataComponent() {\n  const data = signal<any[]>([]);\n  const loading = signal(true);\n\n  onMount(async () => {\n    const response = await fetch('/api/data');\n    data.value = await response.json();\n    loading.value = false;\n  });\n\n  onCleanup(() => {\n    // abort pending requests, clear timers, etc.\n  });\n\n  return (\n    <div>\n      {loading.value ? <p>Loading...</p> : <ul>{data.value.map(d => <li>{d.name}</li>)}</ul>}\n    </div>\n  );\n}\n```\n\n## Component Composition Patterns\n\n### Higher-Order Components\n\n```tsx\nfunction withAuth<T extends {}>(Component: VeloxComponent<T>) {\n  retur"
  },
  {
    "file": "pages/configuration.md",
    "title": "Configuration",
    "section-id": "getting-started",
    "keywords": "configuration, velox.config.ts, settings, options, defineConfig",
    "description": "Complete reference for velox.config.ts and all available configuration options",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Configuration\n\nVelox is configured through a single `velox.config.ts` file at the root of your project. This file is evaluated at build time (and at dev-server startup) to determine how Velox should compile and serve your application.\n\n## Creating the Config File\n\nIf you used `create-velox` to scaffold your project, a `velox.config.ts` is generated for you. To create one manually:\n\n```typescript\nimport { defineConfig } from 'velox';\n\nexport default defineConfig({\n  // options go here\n});\n```\n\n`defineConfig` is a helper that provides full TypeScript type inference over the configuration object \u2014 use it rather than exporting a plain object.\n\n## Top-Level Options\n\n### `app`\n\nGeneral application metadata.\n\n```typescript\napp: {\n  name: string;               // used in HTML <title> and meta tags\n  baseUrl: string;            // canonical base URL (e.g. https://example.com)\n  defaultLocale?: string;     // default locale for i18n (default: 'en')\n  trailingSlash?: boolean;    // append trailing slash to all routes (default: false)\n}\n```\n\nExample:\n\n```typescript\napp: {\n  name: 'My Velox App',\n  baseUrl: process.env.PUBLIC_BASE_URL ?? 'http://localhost:3700',\n  defaultLocale: 'en',\n  trailingSlash: false,\n},\n```\n\n### `server`\n\nDevelopment and production server settings.\n\n```typescript\nserver: {\n  port?: number;              // dev server port (default: 3700)\n  host?: string;              // bind address (default: 'localhost')\n  https?: {                   // enable HTTPS for the dev server\n    cert: string;             // path to certificate file\n    key: string;              // path to key file\n  };\n  cors?: {\n    origin: string | string[] | '*';\n    credentials?: boolean;\n    methods?: string[];\n  };\n}\n```\n\n### `build`\n\nBuild system options.\n\n```typescript\nbuild: {\n  target: 'node' | 'edge' | 'static';  // deployment target\n  outDir?: string;                       // output directory (default: '.velox/output')\n  sourcemap?: boolean | 'external';      // generate source maps\n  minify?: boolean;                      // minify output (default: true in production)\n  splitting?: boolean;                   // enable code splitting (default: true)\n  analyze?: boolean;                     // emit a bundle analysis report\n  prerender?: string[];                  // explicit list of routes to pre-render\n}\n```\n\n### `routes`\n\nFine-grained routing options.\n\n```typescript\nroutes: {\n  dir?: string;                // routes directory (default: 'routes')\n  extensions?: string[];       // file extensions treated as routes\n  // default: ['.velox', '.tsx', '.ts']\n  exclude?: string[];          // glob patterns to exclude\n}\n```\n\n### `assets`\n\nAsset handling and optimisation.\n\n```typescript\nassets: {\n  publicDir?: string;          // static assets directory (default: 'public')\n  imageOptimisation?: {\n    enabled: boolean;\n    formats?: ('webp' | 'avif')[];\n    quality?: number;          // 1\u2013100, default 80\n  };\n  fonts?: {\n    preload?: boolean;\n    subsets?: string[];\n  };\n}\n```\n\n### `css`\n\nStylesheet handling.\n\n```typescript\ncss: {\n  modules?: {\n    localsConvention?: 'camelCase' | 'camelCaseOnly' | 'dashes';\n    generateScopedName?: string;\n  };\n  preprocessors?: {\n    sass?: boolean;            // enable Sass (requires @velox/sass)\n    less?: boolean;\n    stylus?: boolean;\n  };\n  postcss?: {\n    plugins?: any[];\n  };\n}\n```\n\n### `plugins`\n\nThe plugin array lets you extend Velox with first-party and community plugins.\n\n```typescript\nimport { defineConfig } from 'velox';\nimport { veloxMDX } from '@velox/mdx';\nimport { veloxSass } from '@velox/sass';\nimport { veloxPWA } from '@velox/pwa';\n\nexport default defineConfig({\n  plugins: [\n    veloxMDX(),\n    veloxSass(),\n    veloxPWA({\n      name: 'My App',\n      themeColor: '#3a7bd5',\n    }),\n  ],\n});\n```\n\n### `experimental`\n\nOpt-in to experimental features that are not yet stable.\n\n```typescript\nexperimental: {\n  viewTransitions?: boolean;   // CSS View Transitions API support\n  partialHydration?: boolean;  // fine-grained component hydration\n  reactCompat?: boolean;       // React component compatibility shim\n}\n```\n\n## Environment-Specific Configuration\n\nYou can provide environment-specific overrides:\n\n```typescript\nimport { defineConfig } from 'velox';\n\nexport default defineConfig({\n  app: {\n    name: 'My App',\n    baseUrl: process.env.PUBLIC_BASE_URL!,\n  },\n  server: {\n    port: parseInt(process.env.PORT ?? '3700'),\n  },\n  build: {\n    target: process.env.VELOX_TARGET as 'node' | 'edge' ?? 'node',\n    sourcemap: process.env.NODE_ENV !== 'production',\n  },\n});\n```\n\n## Per-Route Rendering Configuration\n\nYou can override the rendering mode for individual routes from within the route file:\n\n```typescript\n// routes/dashboard.velox server block\nexport const config = {\n  render: 'ssr',       // 'ssr' | 'ssg' | 'isr' | 'csr'\n  revalidate: 60,      // ISR: revalidate every 60 seconds\n  edge: true,          // run on edge runtime\n};\n```\n\n## Full Example\n\nA production-ready `velox.config.ts` for "
  },
  {
    "file": "pages/data-fetching.md",
    "title": "Data Fetching",
    "section-id": "core-concepts",
    "keywords": "data fetching, SSR, SSG, ISR, server-side rendering, static generation, fetch, async",
    "description": "How to fetch data in Velox using SSR, SSG, ISR, and client-side fetching patterns",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Data Fetching\n\nVelox provides multiple data-fetching patterns depending on when and how often your data changes. You can mix strategies freely across routes in the same project.\n\n## Server-Side Rendering (SSR)\n\nIn SSR mode, data is fetched fresh on every request. Use `await` directly in the server block of a `.velox` route:\n\n```tsx\n---\n// routes/blog/[slug].velox\nimport { db } from '$lib/db';\nimport { NotFound } from 'velox/server';\n\nconst { slug } = params;\nconst post = await db.posts.findBySlug(slug);\n\nif (!post) throw new NotFound();\n\nexport const meta = {\n  title: post.title,\n  description: post.excerpt,\n};\nexport const config = { render: 'ssr' };\n---\n\n<article>\n  <h1>{post.title}</h1>\n  <p class=\"byline\">By {post.author} on {post.publishedAt}</p>\n  <div innerHTML={post.htmlContent} />\n</article>\n```\n\nThe `render: 'ssr'` export is optional \u2014 SSR is the default for routes that contain `await` expressions.\n\n### Request Context in SSR\n\nIn SSR mode, the `request` object is available in the server block:\n\n```typescript\nconst authHeader = request.headers.get('Authorization');\nconst userAgent = request.headers.get('User-Agent');\nconst cookieHeader = request.headers.get('Cookie');\n```\n\n## Static Site Generation (SSG)\n\nSSG routes are rendered once at build time. They are ideal for content that rarely changes.\n\n```tsx\n---\nexport const config = { render: 'ssg' };\n\nconst features = await fetch('https://api.example.com/features').then(r => r.json());\n---\n\n<section>\n  <h1>Features</h1>\n  <ul>\n    {features.map(f => <li>{f.name}: {f.description}</li>)}\n  </ul>\n</section>\n```\n\n### Dynamic SSG Routes\n\nFor SSG routes with dynamic segments, export a `paths` function to tell Velox which parameter values to pre-render:\n\n```tsx\n---\nimport { db } from '$lib/db';\n\nexport const config = { render: 'ssg' };\n\n// Called at build time to enumerate all slugs\nexport async function paths() {\n  const slugs = await db.posts.findManySlugs();\n  return slugs.map(slug => ({ slug }));\n}\n\nconst { slug } = params;\nconst post = await db.posts.findBySlug(slug);\nexport const meta = { title: post.title };\n---\n\n<article>\n  <h1>{post.title}</h1>\n  <div innerHTML={post.htmlContent} />\n</article>\n```\n\n## Incremental Static Regeneration (ISR)\n\nISR generates pages statically but revalidates them in the background after a configurable interval:\n\n```tsx\n---\nexport const config = {\n  render: 'isr',\n  revalidate: 3600, // regenerate at most once per hour\n};\n\nconst products = await db.products.findMany({ orderBy: 'created_at' });\n---\n\n<section>\n  {products.map(p => <ProductCard product={p} />)}\n</section>\n```\n\nOn a cache miss (first request, or after `revalidate` seconds), Velox serves the stale page immediately while regenerating the fresh version in the background. The next request gets the fresh version.\n\n### Manual Revalidation\n\nTrigger revalidation programmatically (e.g., from a webhook):\n\n```typescript\n// routes/api/revalidate+server.ts\nimport { revalidatePath, revalidateTag } from 'velox/server';\n\nexport const POST = defineHandler(async (req) => {\n  const { path, secret } = await req.json();\n\n  if (secret !== process.env.REVALIDATE_SECRET) {\n    return Response.json({ error: 'Unauthorized' }, { status: 401 });\n  }\n\n  await revalidatePath(path);\n  return Response.json({ revalidated: true });\n});\n```\n\nTag-based revalidation:\n\n```typescript\n// When fetching, attach cache tags:\nconst data = await fetch('/api/products', {\n  next: { tags: ['products'] }\n});\n\n// Later, invalidate all pages that used the 'products' tag:\nawait revalidateTag('products');\n```\n\n## Client-Side Fetching\n\nFor data that must be fresh on the client (user-specific dashboards, real-time data), use client-side fetching in an interactive component:\n\n```tsx\nimport { signal, onMount } from 'velox/client';\n\nexport default function UserDashboard() {\n  const stats = signal<DashboardStats | null>(null);\n  const error = signal<string | null>(null);\n  const loading = signal(true);\n\n  onMount(async () => {\n    try {\n      const res = await fetch('/api/dashboard/stats', {\n        credentials: 'include',\n      });\n      if (!res.ok) throw new Error('Failed to fetch stats');\n      stats.value = await res.json();\n    } catch (e: any) {\n      error.value = e.message;\n    } finally {\n      loading.value = false;\n    }\n  });\n\n  return (\n    <div>\n      {loading.value && <Spinner />}\n      {error.value && <ErrorMessage message={error.value} />}\n      {stats.value && <StatsGrid stats={stats.value} />}\n    </div>\n  );\n}\n```\n\n### Using `@velox/query`\n\nFor production client-side data fetching, `@velox/query` handles caching, deduplication, background refetch, and stale-while-revalidate:\n\n```typescript\nimport { useQuery } from '@velox/query';\n\nexport default function ProductList() {\n  const { data, status, error, refetch } = useQuery({\n    key: ['products'],\n    fetcher: () => fetch('/api/products').then(r => r.json()),\n    staleTime: 30_000,\n    refetchOnWindowFocus: true,\n  });\n\n  if (status === 'loading') "
  },
  {
    "file": "pages/deploy-cloudflare.md",
    "title": "Deploy to Cloudflare",
    "section-id": "deployment",
    "keywords": "Cloudflare, Pages, Workers, deployment, edge, CDN, Wrangler",
    "description": "Deploying a Velox application to Cloudflare Pages and Workers",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Deploy to Cloudflare\n\nVelox runs natively on Cloudflare Workers. By combining Cloudflare Pages for static assets and Cloudflare Workers for server-side rendering, you get a globally distributed application with sub-millisecond cold starts.\n\n## Architecture\n\nVelox on Cloudflare uses:\n- **Cloudflare Pages** \u2014 serves static assets from the CDN edge\n- **Cloudflare Workers** \u2014 handles SSR requests at the edge\n- **KV** \u2014 used for ISR page caching\n- **D1** \u2014 SQLite-at-the-edge database (optional)\n- **R2** \u2014 object storage for user uploads (optional)\n\n## Setup\n\nInstall the Cloudflare adapter:\n\n```bash\nnpm install @velox/cloudflare\nnpm install -D wrangler\n```\n\nConfigure the adapter:\n\n```typescript\n// velox.config.ts\nimport { defineConfig } from 'velox';\nimport { cloudflare } from '@velox/cloudflare';\n\nexport default defineConfig({\n  adapter: cloudflare({\n    kvNamespace: 'VELOX_CACHE',   // KV namespace for ISR cache\n    routes: {\n      exclude: ['/admin/*'],       // serve these from Pages CDN only\n    },\n  }),\n  build: {\n    target: 'edge',\n  },\n});\n```\n\n## Wrangler Configuration\n\nCreate `wrangler.toml`:\n\n```toml\nname = \"my-velox-app\"\ncompatibility_date = \"2026-01-01\"\ncompatibility_flags = [\"nodejs_compat\"]\npages_build_output_dir = \".velox/output\"\n\n[[kv_namespaces]]\nbinding = \"VELOX_CACHE\"\nid = \"your-kv-namespace-id\"\n\n[[d1_databases]]\nbinding = \"DB\"\ndatabase_name = \"my-database\"\ndatabase_id = \"your-database-id\"\n\n[vars]\nNODE_ENV = \"production\"\n```\n\n## Deployment Steps\n\n### Option 1: Cloudflare Pages Dashboard\n\n1. Go to [dash.cloudflare.com](https://dash.cloudflare.com) \u2192 **Pages** \u2192 **Create a project**\n2. Connect your Git provider and select your repository\n3. Set build settings:\n   - **Framework preset:** Velox\n   - **Build command:** `npm run build`\n   - **Build output directory:** `.velox/output`\n4. Add environment variables\n5. Click **Save and Deploy**\n\n### Option 2: Wrangler CLI\n\n```bash\n# Log in\nnpx wrangler login\n\n# Build\nnpm run build\n\n# Deploy\nnpx wrangler pages deploy .velox/output --project-name my-velox-app\n\n# Or deploy as a Worker\nnpx wrangler deploy\n```\n\n## Using Cloudflare D1 (SQLite at the Edge)\n\nCloudflare D1 is a serverless SQLite database that runs at the edge alongside your Workers.\n\n### Create a Database\n\n```bash\nnpx wrangler d1 create my-database\nnpx wrangler d1 execute my-database --file=./migrations/001_init.sql\n```\n\n### Query D1 in Velox\n\n```typescript\n// routes/api/posts+server.ts\nimport { defineHandler } from 'velox/server';\n\nexport const GET = defineHandler(async (req) => {\n  // env.DB is automatically injected by the Cloudflare adapter\n  const { DB } = process.env as any;\n  const { results } = await DB.prepare('SELECT * FROM posts WHERE published = 1').all();\n  return Response.json(results);\n});\n```\n\nOr with Drizzle's D1 driver:\n\n```typescript\nimport { drizzle } from 'drizzle-orm/d1';\nimport * as schema from '$lib/schema';\n\nexport function getDB(env: Env) {\n  return drizzle(env.DB, { schema });\n}\n```\n\n## Using Cloudflare KV\n\nFor key-value storage (feature flags, cached responses):\n\n```typescript\nconst value = await env.MY_KV.get('my-key');\nawait env.MY_KV.put('my-key', JSON.stringify(data), { expirationTtl: 3600 });\nawait env.MY_KV.delete('my-key');\n```\n\n## Using Cloudflare R2\n\nFor file uploads and object storage:\n\n```typescript\n// routes/api/upload+server.ts\nimport { defineHandler } from 'velox/server';\n\nexport const POST = defineHandler(async (req) => {\n  const formData = await req.formData();\n  const file = formData.get('file') as File;\n\n  const key = `uploads/${Date.now()}-${file.name}`;\n  await env.R2_BUCKET.put(key, file.stream(), {\n    httpMetadata: { contentType: file.type },\n  });\n\n  return Response.json({ url: `https://assets.example.com/${key}` });\n});\n```\n\n## Custom Domains\n\n1. Add your domain in Cloudflare's DNS settings (it should already be proxied through Cloudflare)\n2. Go to Pages \u2192 Your project \u2192 **Custom domains**\n3. Click **Set up a custom domain** and enter your domain\n4. Cloudflare provisions SSL automatically\n\nFor Workers, add a route in `wrangler.toml`:\n\n```toml\n[[routes]]\npattern = \"example.com/*\"\nzone_name = \"example.com\"\n```\n\n## Environment Variables\n\nSet secrets securely:\n\n```bash\nnpx wrangler secret put DATABASE_URL\nnpx wrangler secret put SESSION_SECRET\nnpx wrangler secret put JWT_SECRET\n```\n\nNon-secret variables go in `wrangler.toml` under `[vars]` or in the Pages dashboard.\n\n## Performance Tips\n\n- Use **Cache Rules** in the Cloudflare dashboard to cache SSR pages at the CDN layer\n- Enable **Argo Smart Routing** for improved global routing\n- Use **Tiered Cache** to reduce origin requests\n- Set `Cache-Control: public, max-age=0, s-maxage=3600` on ISR pages to let Cloudflare cache them\n\n## Limits\n\n| Feature | Limit |\n|---------|-------|\n| Worker request timeout | 30s (CPU time) |\n| Worker memory | 128 MB |\n| KV value size | 25 MB |\n| D1 database size | 2 GB |\n| R2 object size | 5 GB |"
  },
  {
    "file": "pages/deploy-docker.md",
    "title": "Docker",
    "section-id": "deployment",
    "keywords": "Docker, Dockerfile, docker-compose, container, containerisation, deployment",
    "description": "Containerising a Velox application with Docker and docker-compose",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Docker\n\nContainerising your Velox application with Docker makes it portable across any infrastructure \u2014 from a simple VPS to a Kubernetes cluster. This guide covers building optimised Docker images and running multi-service stacks with docker-compose.\n\n## Dockerfile\n\nA production-grade multi-stage Dockerfile:\n\n```dockerfile\n# Stage 1: Install dependencies\nFROM node:22-alpine AS deps\nWORKDIR /app\n\n# Copy package manifests only \u2014 enables Docker layer caching\nCOPY package.json package-lock.json ./\nRUN npm ci --frozen-lockfile\n\n# Stage 2: Build the application\nFROM node:22-alpine AS builder\nWORKDIR /app\n\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY . .\n\n# Build args \u2014 pass at build time\nARG PUBLIC_BASE_URL\nARG NODE_ENV=production\nENV PUBLIC_BASE_URL=$PUBLIC_BASE_URL\nENV NODE_ENV=$NODE_ENV\n\nRUN npm run build\n\n# Stage 3: Production runtime\nFROM node:22-alpine AS runner\nWORKDIR /app\n\nENV NODE_ENV=production\nENV PORT=3700\n\n# Create non-root user for security\nRUN addgroup --system --gid 1001 veloxgroup && \\\n    adduser --system --uid 1001 veloxuser\n\n# Copy only production artefacts\nCOPY --from=builder --chown=veloxuser:veloxgroup /app/.velox/output ./\nCOPY --from=builder --chown=veloxuser:veloxgroup /app/package.json ./\n\n# Install production dependencies only\nRUN npm ci --omit=dev --frozen-lockfile\n\nUSER veloxuser\n\nEXPOSE 3700\n\nCMD [\"node\", \"server.js\"]\n```\n\n## Building and Running\n\n```bash\n# Build the image\ndocker build \\\n  --build-arg PUBLIC_BASE_URL=https://example.com \\\n  -t my-velox-app:latest .\n\n# Run the container\ndocker run \\\n  --env-file .env.production \\\n  -p 3700:3700 \\\n  --name velox-app \\\n  my-velox-app:latest\n\n# Run in background\ndocker run -d \\\n  --env-file .env.production \\\n  -p 3700:3700 \\\n  --restart unless-stopped \\\n  --name velox-app \\\n  my-velox-app:latest\n```\n\n## `.dockerignore`\n\nExclude files from the build context to speed up builds:\n\n```\nnode_modules\n.velox\n.git\n.gitignore\n*.md\n.env\n.env.*\n!.env.example\ntests\n*.test.*\n*.spec.*\ncoverage\n```\n\n## docker-compose\n\nA complete stack with the app, PostgreSQL, and Redis:\n\n```yaml\n# docker-compose.yml\nversion: '3.9'\n\nservices:\n  app:\n    build:\n      context: .\n      args:\n        PUBLIC_BASE_URL: ${PUBLIC_BASE_URL:-http://localhost:3700}\n    image: my-velox-app:latest\n    ports:\n      - \"3700:3700\"\n    environment:\n      NODE_ENV: production\n      DATABASE_URL: postgresql://velox:${DB_PASSWORD}@db:5432/velox\n      REDIS_URL: redis://redis:6379\n      SESSION_SECRET: ${SESSION_SECRET}\n      JWT_SECRET: ${JWT_SECRET}\n    depends_on:\n      db:\n        condition: service_healthy\n      redis:\n        condition: service_healthy\n    restart: unless-stopped\n    healthcheck:\n      test: [\"CMD\", \"wget\", \"-qO-\", \"http://localhost:3700/api/health\"]\n      interval: 30s\n      timeout: 10s\n      retries: 3\n      start_period: 40s\n\n  db:\n    image: postgres:16-alpine\n    environment:\n      POSTGRES_USER: velox\n      POSTGRES_PASSWORD: ${DB_PASSWORD}\n      POSTGRES_DB: velox\n    volumes:\n      - postgres_data:/var/lib/postgresql/data\n    healthcheck:\n      test: [\"CMD-SHELL\", \"pg_isready -U velox\"]\n      interval: 10s\n      timeout: 5s\n      retries: 5\n    restart: unless-stopped\n\n  redis:\n    image: redis:7-alpine\n    command: redis-server --requirepass ${REDIS_PASSWORD} --appendonly yes\n    volumes:\n      - redis_data:/data\n    healthcheck:\n      test: [\"CMD\", \"redis-cli\", \"--no-auth-warning\", \"-a\", \"${REDIS_PASSWORD}\", \"ping\"]\n      interval: 10s\n      timeout: 5s\n      retries: 5\n    restart: unless-stopped\n\n  nginx:\n    image: nginx:alpine\n    ports:\n      - \"80:80\"\n      - \"443:443\"\n    volumes:\n      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro\n      - ./nginx/ssl:/etc/nginx/ssl:ro\n      - nginx_cache:/var/cache/nginx\n    depends_on:\n      - app\n    restart: unless-stopped\n\nvolumes:\n  postgres_data:\n  redis_data:\n  nginx_cache:\n```\n\n## Nginx Reverse Proxy\n\n```nginx\n# nginx/nginx.conf\nevents { worker_connections 1024; }\n\nhttp {\n  upstream velox_app {\n    server app:3700;\n    keepalive 64;\n  }\n\n  # Redirect HTTP \u2192 HTTPS\n  server {\n    listen 80;\n    server_name example.com www.example.com;\n    return 301 https://$host$request_uri;\n  }\n\n  server {\n    listen 443 ssl http2;\n    server_name example.com www.example.com;\n\n    ssl_certificate     /etc/nginx/ssl/fullchain.pem;\n    ssl_certificate_key /etc/nginx/ssl/privkey.pem;\n    ssl_protocols       TLSv1.2 TLSv1.3;\n    ssl_ciphers         HIGH:!aNULL:!MD5;\n\n    # Static assets with long cache\n    location /assets/ {\n      proxy_pass http://velox_app;\n      add_header Cache-Control \"public, max-age=31536000, immutable\";\n    }\n\n    # Application\n    location / {\n      proxy_pass http://velox_app;\n      proxy_http_version 1.1;\n      proxy_set_header Upgrade $http_upgrade;\n      proxy_set_header Connection 'upgrade';\n      proxy_set_header Host $host;\n      proxy_set_header X-Real-IP $remote_addr;\n      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n      proxy_set_header X-Forwarded-Proto $sch"
  },
  {
    "file": "pages/deploy-self-hosted.md",
    "title": "Self-Hosted",
    "section-id": "deployment",
    "keywords": "self-hosted, VPS, nginx, PM2, systemd, Linux, server deployment",
    "description": "Running Velox on a VPS with nginx as a reverse proxy, managed by PM2 or systemd",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Self-Hosted\n\nDeploying Velox to your own server (a VPS, dedicated server, or on-premises machine) gives you full control over your infrastructure. This guide covers setting up a Linux server with nginx as a reverse proxy, and managing the Node.js process with either PM2 or systemd.\n\n## Server Preparation\n\nThis guide assumes Ubuntu 24.04 LTS. Adjust package manager commands for other distributions.\n\n```bash\n# Update the system\nsudo apt update && sudo apt upgrade -y\n\n# Install Node.js (LTS) via nvm\ncurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash\nsource ~/.bashrc\nnvm install 22\nnvm use 22\nnvm alias default 22\n\n# Install nginx\nsudo apt install -y nginx\n\n# Install PostgreSQL (if needed)\nsudo apt install -y postgresql postgresql-contrib\n\n# Install Redis (if needed)\nsudo apt install -y redis-server\n```\n\n## Deploying the Application\n\n### Option A: Direct File Copy\n\n```bash\n# On your local machine \u2014 build the app\nnpm run build\n\n# Copy build output to the server\nrsync -avz --delete .velox/output/ user@your-server.com:/var/www/my-velox-app/\nrsync -avz package.json package-lock.json user@your-server.com:/var/www/my-velox-app/\n\n# On the server \u2014 install production dependencies\ncd /var/www/my-velox-app\nnpm ci --omit=dev\n```\n\n### Option B: Git + CI/CD\n\nCreate a deploy script on the server:\n\n```bash\n#!/bin/bash\n# /home/deploy/deploy.sh\nset -e\n\nAPP_DIR=/var/www/my-velox-app\nREPO=https://github.com/your-org/your-repo.git\n\ncd $APP_DIR\n\n# Pull latest code\ngit fetch --all\ngit reset --hard origin/main\n\n# Install dependencies\nnpm ci --frozen-lockfile --omit=dev\n\n# Build\nnpm run build\n\n# Restart application\npm2 reload my-velox-app --update-env\n\necho \"Deployment complete.\"\n```\n\nCall this from your GitHub Actions workflow:\n\n```yaml\n# .github/workflows/deploy.yml\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Deploy to server\n        uses: appleboy/ssh-action@v1\n        with:\n          host: ${{ secrets.SERVER_HOST }}\n          username: deploy\n          key: ${{ secrets.SERVER_SSH_KEY }}\n          script: /home/deploy/deploy.sh\n```\n\n## Environment Variables\n\nStore production secrets in `/etc/environment` or a `.env.production` file:\n\n```bash\n# /etc/environment (system-wide)\nNODE_ENV=production\nDATABASE_URL=postgresql://velox:secretpass@localhost:5432/velox\nSESSION_SECRET=your-long-random-secret-here\nJWT_SECRET=another-long-random-secret\n\n# Or in a project-specific .env.production\nsudo nano /var/www/my-velox-app/.env.production\n```\n\nLoad the env file in your start command (covered below).\n\n## Process Management with PM2\n\nPM2 is a battle-tested process manager for Node.js applications.\n\n```bash\nnpm install -g pm2\n```\n\nCreate a PM2 ecosystem file:\n\n```javascript\n// /var/www/my-velox-app/ecosystem.config.js\nmodule.exports = {\n  apps: [{\n    name: 'my-velox-app',\n    script: 'server.js',\n    cwd: '/var/www/my-velox-app',\n    instances: 'max',           // one process per CPU core\n    exec_mode: 'cluster',       // enable cluster mode for zero-downtime restarts\n    env_file: '/var/www/my-velox-app/.env.production',\n    env: {\n      NODE_ENV: 'production',\n      PORT: 3700,\n    },\n    error_file: '/var/log/pm2/my-velox-app-error.log',\n    out_file: '/var/log/pm2/my-velox-app-out.log',\n    log_date_format: 'YYYY-MM-DD HH:mm:ss',\n    max_memory_restart: '500M', // restart if memory exceeds 500 MB\n  }],\n};\n```\n\nStart and persist:\n\n```bash\npm2 start ecosystem.config.js\npm2 save             # persist process list across reboots\npm2 startup          # install systemd startup script\n\n# Useful commands\npm2 status\npm2 logs my-velox-app\npm2 reload my-velox-app    # zero-downtime reload\npm2 restart my-velox-app   # full restart\npm2 monit                  # real-time monitoring\n```\n\n## systemd Service (Alternative to PM2)\n\nFor simpler setups, a systemd unit file:\n\n```ini\n# /etc/systemd/system/my-velox-app.service\n[Unit]\nDescription=My Velox Application\nAfter=network.target postgresql.service redis.service\n\n[Service]\nType=simple\nUser=www-data\nGroup=www-data\nWorkingDirectory=/var/www/my-velox-app\nEnvironmentFile=/var/www/my-velox-app/.env.production\nExecStart=/usr/bin/node server.js\nRestart=always\nRestartSec=5\nStandardOutput=journal\nStandardError=journal\nSyslogIdentifier=my-velox-app\n\n# Resource limits\nLimitNOFILE=65536\nMemoryMax=512M\n\n[Install]\nWantedBy=multi-user.target\n```\n\n```bash\nsudo systemctl daemon-reload\nsudo systemctl enable my-velox-app\nsudo systemctl start my-velox-app\nsudo journalctl -u my-velox-app -f   # follow logs\n```\n\n## Nginx Configuration\n\n```nginx\n# /etc/nginx/sites-available/my-velox-app\nupstream velox {\n    server 127.0.0.1:3700;\n    keepalive 32;\n}\n\nserver {\n    listen 80;\n    server_name example.com www.example.com;\n    return 301 https://$host$request_uri;\n}\n\nserver {\n    listen 443 ssl http2;\n    server_name example.com www.example.com;\n\n    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;\n    ssl_certificate_key /etc/letsencrypt/live/example.com/privke"
  },
  {
    "file": "pages/deploy-vercel.md",
    "title": "Deploy to Vercel",
    "section-id": "deployment",
    "keywords": "Vercel, deployment, serverless, edge, CI/CD, deploy",
    "description": "Step-by-step guide to deploying a Velox application to Vercel",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Deploy to Vercel\n\nVercel is the recommended hosting platform for Velox applications. The Velox Vercel adapter handles all configuration automatically \u2014 no manual `vercel.json` setup is required for most projects.\n\n## Prerequisites\n\n- A Vercel account ([vercel.com](https://vercel.com))\n- The Vercel CLI: `npm install -g vercel`\n- A Velox project committed to a Git repository (GitHub, GitLab, or Bitbucket)\n\n## Automatic Deployment via Git Integration\n\n### Step 1 \u2014 Push Your Project to Git\n\n```bash\ngit init\ngit add .\ngit commit -m \"Initial commit\"\ngit remote add origin https://github.com/your-username/your-project.git\ngit push -u origin main\n```\n\n### Step 2 \u2014 Import the Project on Vercel\n\n1. Go to [vercel.com/new](https://vercel.com/new)\n2. Click **Add New Project** \u2192 **Import Git Repository**\n3. Select your repository\n4. Vercel automatically detects Velox and sets the correct build settings:\n   - **Framework Preset:** Velox\n   - **Build Command:** `velox build`\n   - **Output Directory:** `.velox/output`\n   - **Install Command:** `npm ci`\n\n### Step 3 \u2014 Configure Environment Variables\n\nIn the Vercel project dashboard:\n1. Go to **Settings** \u2192 **Environment Variables**\n2. Add each variable from your `.env.production` file\n\nDo **not** add `PUBLIC_BASE_URL` manually \u2014 Vercel sets `VERCEL_URL` automatically and the Velox Vercel adapter uses it.\n\n### Step 4 \u2014 Deploy\n\nClick **Deploy**. Vercel will:\n1. Clone your repository\n2. Install dependencies\n3. Run `velox build`\n4. Deploy to its global edge network\n\nYour site is live at `https://your-project.vercel.app`.\n\n## Vercel CLI Deployment\n\nFor manual or scripted deployments:\n\n```bash\n# Install adapter\nnpm install @velox/vercel\n\n# Deploy to preview (equivalent to a branch deploy)\nvercel\n\n# Deploy to production\nvercel --prod\n```\n\n## Configuring the Vercel Adapter\n\nInstall and configure `@velox/vercel`:\n\n```bash\nnpm install @velox/vercel\n```\n\n```typescript\n// velox.config.ts\nimport { defineConfig } from 'velox';\nimport { vercel } from '@velox/vercel';\n\nexport default defineConfig({\n  adapter: vercel({\n    // Route-level edge function configuration\n    edgeRoutes: ['/api/stream', '/api/realtime'],\n\n    // Override ISR revalidation for specific routes\n    isr: {\n      expiration: 60,             // default revalidation (seconds)\n      bypassToken: process.env.VERCEL_ISR_BYPASS_TOKEN,\n    },\n\n    // Enable Vercel Image Optimisation (uses Vercel's CDN)\n    images: {\n      sizes: [640, 1080, 1920],\n    },\n  }),\n});\n```\n\n## Edge Functions\n\nMark individual routes to run on Vercel Edge instead of Node.js serverless:\n\n```typescript\n// routes/api/stream+server.ts\nexport const config = { edge: true };\n\nexport const GET = defineHandler(async (req) => {\n  // Runs on Vercel Edge \u2014 uses Web APIs only\n  return new Response('Hello from edge!');\n});\n```\n\nEdge functions are deployed globally in ~70 Vercel regions and have ~0ms cold start. Use them for latency-sensitive, stateless handlers.\n\n## Custom Domains\n\n1. Go to your project on Vercel \u2192 **Settings** \u2192 **Domains**\n2. Click **Add Domain**\n3. Enter your domain (e.g., `example.com`)\n4. Follow the DNS configuration instructions:\n   - Add a **CNAME** record: `www` \u2192 `cname.vercel-dns.com`\n   - Add an **A** record: `@` \u2192 `76.76.21.21`\n5. SSL certificates are provisioned automatically via Let's Encrypt\n\nSet the canonical base URL environment variable in Vercel:\n\n```\nPUBLIC_BASE_URL = https://example.com\n```\n\n## Preview Deployments\n\nEvery pull request gets an automatic preview deployment at a unique URL (`https://your-project-git-branch-name.vercel.app`). This is configured by default and requires no additional setup.\n\nTo share preview deployments with your team, enable **Password Protection** under **Settings** \u2192 **Deployment Protection**.\n\n## Build Cache\n\nVelox's Velocitor build cache is automatically persisted across deployments by the Vercel adapter. Subsequent deployments typically build 3\u20135\u00d7 faster than the first.\n\n## `vercel.json` Reference\n\nFor advanced configuration, create a `vercel.json` at your project root:\n\n```json\n{\n  \"regions\": [\"iad1\", \"fra1\"],\n  \"cleanUrls\": true,\n  \"trailingSlash\": false,\n  \"headers\": [\n    {\n      \"source\": \"/assets/(.*)\",\n      \"headers\": [\n        { \"key\": \"Cache-Control\", \"value\": \"public, max-age=31536000, immutable\" }\n      ]\n    }\n  ],\n  \"redirects\": [\n    { \"source\": \"/old-path\", \"destination\": \"/new-path\", \"permanent\": true }\n  ]\n}\n```\n\n## Monitoring and Analytics\n\nEnable Vercel Analytics and Speed Insights in your project dashboard. The Velox adapter hooks into these automatically \u2014 no code changes needed.\n\nFor custom event tracking:\n\n```typescript\nimport { track } from '@vercel/analytics';\n\ntrack('button_clicked', { component: 'Hero', variant: 'primary' });\n```"
  },
  {
    "file": "pages/guide-auth.md",
    "title": "Authentication",
    "section-id": "guides",
    "keywords": "authentication, JWT, OAuth2, session, login, auth, security",
    "description": "Implementing authentication in Velox using JWT, OAuth2, and session-based strategies",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Authentication\n\nThis guide covers the three most common authentication patterns for Velox applications: session-based auth, JWT-based auth, and OAuth2 with third-party providers.\n\n## Session-Based Authentication\n\nSession auth stores user state server-side. The client holds only a signed session cookie. This is the simplest and most secure approach for most web applications.\n\n### Setup\n\nInstall the session plugin:\n\n```bash\nnpm install @velox/session @velox/session-redis\n```\n\nConfigure in `velox.config.ts`:\n\n```typescript\nimport { RedisSessionStore } from '@velox/session-redis';\n\nexport default defineConfig({\n  session: {\n    secret: process.env.SESSION_SECRET!,\n    cookieName: 'app.session',\n    maxAge: 60 * 60 * 24 * 7,  // 7 days\n    httpOnly: true,\n    secure: process.env.NODE_ENV === 'production',\n    sameSite: 'lax',\n    store: new RedisSessionStore({ url: process.env.REDIS_URL! }),\n  },\n});\n```\n\n### Login Handler\n\n```typescript\n// routes/api/auth/login+server.ts\nimport { defineHandler, json, redirect } from 'velox/server';\nimport { useSession } from 'velox/server';\nimport { db } from '$lib/db';\nimport { verifyPassword } from '$lib/crypto';\n\nexport const POST = defineHandler(async (req) => {\n  const { email, password } = await req.json();\n\n  if (!email || !password) {\n    return json({ error: 'Email and password are required' }, { status: 400 });\n  }\n\n  const user = await db.users.findByEmail(email);\n  if (!user || !(await verifyPassword(password, user.passwordHash))) {\n    return json({ error: 'Invalid credentials' }, { status: 401 });\n  }\n\n  const session = await useSession();\n  await session.regenerate();  // prevent session fixation\n  await session.update({ userId: user.id, role: user.role });\n\n  return json({ ok: true, redirectTo: '/dashboard' });\n});\n```\n\n### Auth Middleware\n\n```typescript\n// middleware/auth.ts\nimport { defineMiddleware, redirect } from 'velox/server';\nimport { useSession } from 'velox/server';\n\nconst PUBLIC_PATHS = ['/login', '/register', '/api/auth'];\n\nexport default defineMiddleware(async ({ request, next }) => {\n  const pathname = new URL(request.url).pathname;\n\n  if (PUBLIC_PATHS.some(p => pathname.startsWith(p))) {\n    return next();\n  }\n\n  const session = await useSession<{ userId: string }>();\n\n  if (!session.data.userId) {\n    return redirect(`/login?next=${encodeURIComponent(pathname)}`);\n  }\n\n  request.context.set('userId', session.data.userId);\n  return next();\n});\n```\n\n## JWT Authentication\n\nJWT is stateless and ideal for API-first applications or mobile/SPA backends.\n\n### Generating Tokens\n\n```typescript\n// lib/jwt.ts\nimport { SignJWT, jwtVerify } from 'jose';\n\nconst secret = new TextEncoder().encode(process.env.JWT_SECRET!);\n\nexport interface JWTPayload {\n  sub: string;   // user ID\n  role: string;\n  iat: number;\n  exp: number;\n}\n\nexport async function signToken(userId: string, role: string): Promise<string> {\n  return new SignJWT({ sub: userId, role })\n    .setProtectedHeader({ alg: 'HS256' })\n    .setIssuedAt()\n    .setExpirationTime('15m')\n    .sign(secret);\n}\n\nexport async function signRefreshToken(userId: string): Promise<string> {\n  return new SignJWT({ sub: userId, type: 'refresh' })\n    .setProtectedHeader({ alg: 'HS256' })\n    .setIssuedAt()\n    .setExpirationTime('30d')\n    .sign(secret);\n}\n\nexport async function verifyToken(token: string): Promise<JWTPayload> {\n  const { payload } = await jwtVerify(token, secret);\n  return payload as JWTPayload;\n}\n```\n\n### Login + Refresh Endpoints\n\n```typescript\n// routes/api/auth/token+server.ts\nimport { defineHandler, json, badRequest, unauthorized } from 'velox/server';\nimport { signToken, signRefreshToken, verifyToken } from '$lib/jwt';\nimport { db } from '$lib/db';\nimport { verifyPassword } from '$lib/crypto';\n\nexport const POST = defineHandler(async (req) => {\n  const { grant_type, email, password, refresh_token } = await req.json();\n\n  if (grant_type === 'password') {\n    const user = await db.users.findByEmail(email);\n    if (!user || !(await verifyPassword(password, user.passwordHash))) {\n      return unauthorized('Invalid credentials');\n    }\n    return json({\n      access_token: await signToken(user.id, user.role),\n      refresh_token: await signRefreshToken(user.id),\n      token_type: 'Bearer',\n      expires_in: 900,\n    });\n  }\n\n  if (grant_type === 'refresh_token') {\n    const payload = await verifyToken(refresh_token).catch(() => null);\n    if (!payload || payload.type !== 'refresh') {\n      return unauthorized('Invalid refresh token');\n    }\n    const user = await db.users.findById(payload.sub);\n    return json({\n      access_token: await signToken(user.id, user.role),\n      token_type: 'Bearer',\n      expires_in: 900,\n    });\n  }\n\n  return badRequest('Unsupported grant_type');\n});\n```\n\n## OAuth2 with Third-Party Providers\n\n### Using `@velox/auth`\n\n```bash\nnpm install @velox/auth\n```\n\nConfigure providers:\n\n```typescript\n// lib/auth.ts\nimport { createAuth } from '@velox/auth';\n\nexport const auth = create"
  },
  {
    "file": "pages/guide-database.md",
    "title": "Database Integration",
    "section-id": "guides",
    "keywords": "database, Prisma, DrizzleORM, SQL, ORM, PostgreSQL, database integration",
    "description": "How to integrate databases in Velox using Prisma, DrizzleORM, or raw SQL",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Database Integration\n\nVelox is database-agnostic. This guide covers the three most popular approaches: Prisma (full-featured ORM), DrizzleORM (lightweight TypeScript-first ORM), and raw SQL with a typed query builder.\n\n## Prisma\n\nPrisma is the most popular ORM in the Node.js ecosystem. It provides a schema-first approach, auto-generated type-safe client, and powerful migrations.\n\n### Setup\n\n```bash\nnpm install prisma @prisma/client\nnpx prisma init\n```\n\nThis creates a `prisma/schema.prisma` file. Example schema:\n\n```prisma\n// prisma/schema.prisma\ngenerator client {\n  provider = \"prisma-client-js\"\n}\n\ndatasource db {\n  provider = \"postgresql\"\n  url      = env(\"DATABASE_URL\")\n}\n\nmodel User {\n  id        String   @id @default(cuid())\n  email     String   @unique\n  name      String?\n  role      Role     @default(USER)\n  posts     Post[]\n  createdAt DateTime @default(now())\n  updatedAt DateTime @updatedAt\n}\n\nmodel Post {\n  id          String   @id @default(cuid())\n  title       String\n  slug        String   @unique\n  content     String\n  published   Boolean  @default(false)\n  author      User     @relation(fields: [authorId], references: [id])\n  authorId    String\n  createdAt   DateTime @default(now())\n  updatedAt   DateTime @updatedAt\n}\n\nenum Role {\n  USER\n  ADMIN\n  ANALYST\n}\n```\n\nGenerate and run the initial migration:\n\n```bash\nnpx prisma migrate dev --name init\nnpx prisma generate\n```\n\n### Database Client Singleton\n\nIn a server environment, always reuse a single Prisma client instance:\n\n```typescript\n// lib/db.ts\nimport { PrismaClient } from '@prisma/client';\n\nconst globalForPrisma = globalThis as unknown as { prisma: PrismaClient };\n\nexport const db = globalForPrisma.prisma ?? new PrismaClient({\n  log: process.env.NODE_ENV === 'development' ? ['query', 'warn', 'error'] : ['error'],\n});\n\nif (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = db;\n```\n\n### Usage in Routes\n\n```typescript\n// routes/blog/[slug].velox server block\nimport { db } from '$lib/db';\n\nconst post = await db.post.findUnique({\n  where: { slug: params.slug, published: true },\n  include: { author: { select: { name: true } } },\n});\n\nif (!post) throw notFound();\n```\n\n### Transactions\n\n```typescript\nconst result = await db.$transaction(async (tx) => {\n  const user = await tx.user.create({ data: { email, name } });\n  const profile = await tx.profile.create({ data: { userId: user.id } });\n  return { user, profile };\n});\n```\n\n## DrizzleORM\n\nDrizzleORM is a TypeScript-first ORM with a SQL-like query API and zero overhead.\n\n### Setup\n\n```bash\nnpm install drizzle-orm postgres\nnpm install -D drizzle-kit\n```\n\nDefine your schema in TypeScript:\n\n```typescript\n// lib/schema.ts\nimport { pgTable, text, boolean, timestamp, pgEnum } from 'drizzle-orm/pg-core';\n\nexport const roleEnum = pgEnum('role', ['user', 'admin', 'analyst']);\n\nexport const users = pgTable('users', {\n  id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),\n  email: text('email').notNull().unique(),\n  name: text('name'),\n  role: roleEnum('role').default('user').notNull(),\n  createdAt: timestamp('created_at').defaultNow().notNull(),\n  updatedAt: timestamp('updated_at').defaultNow().notNull(),\n});\n\nexport const posts = pgTable('posts', {\n  id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),\n  title: text('title').notNull(),\n  slug: text('slug').notNull().unique(),\n  content: text('content').notNull(),\n  published: boolean('published').default(false).notNull(),\n  authorId: text('author_id').notNull().references(() => users.id),\n  createdAt: timestamp('created_at').defaultNow().notNull(),\n});\n```\n\n### Database Client\n\n```typescript\n// lib/db.ts\nimport { drizzle } from 'drizzle-orm/postgres-js';\nimport postgres from 'postgres';\nimport * as schema from './schema';\n\nconst client = postgres(process.env.DATABASE_URL!);\nexport const db = drizzle(client, { schema });\n```\n\n### Querying\n\n```typescript\nimport { db } from '$lib/db';\nimport { posts, users } from '$lib/schema';\nimport { eq, and, desc } from 'drizzle-orm';\n\n// Find one\nconst post = await db.query.posts.findFirst({\n  where: and(eq(posts.slug, slug), eq(posts.published, true)),\n  with: { author: { columns: { name: true } } },\n});\n\n// Find many with ordering\nconst recentPosts = await db\n  .select()\n  .from(posts)\n  .where(eq(posts.published, true))\n  .orderBy(desc(posts.createdAt))\n  .limit(10);\n\n// Insert\nconst [newPost] = await db\n  .insert(posts)\n  .values({ title, slug, content, authorId })\n  .returning();\n\n// Update\nawait db\n  .update(posts)\n  .set({ published: true, updatedAt: new Date() })\n  .where(eq(posts.id, postId));\n\n// Delete\nawait db.delete(posts).where(eq(posts.id, postId));\n```\n\n### Migrations\n\nConfigure Drizzle Kit:\n\n```typescript\n// drizzle.config.ts\nimport { defineConfig } from 'drizzle-kit';\n\nexport default defineConfig({\n  schema: './lib/schema.ts',\n  out: './drizzle',\n  dialect: 'postgresql',\n  dbCredentials: { url: process.env.DATABASE_URL! },\n});\n```\n\n```bash\nnpx drizzle-kit generate"
  },
  {
    "file": "pages/guide-i18n.md",
    "title": "Internationalisation",
    "section-id": "guides",
    "keywords": "i18n, internationalisation, localisation, translation, locale routing, multilingual",
    "description": "Setting up internationalisation in Velox \u2014 translation files, locale routing, and pluralisation",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Internationalisation\n\nVelox has built-in internationalisation (i18n) support through `@velox/i18n`. It handles locale detection, URL-based locale routing, typed translation files, and pluralisation.\n\n## Setup\n\n```bash\nnpm install @velox/i18n\n```\n\nConfigure in `velox.config.ts`:\n\n```typescript\nimport { defineConfig } from 'velox';\n\nexport default defineConfig({\n  i18n: {\n    locales: ['en', 'fr', 'de', 'ja'],\n    defaultLocale: 'en',\n    routing: 'prefix-except-default',\n    // 'prefix': all locales get a prefix (/en, /fr, /de, /ja)\n    // 'prefix-except-default': default locale has no prefix\n    // 'domain': different domains per locale\n    messagesDir: 'messages',\n  },\n});\n```\n\n## Translation Files\n\nCreate a `messages/` directory at your project root:\n\n```\nmessages/\n\u251c\u2500\u2500 en.json\n\u251c\u2500\u2500 fr.json\n\u251c\u2500\u2500 de.json\n\u2514\u2500\u2500 ja.json\n```\n\nTranslation files use a flat or nested key structure:\n\n```json\n// messages/en.json\n{\n  \"nav.home\": \"Home\",\n  \"nav.blog\": \"Blog\",\n  \"nav.about\": \"About\",\n  \"home.hero.title\": \"Build faster with Velox\",\n  \"home.hero.subtitle\": \"The TypeScript framework for the modern web\",\n  \"home.cta\": \"Get started\",\n  \"post.readMore\": \"Read more\",\n  \"post.publishedOn\": \"Published on {date}\",\n  \"post.comments\": \"{count, plural, =0{No comments} =1{1 comment} other{# comments}}\",\n  \"auth.loginButton\": \"Log in\",\n  \"auth.logoutButton\": \"Log out\",\n  \"errors.notFound\": \"Page not found\",\n  \"errors.serverError\": \"Something went wrong\"\n}\n```\n\n```json\n// messages/fr.json\n{\n  \"nav.home\": \"Accueil\",\n  \"nav.blog\": \"Blog\",\n  \"nav.about\": \"\u00c0 propos\",\n  \"home.hero.title\": \"Construisez plus vite avec Velox\",\n  \"home.hero.subtitle\": \"Le framework TypeScript pour le web moderne\",\n  \"home.cta\": \"Commencer\",\n  \"post.readMore\": \"Lire la suite\",\n  \"post.publishedOn\": \"Publi\u00e9 le {date}\",\n  \"post.comments\": \"{count, plural, =0{Aucun commentaire} =1{1 commentaire} other{# commentaires}}\",\n  \"auth.loginButton\": \"Se connecter\",\n  \"auth.logoutButton\": \"Se d\u00e9connecter\",\n  \"errors.notFound\": \"Page introuvable\",\n  \"errors.serverError\": \"Une erreur est survenue\"\n}\n```\n\n## Using Translations\n\n### In Server Blocks\n\n```tsx\n---\nimport { useTranslations } from 'velox/i18n';\n\nconst t = useTranslations();\nconst locale = useLocale().locale;\n---\n\n<main>\n  <h1>{t('home.hero.title')}</h1>\n  <p>{t('home.hero.subtitle')}</p>\n  <a href=\"/docs\">{t('home.cta')}</a>\n</main>\n```\n\n### With Parameters\n\n```tsx\n---\nconst t = useTranslations();\nconst publishedDate = new Intl.DateTimeFormat(locale).format(post.createdAt);\n---\n\n<p>{t('post.publishedOn', { date: publishedDate })}</p>\n```\n\n### Pluralisation\n\nVelox uses the ICU message format for pluralisation:\n\n```typescript\nt('post.comments', { count: 0 });   // \"No comments\"\nt('post.comments', { count: 1 });   // \"1 comment\"\nt('post.comments', { count: 42 });  // \"42 comments\"\n```\n\n### In Client Components\n\n```typescript\nimport { useTranslations } from 'velox/i18n/client';\n\nexport default function LikeButton({ postId }: { postId: string }) {\n  const t = useTranslations();\n  const liked = signal(false);\n\n  return (\n    <button onClick={() => liked.value = !liked.value}>\n      {liked.value ? t('post.liked') : t('post.like')}\n    </button>\n  );\n}\n```\n\n## Locale Routing\n\nWith `routing: 'prefix-except-default'` and `defaultLocale: 'en'`:\n\n| URL | Locale |\n|-----|--------|\n| `/` | `en` |\n| `/about` | `en` |\n| `/fr` | `fr` |\n| `/fr/about` | `fr` |\n| `/de/blog/my-post` | `de` |\n\nVelox automatically generates alternate hreflang links for SEO.\n\n## Locale Switcher Component\n\n```tsx\nimport { useLocale, usePathname } from 'velox/i18n/client';\n\nexport default function LocaleSwitcher() {\n  const { locale, locales } = useLocale();\n  const pathname = usePathname();\n\n  return (\n    <div class=\"locale-switcher\">\n      {locales.map(loc => (\n        <a\n          key={loc}\n          href={getLocalizedPath(pathname.value, loc)}\n          class={loc === locale ? 'active' : ''}\n          hreflang={loc}\n        >\n          {getLocaleLabel(loc)}\n        </a>\n      ))}\n    </div>\n  );\n}\n\nfunction getLocaleLabel(locale: string): string {\n  const labels: Record<string, string> = {\n    en: 'English',\n    fr: 'Fran\u00e7ais',\n    de: 'Deutsch',\n    ja: '\u65e5\u672c\u8a9e',\n  };\n  return labels[locale] ?? locale;\n}\n```\n\n## Domain-Based Routing\n\nFor country-specific top-level domains:\n\n```typescript\nexport default defineConfig({\n  i18n: {\n    locales: ['en', 'fr', 'de'],\n    defaultLocale: 'en',\n    routing: 'domain',\n    domains: {\n      en: 'example.com',\n      fr: 'example.fr',\n      de: 'example.de',\n    },\n  },\n});\n```\n\n## Type-Safe Translation Keys\n\nGenerate a TypeScript type for your translation keys:\n\n```bash\nnpx velox i18n:generate-types\n```\n\nThis creates `.velox/types/i18n.d.ts` so that `t('invalid.key')` is a compile-time error.\n\n## RTL Languages\n\nFor right-to-left languages (Arabic, Hebrew, etc.), add the `dir` attribute dynamically:\n\n```tsx\n// layouts/default.velox\n---\nconst { locale } = useLocale();\nconst isRTL = ['ar', 'he', 'fa'].includes(locale);\n---"
  },
  {
    "file": "pages/guide-performance.md",
    "title": "Performance",
    "section-id": "guides",
    "keywords": "performance, code splitting, lazy loading, caching, optimisation, Core Web Vitals",
    "description": "Performance optimisation strategies for Velox apps \u2014 code splitting, lazy loading, and caching",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Performance\n\n![Performance Dashboard](assets/images/performance.jpg)\n\nVelox is designed to be fast by default. The Rust-based compiler handles tree-shaking, code splitting, and asset optimisation automatically. This guide covers the additional strategies you can apply to push your application to peak performance.\n\n## Core Web Vitals Targets\n\nBefore optimising, establish baselines. Aim for:\n\n| Metric | Good | Needs Work |\n|--------|------|-----------|\n| LCP (Largest Contentful Paint) | \u2264 2.5s | > 4.0s |\n| FID / INP (Interaction to Next Paint) | \u2264 200ms | > 500ms |\n| CLS (Cumulative Layout Shift) | \u2264 0.1 | > 0.25 |\n| TTFB (Time to First Byte) | \u2264 800ms | > 1800ms |\n\nUse Velox's built-in analytics to monitor these in production:\n\n```typescript\n// velox.config.ts\nexport default defineConfig({\n  analytics: {\n    webVitals: true,\n    endpoint: '/api/analytics/vitals',\n  },\n});\n```\n\n## Code Splitting\n\nVelox automatically splits your JavaScript bundle by route. Every route gets its own chunk, and shared code is extracted into a common chunk. You do not need to configure this.\n\nFor further control, use dynamic imports:\n\n```typescript\n// Only loads when the user clicks \"Open\"\nconst HeavyEditor = lazy(() => import('./HeavyEditor'));\n\nfunction PostPage() {\n  const isEditing = signal(false);\n  return (\n    <div>\n      <h1>{post.title}</h1>\n      {isEditing.value && (\n        <Suspense fallback={<Skeleton />}>\n          <HeavyEditor post={post} />\n        </Suspense>\n      )}\n      <button onClick={() => isEditing.value = true}>Edit</button>\n    </div>\n  );\n}\n```\n\n## Lazy Hydration\n\nDelay hydration of interactive components until they are needed:\n\n```tsx\n<!-- Hydrate only when the component scrolls into view -->\n<CommentSection client:visible postId={post.id} />\n\n<!-- Hydrate only when the browser is idle -->\n<AnalyticsWidget client:idle />\n\n<!-- Hydrate only when a CSS media query matches -->\n<MobileNav client:media=\"(max-width: 768px)\" />\n\n<!-- Never hydrate \u2014 purely server-rendered, no JS -->\n<StaticSidebar />\n```\n\nThe less JavaScript you ship to the client, the better the INP score.\n\n## Image Optimisation\n\nEnable image optimisation in `velox.config.ts`:\n\n```typescript\nassets: {\n  imageOptimisation: {\n    enabled: true,\n    formats: ['webp', 'avif'],\n    quality: 85,\n    maxWidth: 2000,\n  },\n},\n```\n\nUse the `<Image>` component for automatic width/height and format negotiation:\n\n```tsx\nimport { Image } from 'velox';\n\n<Image\n  src=\"/assets/images/hero.jpg\"\n  alt=\"Hero image\"\n  width={1200}\n  height={400}\n  priority        // preload this image (use for above-the-fold images)\n  sizes=\"(max-width: 768px) 100vw, 1200px\"\n/>\n```\n\nThe `priority` prop adds a `<link rel=\"preload\">` tag to the document head and marks the image as `fetchpriority=\"high\"`, which is the single biggest LCP improvement for image-heavy pages.\n\n## HTTP Caching\n\nSet appropriate `Cache-Control` headers for your routes:\n\n```typescript\n// In a route server block\nresponse.headers.set('Cache-Control', 'public, max-age=3600, stale-while-revalidate=86400');\n\n// Or via config for specific paths\nexport default defineConfig({\n  headers: [\n    {\n      source: '/assets/*',\n      headers: [\n        { key: 'Cache-Control', value: 'public, max-age=31536000, immutable' },\n      ],\n    },\n    {\n      source: '/',\n      headers: [\n        { key: 'Cache-Control', value: 'public, max-age=0, s-maxage=3600, stale-while-revalidate=86400' },\n      ],\n    },\n  ],\n});\n```\n\n## Server-Side Caching\n\nCache expensive computations and database queries:\n\n```typescript\nimport { useCache } from 'velox/server';\n\nconst cache = useCache();\n\nasync function getPopularPosts() {\n  const cached = await cache.get<Post[]>('posts:popular');\n  if (cached) return cached;\n\n  const posts = await db.posts.findMany({\n    where: { published: true },\n    orderBy: { viewCount: 'desc' },\n    take: 10,\n  });\n\n  await cache.set('posts:popular', posts, { ttl: 300 }); // 5 minutes\n  return posts;\n}\n```\n\n## Database Query Optimisation\n\nCommon patterns that prevent N+1 queries:\n\n```typescript\n// Bad: N+1 query\nconst posts = await db.post.findMany();\nconst postsWithAuthors = await Promise.all(\n  posts.map(p => db.user.findById(p.authorId)) // N extra queries!\n);\n\n// Good: single query with include\nconst postsWithAuthors = await db.post.findMany({\n  include: { author: { select: { id: true, name: true } } },\n});\n```\n\nAdd indexes for commonly filtered columns:\n\n```sql\n-- In a migration\nCREATE INDEX CONCURRENTLY idx_posts_published_created\n  ON posts (published, created_at DESC)\n  WHERE published = true;\n```\n\n## Edge Deployment\n\nDeploy to edge locations close to your users:\n\n```typescript\n// velox.config.ts\nexport default defineConfig({\n  build: {\n    target: 'edge',\n  },\n});\n```\n\nEdge-compatible routes must use Web APIs only:\n\n```typescript\n// \u2705 Edge-compatible\nimport { defineHandler } from 'velox/server';\nexport const GET = defineHandler(async (req) => {\n  const data = await fetch('https://api.example.com/data');\n  "
  },
  {
    "file": "pages/guide-testing.md",
    "title": "Testing",
    "section-id": "guides",
    "keywords": "testing, unit tests, integration tests, E2E, Playwright, Vitest, testing strategy",
    "description": "Testing Velox applications with unit tests, integration tests, and end-to-end tests using Playwright",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Testing\n\nVelox integrates with Vitest for unit and integration tests, and Playwright for end-to-end tests. The `@velox/test` package provides additional test utilities tailored for Velox's server blocks and API routes.\n\n## Setup\n\n```bash\nnpm install -D vitest @velox/test @playwright/test\nnpx playwright install\n```\n\nAdd test scripts to `package.json`:\n\n```json\n{\n  \"scripts\": {\n    \"test\": \"vitest\",\n    \"test:ui\": \"vitest --ui\",\n    \"test:e2e\": \"playwright test\",\n    \"test:coverage\": \"vitest --coverage\"\n  }\n}\n```\n\nConfigure Vitest:\n\n```typescript\n// vitest.config.ts\nimport { defineConfig } from 'vitest/config';\nimport { veloxTestPlugin } from '@velox/test';\n\nexport default defineConfig({\n  plugins: [veloxTestPlugin()],\n  test: {\n    environment: 'node',\n    globals: true,\n    setupFiles: ['./tests/setup.ts'],\n    coverage: {\n      provider: 'v8',\n      reporter: ['text', 'lcov'],\n    },\n  },\n});\n```\n\n## Unit Tests\n\n### Testing Utility Functions\n\n```typescript\n// lib/formatters.ts\nexport function formatCurrency(amount: number, currency = 'USD'): string {\n  return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount);\n}\n```\n\n```typescript\n// tests/unit/formatters.test.ts\nimport { describe, it, expect } from 'vitest';\nimport { formatCurrency } from '$lib/formatters';\n\ndescribe('formatCurrency', () => {\n  it('formats USD amounts', () => {\n    expect(formatCurrency(1000)).toBe('$1,000.00');\n    expect(formatCurrency(9.99)).toBe('$9.99');\n  });\n\n  it('formats other currencies', () => {\n    expect(formatCurrency(1000, 'EUR')).toBe('\u20ac1,000.00');\n  });\n\n  it('handles zero', () => {\n    expect(formatCurrency(0)).toBe('$0.00');\n  });\n});\n```\n\n### Testing Components\n\n```tsx\n// tests/unit/Counter.test.tsx\nimport { describe, it, expect } from 'vitest';\nimport { render, fireEvent } from '@velox/test';\nimport Counter from '$components/Counter';\n\ndescribe('Counter', () => {\n  it('renders with initial value', () => {\n    const { getByText } = render(<Counter initialValue={5} />);\n    expect(getByText('5')).toBeTruthy();\n  });\n\n  it('increments on button click', async () => {\n    const { getByText, getByRole } = render(<Counter initialValue={0} />);\n    await fireEvent.click(getByRole('button', { name: /increment/i }));\n    expect(getByText('1')).toBeTruthy();\n  });\n\n  it('decrements below initial value', async () => {\n    const { getByText, getByRole } = render(<Counter initialValue={3} />);\n    await fireEvent.click(getByRole('button', { name: /decrement/i }));\n    expect(getByText('2')).toBeTruthy();\n  });\n});\n```\n\n## Integration Tests\n\n### Testing API Routes\n\nThe `createTestServer` utility starts a real Velox server for integration testing:\n\n```typescript\n// tests/integration/api/users.test.ts\nimport { describe, it, expect, beforeAll, afterAll } from 'vitest';\nimport { createTestServer } from '@velox/test';\nimport { db } from '$lib/db';\n\nlet server: Awaited<ReturnType<typeof createTestServer>>;\n\nbeforeAll(async () => {\n  server = await createTestServer({ seed: true });\n});\n\nafterAll(async () => {\n  await server.stop();\n  await db.$disconnect();\n});\n\ndescribe('GET /api/users', () => {\n  it('returns all users', async () => {\n    const res = await server.inject({\n      method: 'GET',\n      url: '/api/users',\n      headers: { Authorization: `Bearer ${server.getAdminToken()}` },\n    });\n\n    expect(res.status).toBe(200);\n    const body = await res.json();\n    expect(Array.isArray(body)).toBe(true);\n    expect(body.length).toBeGreaterThan(0);\n  });\n\n  it('returns 401 without auth', async () => {\n    const res = await server.inject({ method: 'GET', url: '/api/users' });\n    expect(res.status).toBe(401);\n  });\n});\n\ndescribe('POST /api/users', () => {\n  it('creates a new user', async () => {\n    const res = await server.inject({\n      method: 'POST',\n      url: '/api/users',\n      body: { email: 'new@example.com', name: 'New User' },\n      headers: { Authorization: `Bearer ${server.getAdminToken()}` },\n    });\n\n    expect(res.status).toBe(201);\n    const user = await res.json();\n    expect(user.email).toBe('new@example.com');\n    expect(user.id).toBeDefined();\n  });\n\n  it('rejects duplicate email', async () => {\n    await server.inject({\n      method: 'POST',\n      url: '/api/users',\n      body: { email: 'dup@example.com', name: 'First' },\n      headers: { Authorization: `Bearer ${server.getAdminToken()}` },\n    });\n\n    const res = await server.inject({\n      method: 'POST',\n      url: '/api/users',\n      body: { email: 'dup@example.com', name: 'Second' },\n      headers: { Authorization: `Bearer ${server.getAdminToken()}` },\n    });\n\n    expect(res.status).toBe(409);\n  });\n});\n```\n\n### Testing Database Operations\n\n```typescript\n// tests/integration/db/posts.test.ts\nimport { describe, it, expect, beforeEach } from 'vitest';\nimport { db } from '$lib/db';\nimport { createTestUser, createTestPost } from '../factories';\n\nbeforeEach(async () => {\n  await db.$executeRaw`TRUNCATE posts, users RESTART IDENTITY CASC"
  },
  {
    "file": "pages/index.md",
    "title": "Introduction",
    "section-id": "getting-started",
    "keywords": "velox, framework, typescript, javascript, full-stack, introduction",
    "description": "An introduction to Velox, the high-performance TypeScript web framework",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Introduction to Velox\n\n![Velox Framework Hero](assets/images/hero.jpg)\n\nVelox is a high-performance, full-stack TypeScript and JavaScript web framework built for developers who refuse to compromise between developer experience and production performance. Combining a file-based routing model inspired by the best parts of Next.js, an island-based rendering architecture inspired by Astro, and a Rust-powered build toolchain that makes cold starts and hot reloads feel instantaneous, Velox occupies a unique position in the modern web ecosystem.\n\n## Why Velox?\n\nThe JavaScript ecosystem is rich, yet fragmented. Some frameworks offer outstanding developer experience but struggle with raw performance at scale. Others are extremely fast but require significant configuration overhead before you can write your first component. Velox was created to close that gap.\n\nThe core philosophy of Velox can be summarised in three words: **fast by default**. Every architectural decision \u2014 from the Rust-based bundler (Velocitor) to the zero-runtime component model \u2014 is made to ensure that your production application runs as efficiently as possible without requiring manual intervention from the developer.\n\n## Key Features\n\n### Rust-Powered Toolchain (Velocitor)\n\nThe Velox build system, internally called Velocitor, is written in Rust. It handles TypeScript transpilation, module bundling, tree-shaking, code splitting, and asset optimisation in a single pass. On modern hardware, a full production build of a medium-sized application typically completes in under three seconds. Incremental rebuilds during development are sub-50ms for most file changes.\n\n### File-Based Routing\n\nVelox uses a file-based routing system. Any `.velox` or `.tsx` file placed under the `routes/` directory automatically becomes a route. Dynamic segments use `[param]` notation, optional segments use `[[param]]`, and catch-all routes use `[...rest]`. No manual route registration is ever required.\n\n### Islands Architecture\n\nBy default, Velox renders pages entirely on the server. Interactive components are \"islands\" \u2014 explicitly opt-in to client-side hydration using the `client:*` directive. This means your pages ship zero JavaScript by default; you add interactivity exactly where it is needed.\n\n### Hybrid Rendering Modes\n\nVelox supports four rendering strategies per route:\n- **SSR (Server-Side Rendering)** \u2014 rendered fresh on every request\n- **SSG (Static Site Generation)** \u2014 pre-rendered at build time\n- **ISR (Incremental Static Regeneration)** \u2014 statically generated but revalidated on a schedule\n- **CSR (Client-Side Rendering)** \u2014 fully client-rendered for dashboard-style pages\n\nYou can mix rendering modes across routes within a single project.\n\n### TypeScript First\n\nVelox is written in TypeScript and treats TypeScript as a first-class citizen. Configuration files, route handlers, middleware, and components all benefit from full type inference. There is no separate type-generation step required.\n\n### Edge-Ready\n\nVelox applications are deployable to Cloudflare Workers, Vercel Edge, and similar runtimes out of the box. The framework's core HTTP runtime has no Node.js-specific dependencies and operates on standard Web APIs (`Request`, `Response`, `fetch`, `crypto`), making edge deployment trivially simple.\n\n### Built-In Middleware System\n\nThe middleware system allows you to intercept and transform requests and responses at multiple points in the pipeline. Auth, rate limiting, logging, CORS, and header manipulation are all achievable through composable middleware functions.\n\n## How Velox Compares\n\n| Feature | Velox | Next.js | Astro | Remix |\n|---|---|---|---|---|\n| Build system | Rust (Velocitor) | Webpack/Turbopack | Vite | Vite |\n| Default JS shipped | Zero | Varies | Zero | Varies |\n| Rendering modes | SSR/SSG/ISR/CSR | SSR/SSG/ISR | SSG/SSR | SSR |\n| Full-stack API routes | Yes | Yes | Yes | Yes |\n| File-based routing | Yes | Yes | Yes | No |\n| TypeScript support | First-class | First-class | First-class | First-class |\n| Edge runtime | Native | Adapter | Adapter | Adapter |\n\n## Who Is Velox For?\n\nVelox is well suited for:\n\n- Teams building content-heavy marketing sites that need fast initial load times with selective interactivity\n- Full-stack application teams who want a unified framework for frontend and backend\n- Engineers at high-scale companies who need ISR and edge caching to serve global audiences\n- Developers migrating from Next.js who want faster build times without giving up the Next.js mental model\n\nVelox is perhaps not the best choice if you are building a highly stateful single-page application that is mostly client-rendered \u2014 in that case a pure SPA framework may be simpler.\n\n## Getting Started\n\nThe quickest way to get started with Velox is to install the CLI and scaffold a new project:\n\n```bash\nnpm create velox@latest my-app\ncd my-app\nnpm run dev\n```\n\nYour new project will be running at `http://localhost:3700` in under ten seconds.\n\nRead on to the "
  },
  {
    "file": "pages/installation.md",
    "title": "Installation",
    "section-id": "getting-started",
    "keywords": "install, setup, npm, yarn, pnpm, bun, node, requirements",
    "description": "How to install Velox and set up your development environment",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Installation\n\nThis page covers everything you need to install Velox and get your development environment ready to build production applications.\n\n## System Requirements\n\nBefore installing Velox, ensure your system meets the following requirements:\n\n| Requirement | Minimum Version | Recommended |\n|---|---|---|\n| Node.js | 20.0.0 | 22.x LTS |\n| npm | 9.0.0 | 10.x |\n| Operating system | macOS 12, Ubuntu 22.04, Windows 10 | Latest stable |\n| RAM | 2 GB | 8 GB+ |\n| Disk space | 500 MB | 2 GB (for caches) |\n\nVelox's Rust-based build system (Velocitor) ships as a pre-compiled binary for macOS (arm64 + x86_64), Linux (x86_64 + aarch64), and Windows (x86_64). You do **not** need a Rust toolchain installed on your machine.\n\n## Installing the Velox CLI\n\nThe Velox CLI (`velox`) is the primary tool for scaffolding projects, running the development server, and triggering builds. Install it globally with your preferred package manager:\n\n```bash\n# npm\nnpm install -g velox-cli\n\n# yarn\nyarn global add velox-cli\n\n# pnpm\npnpm add -g velox-cli\n\n# bun\nbun add -g velox-cli\n```\n\nAfter installation, verify the CLI is available:\n\n```bash\nvelox --version\n# velox-cli v1.4.0\n```\n\n## Creating a New Project\n\n### Using `create-velox` (Recommended)\n\nThe easiest way to start a new Velox project is through the `create-velox` initialiser. It interactively walks you through project setup:\n\n```bash\nnpm create velox@latest\n```\n\nYou will be asked:\n1. **Project name** \u2014 used as the directory name and initial package name\n2. **Template** \u2014 choose from `minimal`, `blog`, `docs`, `dashboard`, or `e-commerce`\n3. **TypeScript or JavaScript** \u2014 TypeScript is strongly recommended\n4. **Package manager** \u2014 the scaffolder will use this for the initial install\n\nFor non-interactive use, pass flags directly:\n\n```bash\nnpm create velox@latest my-app -- --template minimal --ts --pm pnpm\n```\n\n### Manual Installation\n\nIf you prefer to configure everything from scratch:\n\n```bash\nmkdir my-app && cd my-app\nnpm init -y\nnpm install velox\nnpm install -D velox-cli typescript @types/node\n```\n\nCreate a minimal `velox.config.ts`:\n\n```typescript\nimport { defineConfig } from 'velox';\n\nexport default defineConfig({\n  app: {\n    name: 'my-app',\n  },\n});\n```\n\n## Installing Dependencies in an Existing Project\n\nIf you are adding Velox to an existing TypeScript project:\n\n```bash\nnpm install velox\nnpm install -D velox-cli\n```\n\nThen add the following scripts to your `package.json`:\n\n```json\n{\n  \"scripts\": {\n    \"dev\": \"velox dev\",\n    \"build\": \"velox build\",\n    \"start\": \"velox start\",\n    \"preview\": \"velox preview\"\n  }\n}\n```\n\n## Node Version Management\n\nWe recommend using a Node version manager to ensure you always have the correct version. Popular options:\n\n```bash\n# nvm (macOS/Linux)\nnvm install 22\nnvm use 22\n\n# fnm (fast, cross-platform)\nfnm install 22\nfnm use 22\n\n# volta (pins versions per project)\nvolta install node@22\n```\n\nYou can also pin the Node version for your project by adding a `.nvmrc` or `.node-version` file:\n\n```\n22\n```\n\n## Environment Variables\n\nVelox reads environment variables from `.env` files at the project root. The following files are loaded in order (later files override earlier ones):\n\n| File | Loaded in | Committed to git? |\n|---|---|---|\n| `.env` | All environments | Usually yes (no secrets) |\n| `.env.local` | All environments | No (gitignored) |\n| `.env.development` | `velox dev` only | Usually yes |\n| `.env.production` | `velox build` / `velox start` | Usually yes |\n| `.env.test` | Test runs | Usually yes |\n\nVariables prefixed with `PUBLIC_` are exposed to the browser. All other variables remain server-side only.\n\n```bash\n# .env\nPUBLIC_APP_NAME=My Velox App\nDATABASE_URL=postgres://localhost:5432/mydb\nSECRET_API_KEY=do-not-expose-this\n```\n\n## Updating Velox\n\nTo update Velox to the latest version within your project:\n\n```bash\nnpm install velox@latest\nnpm install -D velox-cli@latest\n```\n\nTo check whether updates are available without applying them:\n\n```bash\nvelox upgrade --check\n```\n\n## Troubleshooting Installation\n\n**`velox` command not found after global install**\nEnsure your package manager's global bin directory is in your `PATH`. For npm, run `npm config get prefix` and add the `bin` subdirectory to your shell profile.\n\n**Velocitor binary fails to run on Linux**\nSome minimal Linux environments (e.g., Alpine Linux) may be missing the `glibc` version Velocitor requires. Install `glibc` compatibility libraries or use the musl build:\n\n```bash\nnpm install velox@latest --velox-binary-variant=musl\n```\n\n**Windows Defender flags the Velocitor binary**\nThis is a false positive. Add an exclusion for your project's `node_modules/.velox-bin/` directory.\n\nNext, follow the [Quick Start](quick-start.md) guide to build your first Velox application."
  },
  {
    "file": "pages/layouts.md",
    "title": "Layouts",
    "section-id": "core-concepts",
    "keywords": "layouts, nested layouts, shared layouts, layout groups, _layout, slots",
    "description": "How to use nested layouts, shared layouts, and layout groups in Velox",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Layouts\n\nLayouts define the structural shell around your page content \u2014 navigation headers, sidebars, footers, and anything else that persists across multiple pages. Velox provides a flexible, composable layout system built directly into the file-based router.\n\n## Default Layout\n\nThe file `layouts/default.velox` is the root layout applied to all routes unless overridden:\n\n```tsx\n// layouts/default.velox\n---\nimport Header from '../components/Header.tsx';\nimport Footer from '../components/Footer.tsx';\n---\n\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <title>{meta.title} \u2014 My App</title>\n    <meta name=\"description\" content={meta.description} />\n    <link rel=\"stylesheet\" href=\"/styles/global.css\" />\n  </head>\n  <body>\n    <Header />\n    <main id=\"main-content\">\n      <slot />\n    </main>\n    <Footer />\n  </body>\n</html>\n```\n\nThe `<slot />` element is where the current page's content is injected. Layout files receive `meta` (the exports from the route's server block) and `params` automatically.\n\n## Route-Level Layout Override\n\nA route can specify a different layout using the `layout` export in its server block:\n\n```tsx\n---\nexport const layout = 'minimal'; // uses layouts/minimal.velox\nexport const meta = { title: 'Login' };\n---\n\n<div class=\"login-container\">\n  <LoginForm />\n</div>\n```\n\nSet `layout` to `false` to render the page with no layout at all:\n\n```tsx\n---\nexport const layout = false; // bare HTML response\n---\n\n<!DOCTYPE html>\n<html>...</html>\n```\n\n## `_layout.velox` \u2014 Directory Scoped Layouts\n\nPlace a `_layout.velox` file inside any `routes/` subdirectory to apply a layout to all routes in that directory and its subdirectories:\n\n```\nroutes/\n\u251c\u2500\u2500 _layout.velox            \u2190 root layout (all routes)\n\u251c\u2500\u2500 index.velox\n\u251c\u2500\u2500 about.velox\n\u2514\u2500\u2500 admin/\n    \u251c\u2500\u2500 _layout.velox        \u2190 admin layout (only /admin/* routes)\n    \u251c\u2500\u2500 index.velox\n    \u2514\u2500\u2500 users/\n        \u251c\u2500\u2500 _layout.velox    \u2190 users layout (only /admin/users/* routes)\n        \u2514\u2500\u2500 index.velox\n```\n\nLayouts nest \u2014 the admin layout wraps its content inside the root layout's `<slot />`, and the users layout wraps inside the admin layout's `<slot />`:\n\n```\nRoot Layout\n  \u2514\u2500\u2500 Admin Layout\n        \u2514\u2500\u2500 Users Layout\n              \u2514\u2500\u2500 Page Content\n```\n\n### Admin Layout Example\n\n```tsx\n// routes/admin/_layout.velox\n---\nimport AdminNav from '../../components/AdminNav.tsx';\n\nconst user = request.context.get('user');\nexport const meta = { title: 'Admin' };\n---\n\n<div class=\"admin-shell\">\n  <AdminNav user={user} />\n  <div class=\"admin-content\">\n    <slot />\n  </div>\n</div>\n```\n\n## Layout Groups\n\nWrap a directory in parentheses to create a **route group** that applies a shared layout without affecting the URL:\n\n```\nroutes/\n\u251c\u2500\u2500 (public)/\n\u2502   \u251c\u2500\u2500 _layout.velox    \u2190 marketing/public layout\n\u2502   \u251c\u2500\u2500 index.velox      \u2192  /\n\u2502   \u2514\u2500\u2500 pricing.velox    \u2192  /pricing\n\u2514\u2500\u2500 (app)/\n    \u251c\u2500\u2500 _layout.velox    \u2190 application layout (requires auth)\n    \u251c\u2500\u2500 dashboard.velox  \u2192  /dashboard\n    \u2514\u2500\u2500 settings.velox   \u2192  /settings\n```\n\nBoth `/` and `/pricing` use the public layout. Both `/dashboard` and `/settings` use the app layout. The group name `(public)` and `(app)` never appear in the URL.\n\n## Shared Layout Components\n\nFor UI elements shared between multiple layouts (a navigation bar used by both the public and admin layouts, for example), extract them as regular components:\n\n```tsx\n// components/TopNav.tsx\ninterface TopNavProps {\n  links: { label: string; href: string }[];\n  user?: User | null;\n}\n\nexport default function TopNav({ links, user }: TopNavProps) {\n  return (\n    <nav class=\"top-nav\">\n      <ul>\n        {links.map(link => (\n          <li><a href={link.href}>{link.label}</a></li>\n        ))}\n      </ul>\n      {user ? <UserMenu user={user} /> : <a href=\"/login\">Log in</a>}\n    </nav>\n  );\n}\n```\n\nUse it in both layouts:\n\n```tsx\n// layouts/default.velox\n<TopNav links={publicLinks} user={null} />\n\n// routes/admin/_layout.velox\n<TopNav links={adminLinks} user={user} />\n```\n\n## Data in Layouts\n\n`_layout.velox` files have their own server block and can fetch data independently:\n\n```tsx\n// routes/dashboard/_layout.velox\n---\nimport { db } from '$lib/db';\n\nconst user = request.context.get('user');\nconst notifications = await db.notifications.findUnread(user.id);\n---\n\n<div class=\"dashboard-shell\">\n  <DashboardNav notifications={notifications} />\n  <slot />\n</div>\n```\n\nLayout data is fetched in parallel with page data \u2014 there is no waterfall.\n\n## Parallel Slots\n\nFor complex layouts with multiple content regions, use named parallel slots:\n\n```tsx\n// A layout that accepts both main content and a sidebar\n---\nexport const slots = ['default', 'sidebar'];\n---\n\n<div class=\"two-column\">\n  <aside class=\"sidebar\">\n    <slot name=\"sidebar\" />\n  </aside>\n  <main>\n    <slot />\n  </main>\n</div>\n```\n\nFill the named slot from the page:\n\n```tsx\n---\nexport const layout = 'two-column';\n---\n\n<!-- Default slot content -->"
  },
  {
    "file": "pages/middleware.md",
    "title": "Middleware",
    "section-id": "core-concepts",
    "keywords": "middleware, request pipeline, auth middleware, rate limiting, CORS, headers",
    "description": "How to use and write Velox middleware for request/response transformation",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Middleware\n\nMiddleware in Velox is a function that intercepts HTTP requests before they reach a route handler and can transform both the request and the response. Middleware is composable, typed, and supports async operations.\n\n## How Middleware Works\n\nThe Velox request pipeline processes a request in the following order:\n\n1. **Global middleware** \u2014 applied to every request\n2. **Path-scoped middleware** \u2014 applied based on route matching\n3. **Route handler** \u2014 the actual page or API route\n4. **Response middleware** \u2014 runs on the way out (in reverse order)\n\n```\nRequest\n  \u2193\n[Global Middleware 1]\n  \u2193\n[Global Middleware 2]\n  \u2193\n[Path Middleware]\n  \u2193\n[Route Handler]\n  \u2193\n[Response (in reverse)]\n```\n\n## Writing Middleware\n\nCreate a middleware file in the `middleware/` directory. A middleware function receives the `request` and a `next` function. Call `next()` to pass control to the next middleware or the route handler:\n\n```typescript\n// middleware/logger.ts\nimport { defineMiddleware } from 'velox/server';\n\nexport default defineMiddleware(async ({ request, next }) => {\n  const start = Date.now();\n  const response = await next();\n  const duration = Date.now() - start;\n  console.log(`${request.method} ${request.url} \u2014 ${response.status} (${duration}ms)`);\n  return response;\n});\n```\n\n## Configuring Middleware\n\nRegister middleware in `velox.config.ts`:\n\n```typescript\nimport { defineConfig } from 'velox';\n\nexport default defineConfig({\n  middleware: [\n    { path: '*', handler: './middleware/logger' },\n    { path: '/admin/*', handler: './middleware/auth' },\n    { path: '/api/*', handler: './middleware/rateLimit' },\n  ],\n});\n```\n\nOr, use a `middleware.ts` file at the project root for global middleware:\n\n```typescript\n// middleware.ts (project root \u2014 applies to all routes automatically)\nimport { defineMiddleware } from 'velox/server';\n\nexport default defineMiddleware(async ({ request, next }) => {\n  // runs on every request\n  return next();\n});\n```\n\n## Authentication Middleware\n\n```typescript\n// middleware/auth.ts\nimport { defineMiddleware, redirect } from 'velox/server';\nimport { verifyJWT } from '$lib/auth';\n\nexport default defineMiddleware(async ({ request, next }) => {\n  const token = request.cookies.get('session')?.value\n    ?? request.headers.get('Authorization')?.replace('Bearer ', '');\n\n  if (!token) {\n    return redirect('/login?next=' + encodeURIComponent(request.url));\n  }\n\n  let user;\n  try {\n    user = await verifyJWT(token);\n  } catch {\n    return redirect('/login?error=invalid_token');\n  }\n\n  // Attach user to request context for downstream handlers\n  request.context.set('user', user);\n\n  return next();\n});\n```\n\nAccess the context in your route:\n\n```typescript\n// routes/dashboard.velox server block\nconst user = request.context.get('user');\n```\n\n## Rate Limiting Middleware\n\n```typescript\n// middleware/rateLimit.ts\nimport { defineMiddleware } from 'velox/server';\n\nconst counters = new Map<string, { count: number; resetAt: number }>();\nconst WINDOW_MS = 60_000; // 1 minute\nconst MAX_REQUESTS = 100;\n\nexport default defineMiddleware(async ({ request, next }) => {\n  const ip = request.headers.get('CF-Connecting-IP')\n    ?? request.headers.get('X-Forwarded-For')\n    ?? 'unknown';\n\n  const now = Date.now();\n  const counter = counters.get(ip) ?? { count: 0, resetAt: now + WINDOW_MS };\n\n  if (now > counter.resetAt) {\n    counter.count = 0;\n    counter.resetAt = now + WINDOW_MS;\n  }\n\n  counter.count++;\n  counters.set(ip, counter);\n\n  if (counter.count > MAX_REQUESTS) {\n    return new Response('Too Many Requests', {\n      status: 429,\n      headers: {\n        'Retry-After': String(Math.ceil((counter.resetAt - now) / 1000)),\n        'X-RateLimit-Limit': String(MAX_REQUESTS),\n        'X-RateLimit-Remaining': '0',\n      },\n    });\n  }\n\n  const response = await next();\n  response.headers.set('X-RateLimit-Limit', String(MAX_REQUESTS));\n  response.headers.set('X-RateLimit-Remaining', String(MAX_REQUESTS - counter.count));\n  return response;\n});\n```\n\n## CORS Middleware\n\n```typescript\n// middleware/cors.ts\nimport { defineMiddleware } from 'velox/server';\n\nconst ALLOWED_ORIGINS = process.env.ALLOWED_ORIGINS?.split(',') ?? ['*'];\n\nexport default defineMiddleware(async ({ request, next }) => {\n  const origin = request.headers.get('Origin') ?? '';\n  const isAllowed = ALLOWED_ORIGINS.includes('*') || ALLOWED_ORIGINS.includes(origin);\n\n  if (request.method === 'OPTIONS') {\n    // Preflight response\n    return new Response(null, {\n      status: 204,\n      headers: corsHeaders(origin, isAllowed),\n    });\n  }\n\n  const response = await next();\n\n  if (isAllowed) {\n    for (const [key, value] of Object.entries(corsHeaders(origin, true))) {\n      response.headers.set(key, value);\n    }\n  }\n\n  return response;\n});\n\nfunction corsHeaders(origin: string, allowed: boolean) {\n  if (!allowed) return {};\n  return {\n    'Access-Control-Allow-Origin': origin,\n    'Access-Control-Allow-Methods': 'GET, POST, PUT, PATCH, DELETE, OPTIONS',\n    'Access-Co"
  },
  {
    "file": "pages/project-structure.md",
    "title": "Project Structure",
    "section-id": "getting-started",
    "keywords": "project structure, directory layout, files, folders, architecture",
    "description": "A detailed explanation of every file and folder in a Velox project",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Project Structure\n\n![Velox Architecture](assets/images/architecture.jpg)\n\nUnderstanding the Velox project structure is key to working effectively with the framework. This page explains the purpose of every directory and file you will encounter in a standard Velox project.\n\n## Top-Level Layout\n\n```\nmy-velox-app/\n\u251c\u2500\u2500 routes/              \u2190 all pages and API routes\n\u251c\u2500\u2500 layouts/             \u2190 shared page layouts\n\u251c\u2500\u2500 components/          \u2190 reusable UI components\n\u251c\u2500\u2500 lib/                 \u2190 shared server-side utilities\n\u251c\u2500\u2500 middleware/          \u2190 request/response interceptors\n\u251c\u2500\u2500 public/              \u2190 static assets (copied verbatim)\n\u251c\u2500\u2500 styles/              \u2190 global CSS and design tokens\n\u251c\u2500\u2500 tests/               \u2190 test files\n\u251c\u2500\u2500 .velox/              \u2190 build cache and output (gitignored)\n\u251c\u2500\u2500 velox.config.ts      \u2190 framework configuration\n\u251c\u2500\u2500 tsconfig.json        \u2190 TypeScript configuration\n\u251c\u2500\u2500 package.json\n\u2514\u2500\u2500 .env                 \u2190 environment variables\n```\n\n## `routes/`\n\nThis is the most important directory. Every file in `routes/` maps to a URL path unless prefixed with `_` (underscore files are ignored by the router).\n\n### Page Routes\n\nFiles ending in `.velox` or `.tsx` become page routes:\n\n```\nroutes/\n\u251c\u2500\u2500 index.velox          \u2192  /\n\u251c\u2500\u2500 about.velox          \u2192  /about\n\u251c\u2500\u2500 blog/\n\u2502   \u251c\u2500\u2500 index.velox      \u2192  /blog\n\u2502   \u2514\u2500\u2500 [slug].velox     \u2192  /blog/:slug\n\u251c\u2500\u2500 docs/\n\u2502   \u2514\u2500\u2500 [...path].velox  \u2192  /docs/* (catch-all)\n\u2514\u2500\u2500 _components/         \u2190 underscore prefix: ignored by router\n    \u2514\u2500\u2500 Header.tsx\n```\n\n### API Routes\n\nFiles suffixed with `+server.ts` become API routes. They export HTTP method handlers:\n\n```\nroutes/\n\u2514\u2500\u2500 api/\n    \u251c\u2500\u2500 users+server.ts          \u2192  /api/users\n    \u2514\u2500\u2500 users/[id]+server.ts     \u2192  /api/users/:id\n```\n\n### Special Files\n\n| File | Purpose |\n|---|---|\n| `_error.velox` | Custom error page (404, 500) in any directory |\n| `_loading.velox` | Loading state shown during route transitions |\n| `_layout.velox` | Layout that wraps all sibling routes |\n\n## `layouts/`\n\nLayout files define the shell that wraps your page content. A layout receives a `<slot />` where the page content is injected.\n\n```tsx\n// layouts/default.velox\n---\nimport Header from '../components/Header.tsx';\nimport Footer from '../components/Footer.tsx';\n---\n\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>{meta.title}</title>\n  </head>\n  <body>\n    <Header />\n    <slot />\n    <Footer />\n  </body>\n</html>\n```\n\nThe default layout (`layouts/default.velox`) wraps all routes unless a route specifies a different layout via the `layout` frontmatter property.\n\n## `components/`\n\nReusable UI components that can be used in routes and layouts. Components do not have server blocks \u2014 they are purely presentational (though they can accept server-fetched data as props).\n\n```\ncomponents/\n\u251c\u2500\u2500 Header.tsx\n\u251c\u2500\u2500 Footer.tsx\n\u251c\u2500\u2500 Button.tsx\n\u251c\u2500\u2500 ui/\n\u2502   \u251c\u2500\u2500 Card.tsx\n\u2502   \u2514\u2500\u2500 Modal.tsx\n\u2514\u2500\u2500 forms/\n    \u251c\u2500\u2500 Input.tsx\n    \u2514\u2500\u2500 Select.tsx\n```\n\n## `lib/`\n\nServer-side utility modules \u2014 database clients, external API helpers, auth utilities. Code in `lib/` is never bundled for the client unless explicitly imported from a client-side component.\n\n```\nlib/\n\u251c\u2500\u2500 db.ts           \u2190 database connection\n\u251c\u2500\u2500 auth.ts         \u2190 authentication helpers\n\u251c\u2500\u2500 email.ts        \u2190 email sending\n\u2514\u2500\u2500 cache.ts        \u2190 caching utilities\n```\n\n## `middleware/`\n\nMiddleware functions execute on every matching request before the route handler runs. Middleware files are auto-loaded based on path:\n\n```\nmiddleware/\n\u251c\u2500\u2500 auth.ts          \u2190 applies to all routes (no path suffix)\n\u2514\u2500\u2500 admin.ts         \u2190 must be explicitly referenced in velox.config.ts\n```\n\n## `public/`\n\nStatic files in `public/` are served at the root path without transformation. A file at `public/robots.txt` is served at `/robots.txt`. Use this for favicons, `manifest.json`, `sitemap.xml`, and static images that do not need optimisation.\n\n## `styles/`\n\nGlobal stylesheets. Velox supports CSS Modules (`.module.css`), plain CSS, and Sass (`.scss`) if the `@velox/sass` plugin is installed. The file `styles/global.css` is automatically injected into every page.\n\n```\nstyles/\n\u251c\u2500\u2500 global.css       \u2190 injected automatically\n\u251c\u2500\u2500 tokens.css       \u2190 CSS custom properties / design tokens\n\u2514\u2500\u2500 reset.css        \u2190 CSS reset or normalise\n```\n\n## `.velox/`\n\nGenerated directory \u2014 **never commit this to git**. Contains:\n\n- `.velox/cache/` \u2014 Velocitor's incremental build cache (keyed by content hash)\n- `.velox/output/` \u2014 production build output\n- `.velox/tmp/` \u2014 temporary files used during development\n\nAdd `.velox/` to your `.gitignore`:\n\n```\n# .gitignore\n.velox/\n.env.local\nnode_modules/\n```\n\n## `velox.config.ts`\n\nThe central configuration file for the framework. See the full [Configuration](configuration.md) reference for every available option. A minimal example:\n\n```typescript\nimport { defineConfig } from 'velox';\n\nexport default defineConfig({\n  app: {\n    name: 'my-velox-app',\n    baseUrl: process.env.PUBLIC_BASE_URL ?? 'http://localhost:3700',\n  },"
  },
  {
    "file": "pages/quick-start.md",
    "title": "Quick Start",
    "section-id": "getting-started",
    "keywords": "quick start, first app, hello world, dev server, file structure",
    "description": "Build your first Velox application from scratch in minutes",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Quick Start\n\nThis guide walks you through creating a working Velox application from zero. By the end you will have a running dev server, a couple of pages with navigation between them, and an API route returning JSON.\n\n## Step 1 \u2014 Scaffold the Project\n\n```bash\nnpm create velox@latest my-first-app -- --template minimal --ts --pm npm\ncd my-first-app\n```\n\nThe scaffolder creates the following structure:\n\n```\nmy-first-app/\n\u251c\u2500\u2500 routes/\n\u2502   \u251c\u2500\u2500 index.velox        \u2190 homepage route\n\u2502   \u2514\u2500\u2500 about.velox        \u2190 about page route\n\u251c\u2500\u2500 layouts/\n\u2502   \u2514\u2500\u2500 default.velox      \u2190 wraps all routes by default\n\u251c\u2500\u2500 public/\n\u2502   \u2514\u2500\u2500 favicon.svg\n\u251c\u2500\u2500 velox.config.ts\n\u251c\u2500\u2500 tsconfig.json\n\u2514\u2500\u2500 package.json\n```\n\n## Step 2 \u2014 Start the Development Server\n\n```bash\nnpm run dev\n```\n\nVelox starts the development server on port 3700 by default:\n\n```\n  \u26a1 Velox v1.4.0 \u2014 development server\n  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n  \u2502  Local:    http://localhost:3700    \u2502\n  \u2502  Network:  http://192.168.1.5:3700  \u2502\n  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n  Ready in 312ms\n```\n\nOpen `http://localhost:3700` in your browser. You should see the default Velox welcome page.\n\n## Step 3 \u2014 Understand the Default Page\n\nOpen `routes/index.velox`. A `.velox` file is a superset of TSX with some Velox-specific features:\n\n```tsx\n---\n// Server-side frontmatter block \u2014 runs only on the server\nexport const meta = {\n  title: 'Home',\n  description: 'My first Velox app',\n};\n---\n\n<main>\n  <h1>Welcome to Velox!</h1>\n  <p>Edit <code>routes/index.velox</code> to get started.</p>\n  <a href=\"/about\">About</a>\n</main>\n```\n\nThe `---` fenced block at the top is the **server block** \u2014 it runs exclusively during server-side rendering or static generation. Exports from the server block (like `meta`) are available as template variables in the HTML section below.\n\n## Step 4 \u2014 Add a New Route\n\nCreate a new file at `routes/contact.velox`:\n\n```tsx\n---\nexport const meta = {\n  title: 'Contact',\n  description: 'Get in touch with us',\n};\n---\n\n<main>\n  <h1>Contact Us</h1>\n  <p>Send us a message at <a href=\"mailto:hello@example.com\">hello@example.com</a></p>\n</main>\n```\n\nSave the file. Velox automatically picks up the new route \u2014 navigate to `http://localhost:3700/contact` and you will see your new page without restarting the server.\n\n## Step 5 \u2014 Create an API Route\n\nAPI routes live in the `routes/` directory alongside page routes, but are named with a `+` prefix to distinguish them.\n\nCreate `routes/api/hello+server.ts`:\n\n```typescript\nimport { defineHandler } from 'velox/server';\n\nexport const GET = defineHandler(async (req) => {\n  const name = new URL(req.url).searchParams.get('name') ?? 'World';\n  return Response.json({ message: `Hello, ${name}!` });\n});\n```\n\nTest it at `http://localhost:3700/api/hello?name=Velox`. You should receive:\n\n```json\n{ \"message\": \"Hello, Velox!\" }\n```\n\n## Step 6 \u2014 Fetch Data on the Server\n\nUpdate `routes/index.velox` to fetch data server-side:\n\n```tsx\n---\nimport { fetch } from 'velox/server';\n\nexport const meta = {\n  title: 'Home',\n};\n\n// This runs on the server only\nconst res = await fetch('https://jsonplaceholder.typicode.com/todos/1');\nconst todo = await res.json();\n---\n\n<main>\n  <h1>Welcome to Velox!</h1>\n  <p>Todo from API: {todo.title}</p>\n</main>\n```\n\n## Step 7 \u2014 Add Interactivity (Islands)\n\nBy default, Velox ships zero client-side JavaScript. To add a client-side interactive component, create a component and opt into hydration:\n\nCreate `components/Counter.tsx`:\n\n```tsx\nimport { signal } from 'velox/client';\n\nexport default function Counter() {\n  const count = signal(0);\n  return (\n    <div>\n      <p>Count: {count.value}</p>\n      <button onClick={() => count.value++}>Increment</button>\n    </div>\n  );\n}\n```\n\nUse it in your page with the `client:load` directive:\n\n```tsx\n---\nimport Counter from '../components/Counter.tsx';\n---\n\n<main>\n  <h1>Home</h1>\n  <Counter client:load />\n</main>\n```\n\nThe `client:load` directive tells Velox to hydrate this component immediately when the page loads. Other directives include `client:idle` (hydrate when browser is idle) and `client:visible` (hydrate when the component enters the viewport).\n\n## Step 8 \u2014 Build for Production\n\n```bash\nnpm run build\n```\n\nVelocitor compiles a production-ready build into the `.velox/output/` directory. Review the build output:\n\n```\n  \u26a1 Velox \u2014 production build\n  Compiled 4 routes in 1.8s\n  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n  \u2502  /            \u2192  SSR   (0 KB JS)        \u2502\n  \u2502  /about       \u2192  SSG   (0 KB JS)        \u2502\n  \u2502  /contact     \u2192  SSG   (0 KB JS)        \u2502\n  \u2502  /api/hello   \u2192  Edge handler           \u2502\n  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n  Total JS shipped to client: 2.1 KB (Counter island only)\n```\n\nTo preview the production build locally:\n\n```bash\nnpm run preview\n```\n\n## Next Steps\n\n- Read about [Project Structure](project-structure.md) to understand every directory and file\n- Explore [Routing](routing.md) for dynamic routes and catch-all patterns\n- Learn about [Data Fetchin"
  },
  {
    "file": "pages/routing.md",
    "title": "Routing",
    "section-id": "core-concepts",
    "keywords": "routing, file-based routing, dynamic routes, catch-all, nested routes, navigation",
    "description": "How Velox's file-based routing works, including dynamic segments, catch-all routes, and nested layouts",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# Routing\n\nVelox uses a file-based routing system. The file tree under the `routes/` directory maps one-to-one to the URL structure of your application. There is no router configuration file \u2014 the filesystem is the configuration.\n\n## Basic Routes\n\nAny `.velox` or `.tsx` file placed inside `routes/` becomes a page route:\n\n| File | URL |\n|------|-----|\n| `routes/index.velox` | `/` |\n| `routes/about.velox` | `/about` |\n| `routes/blog/index.velox` | `/blog` |\n| `routes/blog/my-post.velox` | `/blog/my-post` |\n| `routes/shop/shoes/index.velox` | `/shop/shoes` |\n\n## Dynamic Segments\n\nWrap a path segment in square brackets to make it dynamic:\n\n```\nroutes/\n\u2514\u2500\u2500 blog/\n    \u2514\u2500\u2500 [slug].velox   \u2192  /blog/:slug\n```\n\nInside the route, access the parameter via the `params` object in the server block:\n\n```tsx\n---\nconst { slug } = params;\nconst post = await db.posts.findBySlug(slug);\n\nif (!post) {\n  throw new NotFound();\n}\n\nexport const meta = { title: post.title };\n---\n\n<article>\n  <h1>{post.title}</h1>\n  <div innerHTML={post.htmlContent} />\n</article>\n```\n\n### Multiple Dynamic Segments\n\nYou can nest multiple dynamic segments:\n\n```\nroutes/\n\u2514\u2500\u2500 [category]/\n    \u2514\u2500\u2500 [slug].velox   \u2192  /:category/:slug\n```\n\n## Optional Dynamic Segments\n\nWrap a segment in double square brackets to make it optional:\n\n```\nroutes/\n\u2514\u2500\u2500 blog/\n    \u2514\u2500\u2500 [[page]].velox   \u2192  /blog  and  /blog/:page\n```\n\nInside the route, `params.page` will be `undefined` when the segment is not present.\n\n## Catch-All Routes\n\nUse the spread syntax `[...rest]` to match any number of path segments:\n\n```\nroutes/\n\u2514\u2500\u2500 docs/\n    \u2514\u2500\u2500 [...path].velox   \u2192  /docs/  and  /docs/a/b/c/d\n```\n\n`params.path` is an array of path segments: `['a', 'b', 'c', 'd']`.\n\n### Optional Catch-All\n\n`[[...rest]]` matches zero or more segments (i.e., the base path also matches):\n\n```\nroutes/\n\u2514\u2500\u2500 [[...slug]].velox   \u2192  /  and  /anything/at/all\n```\n\n## API Routes\n\nFiles with a `+server.ts` or `+server.js` suffix define API endpoints. They export HTTP method handlers named `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, or `OPTIONS`:\n\n```typescript\n// routes/api/users+server.ts\nimport { defineHandler } from 'velox/server';\nimport { db } from '$lib/db';\n\nexport const GET = defineHandler(async (req) => {\n  const users = await db.users.findMany();\n  return Response.json(users);\n});\n\nexport const POST = defineHandler(async (req) => {\n  const body = await req.json();\n  const user = await db.users.create({ data: body });\n  return Response.json(user, { status: 201 });\n});\n```\n\n## Route Groups\n\nWrap a directory name in parentheses to create a route group. Groups do not affect the URL \u2014 they are purely an organisational tool:\n\n```\nroutes/\n\u2514\u2500\u2500 (marketing)/\n    \u251c\u2500\u2500 index.velox       \u2192  /\n    \u251c\u2500\u2500 about.velox       \u2192  /about\n    \u2514\u2500\u2500 pricing.velox     \u2192  /pricing\n    \u2514\u2500\u2500 _layout.velox     \u2190 layout applied only to marketing routes\n```\n\nThis is useful when you want different layouts for different sections of your site without adding URL segments.\n\n## Special Files\n\n### `_layout.velox`\n\nA `_layout.velox` file wraps all sibling routes and nested route directories. Layouts receive a `<slot />` where child content is injected:\n\n```tsx\n// routes/blog/_layout.velox\n---\nimport Sidebar from '../../components/Sidebar.tsx';\n---\n\n<div class=\"blog-layout\">\n  <Sidebar />\n  <main>\n    <slot />\n  </main>\n</div>\n```\n\nLayouts nest automatically \u2014 a deeply nested `_layout.velox` wraps its subtree, and the tree up to the root layout wraps the whole thing.\n\n### `_error.velox`\n\nRenders when an unhandled error occurs or when a `NotFound` is thrown. Receives `error` and `status` as props.\n\n### `_loading.velox`\n\nShown as an immediate placeholder during route transitions (client-side navigation) while the next route is loading.\n\n## Programmatic Navigation\n\nUse the `useRouter` hook for client-side navigation in interactive components:\n\n```typescript\nimport { useRouter } from 'velox/client';\n\nexport default function LoginButton() {\n  const router = useRouter();\n\n  async function handleLogin() {\n    await performLogin();\n    router.navigate('/dashboard');\n  }\n\n  return <button onClick={handleLogin}>Log in</button>;\n}\n```\n\n### The `<Link>` Component\n\nFor declarative navigation, use the `<Link>` component. It renders an `<a>` tag with client-side navigation and prefetching:\n\n```tsx\nimport { Link } from 'velox/client';\n\n<Link href=\"/about\">About Us</Link>\n<Link href=\"/blog/my-post\" prefetch=\"hover\">My Post</Link>\n```\n\nThe `prefetch` prop accepts `\"hover\"` (prefetch on hover), `\"viewport\"` (prefetch when link enters viewport), or `false` (no prefetch).\n\n## Redirects\n\nReturn a redirect from a server block or API handler:\n\n```typescript\nimport { redirect } from 'velox/server';\n\n// In a server block\nif (!user) {\n  throw redirect('/login', 302);\n}\n\n// In an API route\nexport const GET = defineHandler(async () => {\n  return redirect('/new-location', 301);\n});\n```\n\n## Route Metadata\n\nExport `meta` from a route's server block to set page metadata:\n\n```typescript\nexport co"
  },
  {
    "file": "pages/state-management.md",
    "title": "State Management",
    "section-id": "core-concepts",
    "keywords": "state, signals, store, reactive, computed, effect, state management",
    "description": "Velox's reactive state management system \u2014 signals, stores, and reactive primitives",
    "author": null,
    "date": "",
    "datetime": "",
    "language": "en",
    "body": "# State Management\n\nVelox uses a signals-based reactivity system for client-side state. Signals are fine-grained reactive primitives \u2014 when a signal's value changes, only the DOM nodes that actually read that signal update. There is no virtual DOM diffing, no component tree re-render, and no unnecessary reconciliation.\n\n## Signals\n\nA signal is a reactive value container:\n\n```typescript\nimport { signal } from 'velox/client';\n\nconst count = signal(0);\n\n// Read the current value\nconsole.log(count.value); // 0\n\n// Update the value\ncount.value = 1;\nconsole.log(count.value); // 1\n```\n\nIn JSX, signals are automatically unwrapped \u2014 you do not need `.value` in templates:\n\n```tsx\nconst count = signal(0);\n\n// Both are equivalent:\n<p>{count.value}</p>\n<p>{count}</p>\n```\n\nThe second form (`{count}` without `.value`) subscribes the DOM node directly to the signal. This is more efficient because Velox skips the component function entirely and updates only the text node when the signal changes.\n\n## Computed Signals\n\nA computed signal derives its value from one or more other signals. It re-evaluates automatically when its dependencies change:\n\n```typescript\nimport { signal, computed } from 'velox/client';\n\nconst firstName = signal('Jane');\nconst lastName = signal('Doe');\nconst fullName = computed(() => `${firstName.value} ${lastName.value}`);\n\nconsole.log(fullName.value); // \"Jane Doe\"\nfirstName.value = 'John';\nconsole.log(fullName.value); // \"John Doe\"\n```\n\nComputed signals are lazy and memoised \u2014 the computation only runs when the value is read, and only re-runs if a dependency has changed since the last read.\n\n## Effects\n\nAn effect runs a side effect whenever its reactive dependencies change:\n\n```typescript\nimport { signal, effect } from 'velox/client';\n\nconst query = signal('');\n\neffect(() => {\n  console.log('Search query changed:', query.value);\n  // this re-runs every time query.value changes\n});\n```\n\nEffects clean themselves up automatically when the component unmounts. To clean up manually within an effect (e.g., cancel a previous request):\n\n```typescript\neffect(() => {\n  const controller = new AbortController();\n  fetch(`/api/search?q=${query.value}`, { signal: controller.signal })\n    .then(r => r.json())\n    .then(results => resultsSignal.value = results);\n\n  return () => controller.abort(); // cleanup function\n});\n```\n\n## Stores\n\nFor shared state across components, define a store. A store is a module that encapsulates signals and exposes a clean interface:\n\n```typescript\n// lib/stores/cart.ts\nimport { signal, computed } from 'velox/client';\n\nexport interface CartItem {\n  id: string;\n  name: string;\n  price: number;\n  quantity: number;\n}\n\nconst items = signal<CartItem[]>([]);\n\nexport const cartStore = {\n  items,\n  total: computed(() =>\n    items.value.reduce((sum, item) => sum + item.price * item.quantity, 0)\n  ),\n  itemCount: computed(() =>\n    items.value.reduce((sum, item) => sum + item.quantity, 0)\n  ),\n\n  addItem(item: Omit<CartItem, 'quantity'>) {\n    const existing = items.value.find(i => i.id === item.id);\n    if (existing) {\n      items.value = items.value.map(i =>\n        i.id === item.id ? { ...i, quantity: i.quantity + 1 } : i\n      );\n    } else {\n      items.value = [...items.value, { ...item, quantity: 1 }];\n    }\n  },\n\n  removeItem(id: string) {\n    items.value = items.value.filter(i => i.id !== id);\n  },\n\n  clear() {\n    items.value = [];\n  },\n};\n```\n\nUse the store in any component \u2014 signals are module-level singletons:\n\n```tsx\nimport { cartStore } from '$lib/stores/cart';\n\nexport default function CartIcon() {\n  return (\n    <button>\n      Cart ({cartStore.itemCount})\n    </button>\n  );\n}\n```\n\n## Batch Updates\n\nMultiple signal updates within a `batch()` call are processed as a single reactive update, preventing intermediate renders:\n\n```typescript\nimport { signal, batch } from 'velox/client';\n\nconst x = signal(0);\nconst y = signal(0);\nconst z = signal(0);\n\n// Without batch: triggers 3 re-renders\nx.value = 1;\ny.value = 2;\nz.value = 3;\n\n// With batch: triggers 1 re-render\nbatch(() => {\n  x.value = 1;\n  y.value = 2;\n  z.value = 3;\n});\n```\n\n## Async Signals\n\nFor async data that needs to integrate with the reactivity system, use `asyncSignal`:\n\n```typescript\nimport { signal, asyncSignal } from 'velox/client';\n\nconst userId = signal<string | null>(null);\n\nconst userProfile = asyncSignal(async () => {\n  if (!userId.value) return null;\n  const res = await fetch(`/api/users/${userId.value}`);\n  return res.json();\n});\n\n// userProfile.value is: { status: 'idle' | 'loading' | 'success' | 'error', data, error }\n```\n\nIn JSX:\n\n```tsx\n<div>\n  {userProfile.value.status === 'loading' && <Spinner />}\n  {userProfile.value.status === 'success' && (\n    <p>Hello, {userProfile.value.data.name}</p>\n  )}\n  {userProfile.value.status === 'error' && (\n    <p>Error: {userProfile.value.error.message}</p>\n  )}\n</div>\n```\n\n## Server State with `@velox/query`\n\nFor server state (data fetched from APIs), the `@velox/query` package"
  }
]