API / @aihu/app

@aihu/app

App & routing

Top-level app integration — wires runtime, router, and adapters into a Vite app.

version
5.0.0
exports
21
values
4
types
17
01

createApp

function
function createApp(config?: AppConfig): AppHandle
02

defineConfig

function
function defineConfig(config: AihuConfig): AihuConfig

Define the aihu application configuration.

03

viteAihuPlugin

function
function viteAihuPlugin(config?: AihuConfig): PluginOption[]

viteAihuPlugin() — composed Vite plugin for aihu SPA projects.

04

AihuConfigError

class
class AihuConfigError extends Error

Thrown by defineConfig when configuration validation fails.

05

AdapterContext

interface
interface AdapterContext {
  /** Absolute path to Vite's output directory (resolved build.outDir). */
  readonly outDir: string
  /** Absolute path to the project root (Vite's config.root). */
  readonly root: string
  /**
   * Route definitions derived from the pages directory scan.
   * Contains pattern, segments, and name — module() is irrelevant at adapt() time.
   */
  readonly routes: ReadonlyArray<RouteDefinition>
  /** The resolved AihuConfig passed to viteAihuPlugin(). */
  readonly config: import('./config.ts').AihuConfig

  /**
   * Emit a file relative to outDir. Creates parent directories as needed.
   * path is relative to outDir.
   */
  emitFile(path: string, content: string): Promise<void>

  /**
   * Copy a file or directory (absolute paths). Recursive. Overwrites existing.
   */
  copy(src: string, dest: string): Promise<void>

  /**
   * Write a file at an absolute path. Creates parent directories as needed.
   */
  writeFile(absolutePath: string, content: string): Promise<void>

  /**
   * Generate the source text of a server handler module.
   *
   * Returns a JS string that imports routes and createRequestRouter,
   * wires the handler, and exports `{ handler }`. The adapter appends
   * its platform-specific export wrapper.
   */
  createHandlerSource(options?: CreateHandlerSourceOptions): string
}

Context provided to adapter.adapt() after Vite's closeBundle completes.

06

AihuAdapter

interface
interface AihuAdapter {
  /**
   * Unique adapter name. Used in log output and error messages.
   * Convention: '<platform>' e.g. 'cloudflare', 'vercel', 'node'.
   */
  readonly name: string

  /**
   * Called by viteAihuPlugin's closeBundle hook after Vite finishes
   * writing all output files. The adapter reads from context.outDir,
   * transforms the build output into the platform's required format,
   * and writes the final deployment artifact.
   */
  adapt(context: AdapterContext): Promise<void>
}

The AihuAdapter interface.

07

AihuConfig

interface
interface AihuConfig {
  /** Directory layout overrides. */
  readonly dir?: DirConfig
  /**
   * Output mode. Supports `'spa'` (default) and `'static'` (SSG prerender).
   * defineConfig throws AihuConfigError for any other value.
   */
  readonly output?: OutputMode
  /**
   * Site-level configuration. `site.url` is the absolute base URL used by the
   * `'static'` output mode to resolve relative canonical/OG/Twitter URLs.
   */
  readonly site?: SiteConfig
  /**
   * Aihu plugins. Order is preserved.
   * Appended after the three framework plugins (compiler, router, agent-readiness).
   */
  readonly plugins?: ReadonlyArray<AihuPlugin>
  /** Runtime configuration split — public values are inlined in the client bundle. */
  readonly runtimeConfig?: RuntimeConfig
  /**
   * App-level values made available to all components as bare identifiers.
   * Declared here for documentation and future build-time validation; the
   * values are hoisted into globalThis by createApp() at runtime.
   *
   * @example
   * export default defineConfig({ provide: { supabase, checkAuth } })
   */
  readonly provide?: Record<string, unknown>
  /** HTML <head> metadata. */
  readonly app?: AppHeadConfig
  /** Passthrough to Vite's UserConfig. Merged via Vite's config() hook. */
  readonly vite?: VitePassthrough
  /**
   * Opt-in agent-readiness integration.
   * Requires { name: string } at minimum.
   * When absent or false, a no-op plugin is substituted.
   */
  readonly agentReadiness?: AgentReadinessConfig | false
  /**
   * Deployment adapter. Transforms the Vite build output into the target
   * platform's required format. Called after vite build completes.
   * When absent, no post-build transformation is applied (manual deployment).
   */
  readonly adapter?: AihuAdapter
  /**
   * Router-related app config (arch-5 M1).
   * Currently exposes the `viewTransitions` opt-in for `<a>`.
   */
  readonly router?: RouterConfig
  /**
   * CSS / styling integration. Currently surfaces the project-wide
   * `shadowMode` forwarded to the compiler. Set to `{ shadowMode: 'light' }`
   * when using a cascade-dependent CSS framework (Tailwind, UnoCSS, Pico).
   */
  readonly css?: CssConfig
}
08

AppConfig

interface
interface AppConfig {
  /** Id of the outlet element in index.html. Default: 'outlet' */
  outletId?: string
  /**
   * App-level values hoisted into globalThis before any component runs.
   * Use this for singletons (db clients, auth helpers, i18n) that are
   * referenced as bare identifiers inside @state blocks.
   *
   * @example
   * createApp({ provide: { supabase, checkAuth } })
   */
  provide?: Record<string, unknown>
  /**
   * Rendering mode from the server config. Controls whether the client
   * wires the hydration function into the runtime.
   *
   * - 'ssr' | 'hybrid' (default): wires _setHydrate so the client can
   *   take over from server-rendered HTML without re-creating DOM.
   * - 'spa': skips _setHydrate — no SSR HTML to hydrate, mount-only.
   *
   * Pass `defineAihuConfig(…).rendering?.mode` from your server config.
   * Default: 'ssr' (hydration wired).
   */
  rendering?: { mode?: AppRenderingMode }
  /**
   * Site-level config. `site.url` is the absolute base URL used to resolve
   * relative per-route `canonical` / `og:*` / `twitter:*` values into absolute
   * URLs as the head is applied on client navigation (mirrors the SSG path's
   * `AihuConfig.site.url`). When absent, relative values are emitted unchanged.
   */
  site?: { url?: string }
  /**
   * Global `<head>` defaults (typically `aihu.config.ts`'s `app.head`). On every
   * navigation these defaults are folded under the active route's head
   * (`routeHeadToSsrHead`'s `globalHead`) and re-applied — so a route that omits
   * a field falls back to the global default, and global tags persist across
   * navigations while route-only tags are cleaned up.
   */
  head?: HeadConfig
}

Inline runtime configuration accepted by createApp().

09

AppHandle

interface
interface AppHandle {
  /**
   * Switch the active layout on the current route without navigating.
   * `setLayout(name)` forces that layout; `setLayout(null)` forces none. The
   * override is reset on the next navigation. Wire it to a UI toggle or expose
   * it to an `@agent` action (e.g. `setLayout("compact")`).
   */
  setLayout(name: string | null): Promise<void>
}
10

AppHeadConfig

interface
interface AppHeadConfig {
  readonly head?: HeadConfig
}
11

CreateHandlerSourceOptions

interface
interface CreateHandlerSourceOptions {
  /**
   * Import specifier for the compiled routes manifest module.
   * Default: './routes-manifest.js'
   */
  routesSpecifier?: string
  /**
   * Import specifier for @aihu/server.
   * Default: '@aihu/server'
   * Adapters that bundle server deps may override this to a relative path.
   */
  serverSpecifier?: string
}

Options for AdapterContext.createHandlerSource().

12

DirConfig

interface
interface DirConfig {
  /** Directory to scan for page routes. Default: 'pages' */
  readonly pages?: string
  /** Directory to scan for layout files. Default: 'src/layouts' */
  readonly layouts?: string
  /** Public static assets directory. Default: 'public' */
  readonly public?: string
}
13

HeadConfig

interface
interface HeadConfig {
  readonly title?: string
  /** Default: 'UTF-8' */
  readonly charset?: string
  /** Default: 'width=device-width, initial-scale=1' */
  readonly viewport?: string
  readonly meta?: ReadonlyArray<Record<string, string>>
}
14

RouterConfig

interface
interface RouterConfig {
  /**
   * When `true`, `<a>` navigation wraps in `document.startViewTransition()`
   * if the browser supports the View Transitions API. No-op in unsupported
   * browsers (graceful degradation). Default: `false`.
   *
   * SSR safety: the wrapping is browser-only — server-rendered HTML is
   * unchanged, and hydration is unaffected.
   */
  readonly viewTransitions?: boolean
}

Router-related app config (arch-5 M1, RFC-A5-012).

15

RuntimeConfig

interface
interface RuntimeConfig {
  readonly public?: Record<string, unknown>
  /** V0: accepted but ignored at runtime (server-side enforcement deferred to V1). */
  readonly private?: Record<string, unknown>
}

Runtime configuration split.

16

SiteConfig

interface
interface SiteConfig {
  /**
   * Absolute base URL of the deployed site (e.g. `https://example.com`).
   * Used by the `'static'` (SSG) output mode to resolve relative per-route
   * `canonical` / `og:*` / `twitter:*` URLs into absolute URLs (passed as
   * `siteUrl` to @aihu/server's `routeHeadToSsrHead`). When absent, relative
   * URLs are emitted unchanged.
   */
  readonly url?: string
}

Site-level configuration.

17

AgentReadinessConfig

typeagent
type AgentReadinessConfig = import('@aihu-plugin/agent-readiness').AgentReadinessConfig

Type-only import — not bundled when agentReadiness is absent.

18

AihuPlugin

type
type AihuPlugin = Plugin

A Aihu plugin is structurally identical to a Vite plugin (V0).

19

AppRenderingMode

type
type AppRenderingMode = 'ssr' | 'spa' | 'hybrid'

Rendering mode passed from the server config into the client bootstrap.

20

OutputMode

type
type OutputMode = 'spa' | 'static'

Build output mode.

21

VitePassthrough

type
type VitePassthrough = Omit<UserConfig, 'plugins'>

Vite config fields that can be safely merged (excludes plugins — use AihuConfig.plugins).