---
title: API Reference
description: Every public API with the release it first shipped in, its stability tier and a usage example — generated from the JSDoc on the exports themselves.
---

# API Reference

<!-- AUTO-GENERATED by scripts/generate-api-reference.ts from the `@since` / `@stability` / `@example` JSDoc tags on each export — do not edit by hand. Run `bun run scripts/generate-api-reference.ts` to regenerate. -->

Every public API, the release it first shipped in, its stability tier and a short example. The tiers are the ones the README's stability table defines: on a **beta** surface a breaking change ships in a minor release with a migration note in the changelog; an **alpha** surface may change without notice, so pin exact versions if you depend on it. Pre-1.0, a minor release is the breaking-change slot for both.

Everything here comes from `@since` / `@stability` / `@example` JSDoc tags on the exports, so the code is the source of truth: a new export cannot ship without a stability decision, and a new beta function cannot ship without an example.

## Runtime

Everything `@barefootjs/client` exports. **Beta** is the set a component author actually writes — the reactive primitives, context, the four portal helpers, the two compiler built-ins and the two adapter-lowered helpers. **Alpha** is the rest: shipped and usable, but with no authored call site and no documented pattern, so its contract is not frozen. The compiler ABI is not listed at all — `forwardProps` and `unwrap` are pure, so this SSR-safe entry re-exports them for the compiler's SSR-rewritten imports too; `provideContext` is DOM-only and moves to `@barefootjs/client/runtime` for the CSR path. None is ever written by hand.

| API | Kind | Since | Status |
|---|---|---|---|
| [`Async()`](#async) | function | 0.15.0 | **Beta** |
| [`AsyncProps`](#asyncprops) | interface | 0.15.0 | **Beta** |
| [`batch()`](#batch) | function | 0.1.0 | **Beta** |
| [`CleanupFn`](#cleanupfn) | type | 0.1.0 | **Beta** |
| [`Context`](#context) | type | 0.1.0 | **Beta** |
| [`createContext()`](#createcontext) | function | 0.1.0 | **Beta** |
| [`createEffect()`](#createeffect) | function | 0.1.0 | **Beta** |
| [`createMemo()`](#creatememo) | function | 0.1.0 | **Beta** |
| [`createMutation()`](#createmutation) | function | 0.39.0 | Alpha |
| [`CreateMutationOptions`](#createmutationoptions) | interface | 0.39.0 | Alpha |
| [`createPortal()`](#createportal) | function | 0.1.0 | **Beta** |
| [`createQuery()`](#createquery) | function | 0.39.0 | Alpha |
| [`CreateQueryOptions`](#createqueryoptions) | interface | 0.39.0 | Alpha |
| [`createRoot()`](#createroot) | function | 0.1.0 | Alpha |
| [`createSearchParams()`](#createsearchparams) | function | 0.17.0 | **Beta** |
| [`createSignal()`](#createsignal) | function | 0.1.0 | **Beta** |
| [`EffectFn`](#effectfn) | type | 0.1.0 | **Beta** |
| [`findSiblingSlot()`](#findsiblingslot) | function | 0.1.0 | **Beta** |
| [`http`](#http) | const | 0.39.0 | Alpha |
| [`HttpDescriptor`](#httpdescriptor) | type | 0.39.0 | Alpha |
| [`HttpError`](#httperror) | class | 0.39.0 | Alpha |
| [`HttpInit`](#httpinit) | interface | 0.39.0 | Alpha |
| [`HttpMethod`](#httpmethod) | type | 0.39.0 | Alpha |
| [`HttpParams`](#httpparams) | type | 0.39.0 | Alpha |
| [`HttpParamValue`](#httpparamvalue) | type | 0.39.0 | Alpha |
| [`isSSRPortal()`](#isssrportal) | function | 0.1.0 | **Beta** |
| [`Memo`](#memo) | type | 0.1.0 | **Beta** |
| [`MutationAction`](#mutationaction) | interface | 0.39.0 | Alpha |
| [`onCleanup()`](#oncleanup) | function | 0.1.0 | **Beta** |
| [`onMount()`](#onmount) | function | 0.1.0 | **Beta** |
| [`Portal`](#portal) | type | 0.1.0 | **Beta** |
| [`PortalChildren`](#portalchildren) | type | 0.1.0 | **Beta** |
| [`PortalOptions`](#portaloptions) | interface | 0.1.0 | **Beta** |
| [`QueryAction`](#queryaction) | interface | 0.39.0 | Alpha |
| [`queryHref()`](#queryhref) | function | 0.17.0 | **Beta** |
| [`QueryParams`](#queryparams) | type | 0.17.0 | **Beta** |
| [`QueryParamValue`](#queryparamvalue) | type | 0.17.0 | **Beta** |
| [`Reactive`](#reactive) | type | 0.1.0 | **Beta** |
| [`Region()`](#region) | function | 0.15.0 | **Beta** |
| [`RegionProps`](#regionprops) | interface | 0.15.0 | **Beta** |
| [`Renderable`](#renderable) | type | 0.1.0 | **Beta** |
| [`SearchParamsInit`](#searchparamsinit) | type | 0.17.0 | **Beta** |
| [`Signal`](#signal) | type | 0.1.0 | **Beta** |
| [`splitProps()`](#splitprops) | function | 0.1.0 | Alpha |
| [`untrack()`](#untrack) | function | 0.1.0 | **Beta** |
| [`useContext()`](#usecontext) | function | 0.1.0 | **Beta** |

### `Async()`

`function` · **Beta** since 0.15.0 · `@barefootjs/client`

Streaming async boundary. Lowered by the compiler to the adapter's streaming primitive (Hono `<Suspense>`); `fallback` is shown until the children resolve. Compiled away — never executes at runtime.

```tsx
import { Async } from '@barefootjs/client'

export function Page() {
  return (
    <Async fallback={<p>Loading comments…</p>}>
      <Comments />
    </Async>
  )
}
```

### `AsyncProps`

`interface` · **Beta** since 0.15.0 · `@barefootjs/client`

Props of the `<Async>` built-in.

| Field | Since | Status | Description |
|---|---|---|---|
| `fallback` | 0.15.0 | **Beta** | UI rendered while the streamed children resolve. |
| `children` | 0.15.0 | **Beta** | Content streamed in once resolved. |

### `batch()`

`function` · **Beta** since 0.1.0 · `@barefootjs/client`

Batch multiple signal updates and propagate once

```tsx
const [a, setA] = createSignal(0)
const [b, setB] = createSignal(0)
batch(() => {
  setA(1)  // queued
  setB(2)  // queued
})
// effects run once here, not twice
```

### `CleanupFn`

`type` · **Beta** since 0.1.0 · `@barefootjs/client`

A cleanup callback, as registered with `onCleanup` or returned from an effect.

### `Context`

`type` · **Beta** since 0.1.0 · `@barefootjs/client`

A context handle created by `createContext`.

### `createContext()`

`function` · **Beta** since 0.1.0 · `@barefootjs/client`

Create a new context with an optional default value.

```tsx
"use client"
import { createContext } from '@barefootjs/client'

export const TabsContext = createContext<{ active: () => string }>()

// A parent provides the value; any descendant reads it with useContext().
// <TabsContext.Provider value={{ active }}>...</TabsContext.Provider>
```

### `createEffect()`

`function` · **Beta** since 0.1.0 · `@barefootjs/client`

Side effect that runs automatically when signals change

```tsx
const [count, setCount] = createSignal(0)
createEffect(() => {
  console.log("count changed:", count())
})
setCount(1)  // Logs "count changed: 1"
```

### `createMemo()`

`function` · **Beta** since 0.1.0 · `@barefootjs/client`

Create a memoized computed value

```tsx
const [count, setCount] = createSignal(2)
const doubled = createMemo(() => count() * 2)
doubled()    // 4
setCount(5)
doubled()    // 10
```

### `createMutation()`

`function` · Alpha since 0.39.0 · `@barefootjs/client`

`createMutation(fn, options?)` — a value written only by calling the returned action. Returns `[value, action]`, the same tuple shape as `createQuery`. See spec/async.md §7.4/§7.5.

### `CreateMutationOptions`

`interface` · Alpha since 0.39.0 · `@barefootjs/client`

Options `createMutation` accepts. Unlike `CreateQueryOptions`, there is no `initial` — a mutation has no initial request to seed from (spec/async.md §7.4); the compiler refuses one written anyway (BF118).

### `createPortal()`

`function` · **Beta** since 0.1.0 · `@barefootjs/client`

Render children into a container outside the parent DOM hierarchy. Browser-only.

```tsx
"use client"
function DialogOverlay() {
  const handleMount = (el: HTMLElement) => {
    // Move the overlay to <body> so no ancestor's overflow or z-index clips it.
    createPortal(el, document.body)
  }
  return <div ref={handleMount} class="fixed inset-0 bg-black/50" />
}
```

### `createQuery()`

`function` · Alpha since 0.39.0 · `@barefootjs/client`

`createQuery(fn, options?)` — a value re-sent whenever a signal `fn` reads changes. Returns `[value, action]`, the same `[getter, setter]`-shaped tuple as `createSignal`. See spec/async.md §7 for the full model.

### `CreateQueryOptions`

`interface` · Alpha since 0.39.0 · `@barefootjs/client`

Options `createQuery` accepts. `initial` is the **already-obtained result** of the initial request (spec/async.md §7.5) — not a placeholder.

### `createRoot()`

`function` · Alpha since 0.1.0 · `@barefootjs/client`

Create an isolated reactive scope with explicit disposal. All effects/memos created inside run within this root and are disposed together when the returned dispose function is called.

```ts
const dispose = createRoot((dispose) => {
  createEffect(() => console.log(count()))
  return dispose
})

dispose()  // tears down every effect and memo created inside the scope
```

### `createSearchParams()`

`function` · **Beta** since 0.17.0 · `@barefootjs/client`

Request-scoped query-string signal, returned as a `createSignal`-shaped `[getter, setter]` tuple. See the doc comment on `searchParamsTuple` above for the read/write semantics.

```tsx
"use client"
const [searchParams, setSearchParams] = createSearchParams()

// Reads re-run when the router changes the query, with no swap or re-hydration.
const sort = createMemo(() => searchParams().get('sort') ?? 'date')

// Writing navigates: soft same-route when a router is running, hard otherwise.
setSearchParams({ sort: 'price' })
```

### `createSignal()`

`function` · **Beta** since 0.1.0 · `@barefootjs/client`

Create a reactive value

```tsx
const [count, setCount] = createSignal(0)
count()              // 0
setCount(5)          // Update to 5
setCount(n => n + 1) // Update with function (becomes 6)

const [user, setUser] = createSignal<User>()
user()               // undefined — typed `User | undefined`
```

### `EffectFn`

`type` · **Beta** since 0.1.0 · `@barefootjs/client`

An effect body; may return a `CleanupFn`.

### `findSiblingSlot()`

`function` · **Beta** since 0.1.0 · `@barefootjs/client`

The nearest element matching `slotSelector` among `el`'s siblings, or `null`. Browser-only.

```tsx
"use client"
const handleMount = (el: HTMLElement) => {
  const triggerEl = findSiblingSlot(el, '[data-slot="popover-trigger"]')
  if (!triggerEl) return
  const r = triggerEl.getBoundingClientRect()
  el.style.top = `${r.bottom + window.scrollY}px`
}
```

### `http`

`const` · Alpha since 0.39.0 · `@barefootjs/client`

Build `http` request descriptors — pure, synchronous, no I/O. See the module doc comment and spec/async.md §7.2 for the constructor table and the params/body serialisation rules.

### `HttpDescriptor`

`type` · Alpha since 0.39.0 · `@barefootjs/client`

A pure request descriptor. Constructing one performs no I/O — see the `http` namespace below. `T` is a phantom: it is never set on the runtime object, only carried in the type so `createQuery`'s `initial` and `value()` can be checked against it.

### `HttpError`

`class` · Alpha since 0.39.0 · `@barefootjs/client`

A non-2xx HTTP response to a request sent from an `http` descriptor — what a query's `error()` holds when the server answered with an error status (a network failure is the underlying error instead). `status` is the response status; `body` is the response body parsed as JSON when possible, else the raw text, else `undefined`.

### `HttpInit`

`interface` · Alpha since 0.39.0 · `@barefootjs/client`

The third argument any `http` constructor accepts. v0 is intentionally narrow — headers and credentials only.

### `HttpMethod`

`type` · Alpha since 0.39.0 · `@barefootjs/client`

The HTTP methods `http` can build a descriptor for. `QUERY` is the safe, read-with-a-body method (spec/async.md §7.2); it is not a method `fetch`/`XMLHttpRequest` special-case, so it is sent like any other verb.

### `HttpParams`

`type` · Alpha since 0.39.0 · `@barefootjs/client`

The params object `http.get` / `http.head` accept.

### `HttpParamValue`

`type` · Alpha since 0.39.0 · `@barefootjs/client`

One `http` param value. Unlike `queryHref`'s string-only `QueryParamValue`, numbers and booleans are accepted and kept — including `0` and `false` — because descriptors are never lowered to an SSR template (no string-only parity requirement to preserve). `null`, `undefined` and `''` are omitted; an array appends one entry per member.

### `isSSRPortal()`

`function` · **Beta** since 0.1.0 · `@barefootjs/client`

Whether `element` is a portal target the server already rendered in place. Browser-only.

```tsx
"use client"
function DialogOverlay() {
  const handleMount = (el: HTMLElement) => {
    // Only portal a client-mounted overlay; SSR already placed the other one.
    if (el.parentNode !== document.body && !isSSRPortal(el)) {
      createPortal(el, document.body, { ownerScope: el.closest('[bf-s]') ?? undefined })
    }
  }
  return <div ref={handleMount} class="fixed inset-0 bg-black/50" />
}
```

### `Memo`

`type` · **Beta** since 0.1.0 · `@barefootjs/client`

The cached getter `createMemo` returns.

### `MutationAction`

`interface` · Alpha since 0.39.0 · `@barefootjs/client`

The callable `action` a mutation returns alongside its value: sends the request function's current descriptor when called, and carries two reactive accessors.

### `onCleanup()`

`function` · **Beta** since 0.1.0 · `@barefootjs/client`

Register cleanup function for effects

```tsx
createEffect(() => {
  const timer = setInterval(() => console.log('tick'), 1000)
  onCleanup(() => clearInterval(timer))
})
```

### `onMount()`

`function` · **Beta** since 0.1.0 · `@barefootjs/client`

Run a function once when the component mounts

```tsx
onMount(() => {
  console.log('Component mounted!')
  onCleanup(() => console.log('Component unmounted!'))
})
```

### `Portal`

`type` · **Beta** since 0.1.0 · `@barefootjs/client`

The handle `createPortal` returns.

### `PortalChildren`

`type` · **Beta** since 0.1.0 · `@barefootjs/client`

Valid children types for createPortal

### `PortalOptions`

`interface` · **Beta** since 0.1.0 · `@barefootjs/client`

Options for createPortal

| Field | Since | Status | Description |
|---|---|---|---|
| `ownerScope` | 0.1.0 | **Beta** | The scope element that owns this portal. |

### `QueryAction`

`interface` · Alpha since 0.39.0 · `@barefootjs/client`

The callable `action` a query returns alongside its value: re-sends the current descriptor when called, and carries two reactive accessors.

### `queryHref()`

`function` · **Beta** since 0.17.0 · `@barefootjs/client`

Build an href from a base path and a query-params object. Pure; SSR adapters lower the call to their own query helper.

```ts
queryHref('/posts', { sort: 'price', tag: 'hono' })  // '/posts?sort=price&tag=hono'
queryHref('/posts', { tag: ['hono', 'go'] })         // '/posts?tag=hono&tag=go'

// Empty, null and undefined values are omitted, so a conditional include
// folds into the value itself. Nothing survives here, so the base is returned:
queryHref('/posts', { sort: undefined, tag: '' })    // '/posts'
```

### `QueryParams`

`type` · **Beta** since 0.17.0 · `@barefootjs/client`

The params object `queryHref` accepts.

### `QueryParamValue`

`type` · **Beta** since 0.17.0 · `@barefootjs/client`

One `queryHref` param value: a string, a repeated string, or absent.

### `Reactive`

`type` · **Beta** since 0.1.0 · `@barefootjs/client`

Phantom brand for compile-time reactivity detection. The compiler checks for the '__reactive' property via TypeChecker to identify reactive expressions.

### `Region()`

`function` · **Beta** since 0.15.0 · `@barefootjs/client`

Page-lifecycle boundary (spec/router.md). Lowered by the compiler to a wrapper element carrying a deterministic `bf-region` marker the client router matches on. Compiled away — never executes at runtime.

```tsx
import { Region } from '@barefootjs/client'

// The router disposes and re-hydrates only what is inside <Region> on a
// navigation; the header outside it survives untouched.
export function Layout(props: { children?: unknown }) {
  return (
    <>
      <SiteHeader />
      <Region>{props.children}</Region>
    </>
  )
}
```

### `RegionProps`

`interface` · **Beta** since 0.15.0 · `@barefootjs/client`

Props of the `<Region>` built-in.

| Field | Since | Status | Description |
|---|---|---|---|
| `children` | 0.15.0 | **Beta** | The page-lifecycle subtree the router disposes / re-hydrates on navigation. |

### `Renderable`

`type` · **Beta** since 0.1.0 · `@barefootjs/client`

Anything that can be converted to HTML string via toString()

### `SearchParamsInit`

`type` · **Beta** since 0.17.0 · `@barefootjs/client`

Accepted inputs for `setSearchParams` — a raw query string (with or without a leading `?`), a `URLSearchParams`, or a plain record (array = multi-value, form-encoded like the client `queryHref`, cf. #2048).

### `Signal`

`type` · **Beta** since 0.1.0 · `@barefootjs/client`

The `[getter, setter]` tuple `createSignal` returns.

### `splitProps()`

`function` · Alpha since 0.1.0 · `@barefootjs/client`

Split a props object into two: one with the specified keys, one with the rest. Both returned objects use Proxy to defer reads, preserving reactive tracking.

```tsx
"use client"
function Checkbox(props: CheckboxProps) {
  // `local` carries the two keys this component handles itself; everything
  // else rides along to the DOM element, still reactive.
  const [local, rest] = splitProps(props, ['checked', 'onCheckedChange'])
  return <button {...rest} aria-checked={local.checked} />
}
```

### `untrack()`

`function` · **Beta** since 0.1.0 · `@barefootjs/client`

Run a function without tracking signal dependencies

```tsx
createEffect(() => {
  const value = untrack(() => someSignal()) // won't re-run when someSignal changes
  console.log(value)
})
```

### `useContext()`

`function` · **Beta** since 0.1.0 · `@barefootjs/client`

Read the nearest provided value for a context. Browser-only; the compiler rewrites the import in `"use client"` components.

```tsx
"use client"
function AccordionContent(props: { children?: unknown }) {
  const handleMount = (el: HTMLElement) => {
    const ctx = useContext(AccordionItemContext)
    createEffect(() => {
      el.dataset.state = ctx.open() ? 'open' : 'closed'
    })
  }
  return <div ref={handleMount}>{props.children}</div>
}
```

## Directives

The two source-level directives the compiler recognizes. They are syntax, not imports; the spellings are defined once in `packages/jsx/src/directives.ts`.

| API | Kind | Since | Status |
|---|---|---|---|
| [`@client` expression directive](#client-expression-directive) | const | 0.1.0 | **Beta** |
| [`"use client"`](#use-client) | const | 0.1.0 | **Beta** |

### `@client` expression directive

`const` · **Beta** since 0.1.0

Expression-level `/* @client */` directive, placed as a block comment directly before a JSX expression, an attribute initializer or a component prop initializer. It tells the compiler to skip server evaluation of that expression and evaluate it on the client only — the escape for expressions no template adapter can lower.

```tsx
// No template adapter can lower `toLocaleString()`, so evaluate it on the
// client only. The server renders nothing there; hydration fills it in.
<span>{/* @client */ total().toLocaleString()}</span>
```

### `"use client"`

`const` · **Beta** since 0.1.0

Module-level `"use client"` directive. A component file that opens with it ships client JS and hydrates; without it the file's components render to static HTML only, and importing a browser-only API from it is a compile error.

```tsx
"use client"
import { createSignal } from '@barefootjs/client'

export function Counter() {
  const [count, setCount] = createSignal(0)
  return <button onClick={() => setCount(count() + 1)}>{count()}</button>
}
```

## Vite plugin

Everything `@barefootjs/vite` exports. **Beta** is what configuring a build takes: `barefoot()`, its four options and the `afterEmit` context every adapter builder composes through. **Alpha** is the rest — the URL and discovery helpers re-exported so a builder resolves assets the way the plugin itself does. See [Vite Plugin](./vite-plugin.md) for the build and dev output, the on-disk layout and the dev-server markers.

| API | Kind | Since | Status |
|---|---|---|---|
| [`AfterEmitContext`](#afteremitcontext) | interface | 0.31.0 | **Beta** |
| [`barefoot()`](#barefoot) | function | 0.31.0 | **Beta** |
| [`BarefootPluginApi`](#barefootpluginapi) | interface | 0.31.0 | Alpha |
| [`BarefootViteOptions`](#barefootviteoptions) | interface | 0.31.0 | **Beta** |
| [`ComponentDirEntry`](#componentdirentry) | interface | 0.31.0 | **Beta** |
| [`devModuleUrl()`](#devmoduleurl) | function | 0.31.0 | Alpha |
| [`devRequestPath()`](#devrequestpath) | function | 0.31.0 | Alpha |
| [`discoverComponents()`](#discovercomponents) | function | 0.31.0 | Alpha |
| [`DiscoveredComponent`](#discoveredcomponent) | interface | 0.31.0 | Alpha |
| [`joinBaseAndFile()`](#joinbaseandfile) | function | 0.31.0 | Alpha |
| [`loadManifest()`](#loadmanifest) | function | 0.31.0 | Alpha |
| [`PLUGIN_NAME`](#plugin_name) | const | 0.31.0 | Alpha |
| [`ResolvedComponentDirEntry`](#resolvedcomponentdirentry) | interface | 0.31.0 | Alpha |
| [`resolveDevOrigin()`](#resolvedevorigin) | function | 0.31.0 | Alpha |
| [`resolveScriptAssets()`](#resolvescriptassets) | function | 0.31.0 | Alpha |
| [`toPosixRelative()`](#toposixrelative) | function | 0.31.0 | Alpha |

### `AfterEmitContext`

`interface` · **Beta** since 0.31.0 · `@barefootjs/vite`

Narrow context handed to `afterEmit` once per eager pass (`writeBundle` for `vite build`, the dev pass for `vite dev`) — AFTER every discovered component's template has already been written to `templatesDir`. This is the one escape hatch this plugin exposes, and its shape is deliberately minimal:

| Field | Since | Status | Description |
|---|---|---|---|
| `types` | 0.31.0 | **Beta** | Per-source-file `types` output, keyed by that file's absolute path. |
| `projectDir` | 0.31.0 | **Beta** | Absolute path to the Vite project root. |
| `templatesDir` | 0.31.0 | **Beta** | Absolute path to the configured `templates` output dir. |
| `outDir` | 0.31.0 | **Beta** | Absolute path to Vite's configured `build.outDir`. |
| `mode` | 0.31.0 | **Beta** | Which eager pass just ran. |

### `barefoot()`

`function` · **Beta** since 0.31.0 · `@barefootjs/vite`

The core BarefootJS Vite plugin: compiles every `.tsx` under `components` into a template for `adapter` and client JS for Vite to bundle. See `docs/core/advanced/vite-plugin.md`.

```ts
// vite.config.ts
import { defineConfig } from 'vite'
import { barefoot } from '@barefootjs/vite'
import { HonoAdapter } from '@barefootjs/hono'

export default defineConfig({
  base: '/static/components/',
  build: { outDir: 'public/components' },
  plugins: [
    barefoot({
      adapter: new HonoAdapter(),
      components: ['components'],
      templates: 'dist/components',
    }),
  ],
})
```

### `BarefootPluginApi`

`interface` · Alpha since 0.31.0 · `@barefootjs/vite`

Shape exposed on the returned plugin's `.api` — Vite's own convention (a plugin may attach an `api` property "designed for other plugins or Vite-based tools to access") for exactly this: tooling that wants this plugin's resolved options without re-deriving them from `vite.config.ts` text. The `bf` CLI (`packages/cli/src/context.ts`) is the one consumer today — it uses Vite's own `loadConfigFromFile` to get the resolved config, finds the plugin by name (`PLUGIN_NAME`, exported from `plugin.ts`) in its `plugins` array, and reads `api.options.components` as `sourceDirs`.

### `BarefootViteOptions`

`interface` · **Beta** since 0.31.0 · `@barefootjs/vite`

Public options for the `barefoot()` Vite plugin. Exactly three BarefootJS-specific FIELDS — everything else (bundling, hashing, chunking, tree-shaking, minification, dev server, `base`, `outDir`) is stock Vite config. Do not add more fields here; see the design doc for the full list of options this deliberately drops in favor of Vite's own equivalents (`minify` → `build.minify`, `externals` → Rollup's automatic chunk splitting, `clientJsBasePath`/`barefootJsPath` → `base` + manifest resolution, etc).

| Field | Since | Status | Description |
|---|---|---|---|
| `adapter` | 0.31.0 | **Beta** | A constructed `TemplateAdapter` instance (e.g. `new GoTemplateAdapter({ packageName: 'main' })`). |
| `components` | 0.31.0 | **Beta** | Source directories to scan for `.tsx` components, relative to the Vite project root (or absolute). |
| `templates` | 0.31.0 | **Beta** | Where compiled templates, `ssrDefaults`, and adapter-generated types land — relative to the Vite project root (or absolute). |
| `afterEmit` | 0.31.0 | **Beta** | Optional escape hatch called once per eager pass (build AND dev), after templates are written, with a narrow `AfterEmitContext`. |

### `ComponentDirEntry`

`interface` · **Beta** since 0.31.0 · `@barefootjs/vite`

One `components` entry with per-directory compile behavior. A plain string is exactly equivalent to `{ dir: string }` — see `BarefootViteOptions.components`.

| Field | Since | Status | Description |
|---|---|---|---|
| `dir` | 0.31.0 | **Beta** | Source directory to scan, relative to the Vite root (or absolute). |
| `cssLayerPrefix` | 0.31.0 | **Beta** | `CompileOptions.cssLayerPrefix` for every component under `dir`: static class strings get `layer-{value}:` prefixes so a library's base classes land in a lower… |
| `skipDirs` | 0.31.0 | **Beta** | Directory NAMES to skip anywhere under `dir` (e.g. `['shared']`). |

### `devModuleUrl()`

`function` · Alpha since 0.31.0 · `@barefootjs/vite`

Full absolute URL (origin + `base` + request path) for `absPath` under the dev server.

### `devRequestPath()`

`function` · Alpha since 0.31.0 · `@barefootjs/vite`

The request path (relative to `config.base`, no leading slash) a browser must use to reach `absPath` through Vite's dev server: a root-relative path when `absPath` is under `config.root`, or Vite's `/@fs/` absolute-path passthrough when it isn't.

### `discoverComponents()`

`function` · Alpha since 0.31.0 · `@barefootjs/vite`

Scan every configured `components` directory for `.tsx` files and classify each as client (`'use client'`) or server-only. Each entry may be a plain absolute path (shorthand for `{ dir }`, no `cssLayerPrefix`/ `skipDirs`) or a `ResolvedComponentDirEntry`.

### `DiscoveredComponent`

`interface` · Alpha since 0.31.0 · `@barefootjs/vite`

One `.tsx` file `discoverComponents` found under a `components` directory, with everything the compile passes need to act on it: its path and the source snapshot discovery classified, whether it is (or transitively needs) a client entry, the components it exports and instantiates, and the CSS cascade layer its `components` entry asked for.

### `joinBaseAndFile()`

`function` · Alpha since 0.31.0 · `@barefootjs/vite`

Join a Vite `base` (may or may not have a trailing slash; may be a full URL, an absolute path, or `'./'`) with a manifest-relative file path (never starts with `/`) into the URL an adapter should register.

### `loadManifest()`

`function` · Alpha since 0.31.0 · `@barefootjs/vite`

Read and parse the manifest Vite just wrote to `outDir`. `manifestOption` mirrors `build.manifest`: `true` → the default `.vite/manifest.json` path; a string → that custom path, relative to `outDir`.

### `PLUGIN_NAME`

`const` · Alpha since 0.31.0 · `@barefootjs/vite`

The plugin's `name`, for tooling that looks it up in a resolved Vite config's `plugins` array.

### `ResolvedComponentDirEntry`

`interface` · Alpha since 0.31.0 · `@barefootjs/vite`

A `components` directory to scan, already resolved to an absolute `dir`, plus the per-directory compile behavior `barefoot()`'s `ComponentDirEntry` (`types.ts`) carries. `discoverComponents` also accepts a plain absolute path string as shorthand for `{ dir: string }` — the same "string is exactly equivalent to `{ dir }`" equivalence `ComponentDirEntry` itself documents — so existing callers that only ever had bare directories (`integrations/h3`/`elysia`'s `vite.config.ts`, reusing this exported function to resolve every discovered client component's URL) keep compiling and behaving unchanged.

### `resolveDevOrigin()`

`function` · Alpha since 0.31.0 · `@barefootjs/vite`

The dev origin to bake into `scriptAssets`: the user's own `server.origin` if they set one, otherwise `http://localhost:<port>` using the port Vite actually bound — NOT the configured port, which can be wrong (Vite auto-increments past an in-use port unless `strictPort` is set). Also writes the computed default back onto `server.config.server.origin` so Vite's OWN asset-URL rewriting (`import.meta.url`, CSS `url()`, etc.) agrees with the URLs this plugin bakes into templates — both need to match for the cross-origin split (page from the backend, assets from Vite) to work end to end.

### `resolveScriptAssets()`

`function` · Alpha since 0.31.0 · `@barefootjs/vite`

The ordered `scriptAssets` list for one component's entry, per the design: just the entry's own hashed file — shared chunks (including the `@barefootjs/client` runtime) arrive as ESM imports the browser follows on its own, so they need no separate registration. `[]` when the entry isn't in the manifest (e.g. a `'use client'` file whose compile produced no client JS at all, or a stale discovery/build mismatch).

### `toPosixRelative()`

`function` · Alpha since 0.31.0 · `@barefootjs/vite`

Posix-normalized path of `absPath` relative to `root` (manifest keys and Rollup `input` specifiers both want forward slashes regardless of OS).

## Browser mount

Two APIs an app calls itself that live on `@barefootjs/client/runtime`, not on the root entry: `render()` mounts a component with no server-rendered markup (CSR), and `setupStreaming()` installs the swap and re-hydration seams a streaming page or the client router needs. They stay on the browser-only entry because `@barefootjs/client` is SSR-safe — importing it must not pull the DOM runtime into a server bundle. Everything else that entry exports is compiler ABI, emitted into a bundle rather than written, and is not listed here.

| API | Kind | Since | Status |
|---|---|---|---|
| [`render()`](#render) | function | 0.1.0 | **Beta** |
| [`setupStreaming()`](#setupstreaming) | function | 0.1.0 | **Beta** |

> **`render`'s beta promise excludes `ComponentDef`.** The beta promise is the form the CSR page documents — passing a registered component NAME. `render()`'s second overload takes a `ComponentDef` instead, whose remaining fields (`comment`, `fragmentRoot`) are compiler bookkeeping this project is not ready to freeze, so that overload is advanced use at the alpha bar.

### `render()`

`function` · **Beta** since 0.1.0 · `@barefootjs/client/runtime`

Render a component into a container element (CSR mode).

```tsx
// By name (registry-based)
await import('/static/components/Counter.client.js')
render(document.getElementById('app')!, 'Counter', { initialCount: 0 })
```

```tsx
// By ComponentDef (registry-free)
render(container, { name: 'MyNode', init, template }, { id: 'n1' })
```

### `setupStreaming()`

`function` · **Beta** since 0.1.0 · `@barefootjs/client/runtime`

Install the global streaming resolver.

```ts
// client/router-entry.ts — one hand-written entry, registered as a Rollup
// input, loaded once per page before any streamed chunk arrives.
import { setupStreaming } from '@barefootjs/client/runtime'
import { startRouter } from '@barefootjs/router'

setupStreaming()
startRouter()
```

## Adapter builders

Each adapter's `/vite` subpath: a `barefoot()` that constructs the adapter and composes the core plugin, plus its options. All **alpha** — the shape is uniform across the nine, so they are listed rather than written out. See [Vite Plugin → Adapter builders](./vite-plugin.md#adapter-builders).

**`@barefootjs/hono/vite`**

| API | Kind | Since | Status | Summary |
|---|---|---|---|---|
| `barefoot()` | function | 0.31.0 | Alpha | Adapter builder: composes the core `@barefootjs/vite` plugin with a constructed adapter and this backend's post-processing. |
| `HonoViteOptions` | interface | 0.31.0 | Alpha | Options of `@barefootjs/hono/vite`'s `barefoot()`. |
| `HonoViteOptions.components` | option | 0.31.0 | Alpha | Source directories to scan for `.tsx` components, relative to the Vite project root (or absolute). |
| `HonoViteOptions.templates` | option | 0.31.0 | Alpha | Where compiled SSR templates (and `ssrDefaults`) land — relative to the Vite project root (or absolute). |
| `HonoViteOptions.adapterOptions` | option | 0.31.0 | Alpha | Adapter-specific options passed to `HonoAdapter` (e.g. `clientJsFilename`). |
| `HonoViteOptions.assets` | option | 0.31.0 | Alpha | Extra, non-component script entries whose Vite-resolved URL (dev: origin-based; production: content-hashed manifest path) should be exposed to the SSR app as a… |
| `HonoViteOptions.assetsOutputFile` | option | 0.31.0 | Alpha | Output path for the generated asset-map TS module, relative to the Vite project root. |

**`@barefootjs/go-template/vite`**

| API | Kind | Since | Status | Summary |
|---|---|---|---|---|
| `barefoot()` | function | 0.31.0 | Alpha | Adapter builder: composes the core `@barefootjs/vite` plugin with a constructed adapter and this backend's post-processing. |
| `GoTemplateViteOptions` | interface | 0.31.0 | Alpha | Options of `@barefootjs/go-template/vite`'s `barefoot()`. |
| `GoTemplateViteOptions.components` | option | 0.31.0 | Alpha | Source directories to scan for `.tsx` components, relative to the Vite project root (or absolute). |
| `GoTemplateViteOptions.templates` | option | 0.31.0 | Alpha | Where compiled templates, `ssrDefaults`, and `components.go` land — relative to the Vite project root (or absolute). |
| `GoTemplateViteOptions.packageName` | option | 0.31.0 | Alpha | Go package name for generated types (default: 'main'). |
| `GoTemplateViteOptions.typesOutputFile` | option | 0.31.0 | Alpha | Output path for the combined Go types file, relative to the Vite project root (default: 'components.go'). |
| `GoTemplateViteOptions.manualTypes` | option | 0.31.0 | Alpha | Manual type definitions to append (app-specific types not generated from components). |
| `GoTemplateViteOptions.transformTypes` | option | 0.31.0 | Alpha | Transform the combined types string before writing (for app-specific type fixes). |
| `GoTemplateViteOptions.assets` | option | 0.31.0 | Alpha | Extra, non-component script entries whose Vite-resolved URL (dev: origin-based; production: content-hashed manifest path) should be exposed to Go code as a gen… |
| `GoTemplateViteOptions.assetsOutputFile` | option | 0.31.0 | Alpha | Output path for the DEV asset-map file, relative to the Vite project root. |

**`@barefootjs/mojolicious/vite`**

| API | Kind | Since | Status | Summary |
|---|---|---|---|---|
| `barefoot()` | function | 0.31.0 | Alpha | Adapter builder: composes the core `@barefootjs/vite` plugin with a constructed adapter and this backend's post-processing. |
| `MojoliciousViteOptions` | interface | 0.31.0 | Alpha | Options of `@barefootjs/mojolicious/vite`'s `barefoot()`. |
| `MojoliciousViteOptions.components` | option | 0.31.0 | Alpha | Source directories to scan for `.tsx` components, relative to the Vite project root (or absolute). |
| `MojoliciousViteOptions.templates` | option | 0.31.0 | Alpha | Where compiled `.html.ep` templates and `ssrDefaults` land — relative to the Vite project root (or absolute). |
| `MojoliciousViteOptions.assets` | option | 0.31.0 | Alpha | Extra, non-component script entries whose Vite-resolved URL (dev: origin-based; production: content-hashed manifest path) should be exposed to the Perl app as… |
| `MojoliciousViteOptions.assetsOutputFile` | option | 0.31.0 | Alpha | Output path for the generated JSON asset map, relative to the Vite project root. |

**`@barefootjs/xslate/vite`**

| API | Kind | Since | Status | Summary |
|---|---|---|---|---|
| `barefoot()` | function | 0.31.0 | Alpha | Adapter builder: composes the core `@barefootjs/vite` plugin with a constructed adapter and this backend's post-processing. |
| `XslateViteOptions` | interface | 0.31.0 | Alpha | Options of `@barefootjs/xslate/vite`'s `barefoot()`. |
| `XslateViteOptions.components` | option | 0.31.0 | Alpha | Source directories to scan for `.tsx` components, relative to the Vite project root (or absolute). |
| `XslateViteOptions.templates` | option | 0.31.0 | Alpha | Where compiled `.tx` templates and `ssrDefaults` land — relative to the Vite project root (or absolute). |
| `XslateViteOptions.assets` | option | 0.31.0 | Alpha | Extra, non-component script entries whose Vite-resolved URL (dev: origin-based; production: content-hashed manifest path) should be exposed to the Perl app as… |
| `XslateViteOptions.assetsOutputFile` | option | 0.31.0 | Alpha | Output path for the generated JSON asset map, relative to the Vite project root. |

**`@barefootjs/erb/vite`**

| API | Kind | Since | Status | Summary |
|---|---|---|---|---|
| `barefoot()` | function | 0.31.0 | Alpha | Adapter builder: composes the core `@barefootjs/vite` plugin with a constructed adapter and this backend's post-processing. |
| `ErbViteOptions` | interface | 0.31.0 | Alpha | Options of `@barefootjs/erb/vite`'s `barefoot()`. |
| `ErbViteOptions.components` | option | 0.31.0 | Alpha | Source directories to scan for `.tsx` components, relative to the Vite project root (or absolute). |
| `ErbViteOptions.templates` | option | 0.31.0 | Alpha | Where compiled `.erb` templates and `ssrDefaults` land — relative to the Vite project root (or absolute). |
| `ErbViteOptions.assets` | option | 0.31.0 | Alpha | Extra, non-component script entries whose Vite-resolved URL (dev: origin-based; production: content-hashed manifest path) should be exposed to the Ruby app as… |
| `ErbViteOptions.assetsOutputFile` | option | 0.31.0 | Alpha | Output path for the generated JSON asset map, relative to the Vite project root. |

**`@barefootjs/jinja/vite`**

| API | Kind | Since | Status | Summary |
|---|---|---|---|---|
| `barefoot()` | function | 0.31.0 | Alpha | Adapter builder: composes the core `@barefootjs/vite` plugin with a constructed adapter and this backend's post-processing. |
| `JinjaViteOptions` | interface | 0.31.0 | Alpha | Options of `@barefootjs/jinja/vite`'s `barefoot()`. |
| `JinjaViteOptions.components` | option | 0.31.0 | Alpha | Source directories to scan for `.tsx` components, relative to the Vite project root (or absolute). |
| `JinjaViteOptions.templates` | option | 0.31.0 | Alpha | Where compiled `.jinja` templates and `ssrDefaults` land — relative to the Vite project root (or absolute). |
| `JinjaViteOptions.assets` | option | 0.31.0 | Alpha | Extra, non-component script entries whose Vite-resolved URL (dev: origin-based; production: content-hashed manifest path) should be exposed to the Python app a… |
| `JinjaViteOptions.assetsOutputFile` | option | 0.31.0 | Alpha | Output path for the generated JSON asset map, relative to the Vite project root. |

**`@barefootjs/twig/vite`**

| API | Kind | Since | Status | Summary |
|---|---|---|---|---|
| `barefoot()` | function | 0.31.0 | Alpha | Adapter builder: composes the core `@barefootjs/vite` plugin with a constructed adapter and this backend's post-processing. |
| `TwigViteOptions` | interface | 0.31.0 | Alpha | Options of `@barefootjs/twig/vite`'s `barefoot()`. |
| `TwigViteOptions.components` | option | 0.31.0 | Alpha | Source directories to scan for `.tsx` components, relative to the Vite project root (or absolute). |
| `TwigViteOptions.templates` | option | 0.31.0 | Alpha | Where compiled `.twig` templates and `ssrDefaults` land — relative to the Vite project root (or absolute). |
| `TwigViteOptions.assets` | option | 0.31.0 | Alpha | Extra, non-component script entries whose Vite-resolved URL (dev: origin-based; production: content-hashed manifest path) should be exposed to the PHP app as a… |
| `TwigViteOptions.assetsOutputFile` | option | 0.31.0 | Alpha | Output path for the generated JSON asset map, relative to the Vite project root. |

**`@barefootjs/blade/vite`**

| API | Kind | Since | Status | Summary |
|---|---|---|---|---|
| `barefoot()` | function | 0.31.0 | Alpha | Adapter builder: composes the core `@barefootjs/vite` plugin with a constructed adapter and this backend's post-processing. |
| `BladeViteOptions` | interface | 0.31.0 | Alpha | Options of `@barefootjs/blade/vite`'s `barefoot()`. |
| `BladeViteOptions.components` | option | 0.31.0 | Alpha | Source directories to scan for `.tsx` components, relative to the Vite project root (or absolute). |
| `BladeViteOptions.templates` | option | 0.31.0 | Alpha | Where compiled `.blade.php` templates and `ssrDefaults` land — relative to the Vite project root (or absolute). |
| `BladeViteOptions.assets` | option | 0.31.0 | Alpha | Extra, non-component script entries whose Vite-resolved URL (dev: origin-based; production: content-hashed manifest path) should be exposed to the PHP app as a… |
| `BladeViteOptions.assetsOutputFile` | option | 0.31.0 | Alpha | Output path for the generated JSON asset map, relative to the Vite project root. |

**`@barefootjs/rust/vite`**

| API | Kind | Since | Status | Summary |
|---|---|---|---|---|
| `barefoot()` | function | 0.31.0 | Alpha | Adapter builder: composes the core `@barefootjs/vite` plugin with a constructed adapter and this backend's post-processing. |
| `RustViteOptions` | interface | 0.31.0 | Alpha | Options of `@barefootjs/rust/vite`'s `barefoot()`. |
| `RustViteOptions.components` | option | 0.31.0 | Alpha | Source directories to scan for `.tsx` components, relative to the Vite project root (or absolute). |
| `RustViteOptions.templates` | option | 0.31.0 | Alpha | Where compiled `.j2` templates and `ssrDefaults` land — relative to the Vite project root (or absolute). |
| `RustViteOptions.assets` | option | 0.31.0 | Alpha | Extra, non-component script entries whose Vite-resolved URL (dev: origin-based; production: content-hashed manifest path) should be exposed to the Rust app as… |
| `RustViteOptions.assetsOutputFile` | option | 0.31.0 | Alpha | Output path for the generated JSON asset map, relative to the Vite project root. |

## Adapters

The adapter classes, one per backend. Pass an instance as `barefoot()`'s `adapter` option, or use the matching builder above. All **alpha**, as is everything else the adapter packages and `@barefootjs/jsx` export (not itemized here) and the language-side runtimes they ship with.

| Package | API | Kind | Since | Status |
|---|---|---|---|---|
| `@barefootjs/hono` | `HonoAdapter` | class | 0.1.0 | Alpha |
| `@barefootjs/go-template` | `GoTemplateAdapter` | class | 0.1.0 | Alpha |
| `@barefootjs/mojolicious` | `MojoAdapter` | class | 0.1.0 | Alpha |
| `@barefootjs/xslate` | `XslateAdapter` | class | 0.9.1 | Alpha |
| `@barefootjs/erb` | `ErbAdapter` | class | 0.18.0 | Alpha |
| `@barefootjs/jinja` | `JinjaAdapter` | class | 0.18.0 | Alpha |
| `@barefootjs/twig` | `TwigAdapter` | class | 0.18.0 | Alpha |
| `@barefootjs/blade` | `BladeAdapter` | class | 0.18.0 | Alpha |
| `@barefootjs/rust` | `MinijinjaAdapter` | class | 0.18.0 | Alpha |
| `@barefootjs/client/csr-adapter` | `CSRAdapter` | class | 0.1.0 | Alpha |
