Top-level app integration — wires runtime, router, and adapters into a Vite app.
createAppfunction createApp(config?: AppConfig): AppHandledefineConfigfunction defineConfig(config: AihuConfig): AihuConfigDefine the aihu application configuration.
viteAihuPluginfunction viteAihuPlugin(config?: AihuConfig): PluginOption[]viteAihuPlugin() — composed Vite plugin for aihu SPA projects.
AihuConfigErrorclass AihuConfigError extends ErrorThrown by defineConfig when configuration validation fails.
AdapterContextinterface 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.
AihuAdapterinterface 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.
AihuConfiginterface 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
}AppConfiginterface 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().
AppHandleinterface 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>
}AppHeadConfiginterface AppHeadConfig {
readonly head?: HeadConfig
}CreateHandlerSourceOptionsinterface 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().
DirConfiginterface 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
}HeadConfiginterface 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>>
}RouterConfiginterface 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).
RuntimeConfiginterface 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.
SiteConfiginterface 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.
AgentReadinessConfigtype AgentReadinessConfig = import('@aihu-plugin/agent-readiness').AgentReadinessConfigType-only import — not bundled when agentReadiness is absent.
AihuPlugintype AihuPlugin = PluginA Aihu plugin is structurally identical to a Vite plugin (V0).
AppRenderingModetype AppRenderingMode = 'ssr' | 'spa' | 'hybrid'Rendering mode passed from the server config into the client bootstrap.
OutputModetype OutputMode = 'spa' | 'static'Build output mode.
VitePassthroughtype VitePassthrough = Omit<UserConfig, 'plugins'>Vite config fields that can be safely merged (excludes plugins — use AihuConfig.plugins).