.md

Entry-point reference

Every public export, grouped by the package subpath it ships from. Use this as the "which import line do I need?" lookup; the rest of the docs cover what each surface does.

Category
Reference
Entry points
14
Recommended entry
attaform
Bring your own adapter
attaform/abstract

New projects pick attaform. The other subpaths cover explicit Zod pins, the bring-your-own-adapter escape hatch, the Nuxt and Vite integrations, the compiler internals, the DevTools panel, and the type-only surface.

attaform: the recommended entry

The default entry, and the one new projects reach for. useForm here takes a Zod schema and infers every field type from it. It auto-detects the installed Zod major (v3 or v4) and routes to the matching adapter: under the attaform/vite plugin (or attaform/nuxt, which installs it) that resolution happens at build time so the bundle ships one adapter, and without a plugin the entry dispatches at runtime instead.

import { createAttaform, useForm } from 'attaform'

The Zod-default form surface:

  • useForm: the Zod wrapper that infers field types from your schema.
  • useWizard, lazy: the multistep orchestrator and its lazy-step helper.
  • injectForm, injectWizard: reach a provided form or wizard from a descendant component.
  • useRegister: the composable behind v-register, for building custom input components.
  • fieldMeta, withMeta: schema-attached field metadata (label, description, placeholder), backed by a cross-adapter store.
  • unset, isUnset: the blank-anywhere sentinel and its type guard.

On top of that surface, attaform re-exports the framework-agnostic toolkit (the plugin, the directive layer, the SSR bridge, the error classes, the path primitives) that every entry carries. It's listed in full under The framework-agnostic toolkit.

What attaform does NOT ship: the version-specific Zod internals (zodAdapter, kindOf, ZodKind, assertZodVersion, UnsupportedSchemaError). Those diverge between v3 and v4, so they live only on the pinned attaform/zod-v3 and attaform/zod-v4 subpaths.

attaform/zod: the explicit Zod pin

The same surface as attaform, named explicitly. It is byte-identical: attaform is defined as attaform/zod re-exported. Reach for it when you want the import line to name Zod out loud, or when a codebase already standardized on it. New projects don't need the extra characters, and existing attaform/zod code keeps working with no change.

import { useForm } from 'attaform/zod'

attaform/zod-v3

The Zod v3 adapter, pinned with no runtime dispatch, for projects still on v3.

import { useForm, withMeta } from 'attaform/zod-v3'

Ships the same form surface as attaform, plus the v3 zodAdapter and the isZodSchemaType guard. Its runtime introspection is leaner than v4's; see AbstractSchema for the discussion.

attaform/zod-v4

The Zod v4 adapter, pinned explicitly. It's the same adapter attaform selects when it detects zod@4, committed at the import instead of by detection.

import { useForm } from 'attaform/zod-v4'

Ships the richer v4 introspection set on top of the shared form surface: zodAdapter, kindOf, ZodKind, assertZodVersion, UnsupportedSchemaError, and the PathInput / PathOutput type helpers.

attaform/abstract: bring your own adapter

The schema-agnostic escape hatch. useAbstractForm works against any object implementing AbstractSchema: a custom adapter, a non-Zod validation library, or a hand-rolled shape. The Zod entries wrap their schema for you; this entry hands you the unwrapped composable and expects an adapter.

import { useAbstractForm } from 'attaform/abstract'

Ships useAbstractForm, the AbstractSchema contract type, FieldMetaPayload, and the same framework-agnostic toolkit every entry carries. There is deliberately no useForm alias here: a same-named wrong-variant export fails deep at the first schema call instead of at the import site, and removing that footgun is the whole reason the escape hatch is its own entry. This is a lower-level surface than the Zod entries; reach for it only when you're integrating a schema library Attaform doesn't ship an adapter for.

The framework-agnostic toolkit

Every entry re-exports the same schema-agnostic core, so this set is identical whether you import it from attaform, attaform/zod, or attaform/abstract. Pick the entry by which form composable you want; the toolkit rides along.

import {
  // Plugin + registry
  createAttaform,
  useRegistry,
  // Multistep, injection, custom inputs
  useWizard,
  lazy,
  injectForm,
  injectWizard,
  useRegister,
  // Directive layer
  vRegister,
  assignKey,
  defaultCoercionRules,
  defineCoercion,
  // SSR
  renderAttaformState,
  hydrateAttaformState,
  escapeForInlineScript,
  // The unset sentinel
  unset,
  isUnset,
  // Error classes (every Attaform throw extends AttaformError)
  AttaformError,
  InvalidPathError,
  InvalidUseFormConfigError,
  OutsideSetupError,
  RegistryNotInstalledError,
  ReservedFormKeyError,
  SubmitErrorHandlerError,
  // Validation-error codes
  AttaformErrorCode,
  // Display-state heuristic default
  defaultDisplayState,
  // Path primitives (custom adapters only)
  canonicalizePath,
  parseDottedPath,
  isPathPrefix,
  ROOT_PATH,
  ROOT_PATH_KEY,
  // DevTools shared
  DEVTOOLS_WINDOW_KEY,
} from 'attaform'

Also re-exports every public type from runtime/types/types-api and runtime/types/types-core. See Types reference for the full list.

attaform/nuxt

The Nuxt module. Auto-installs the plugin, auto-imports the form composables, and wires the DevTools panel.

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['attaform/nuxt'],
  attaform: {
    defaults: { validateOn: 'change', debounceMs: 100 },
  },
})

After installing, useForm, useWizard, injectForm, injectWizard, fieldMeta, withMeta, and lazy are all global auto-imports (toggle with the module's autoImports option). useAbstractForm, createAttaform, and useRegister stay explicit imports by design. See Installation for the full setup and SSR hydration: Nuxt for the server wiring.

attaform/vite

The Vite plugin. Required under bare Vue + Vite for SSR-correct v-register bindings, and the piece that rewrites attaform / attaform/zod to a single Zod adapter at build time.

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { attaform } from 'attaform/vite'

export default defineConfig({
  plugins: [vue(), attaform()],
})

The same plugin ships for other bundlers at attaform/rollup, attaform/esbuild, attaform/webpack, and attaform/rspack. See SSR hydration: bare Vue for the matching server and client wiring.

attaform/transforms

Raw Vue compiler-core node transforms. Use only when wiring a custom bundler pipeline; the Vite plugin already wraps these for the common case.

import { vRegisterHintTransform, vRegisterPreambleTransform } from 'attaform/transforms'

attaform/devtools-panel

The DevTools panel internals. The Attaform DevTools panel is auto-wired by attaform/nuxt; this entry is exposed for advanced consumers building their own panel hosts.

attaform/types

Type-only subpath. Re-exports every type from the runtime, useful when you want types in a .d.ts consumer file without pulling in the runtime barrel:

import type { UseFormReturnType, FieldState, ValidationError } from 'attaform/types'

For runtime imports under typical app code, import directly from attaform; the type re-exports there are equivalent.

Which subpath for which job?

You want to…Import from
Build a form in a Vue 3 / Nuxt app (Zod v3 or v4)attaform
Pin the Zod v3 adapter explicitlyattaform/zod-v3
Pin the Zod v4 adapter explicitlyattaform/zod-v4
Wire a custom or non-Zod schema libraryattaform/abstract
Install the Nuxt moduleattaform/nuxt
Install the Vite plugin under bare Vue + Viteattaform/vite
Reach directive symbols (vRegister, assignKey, …)attaform
Use SSR helpers (renderAttaformState, etc.)attaform
Catch an Attaform-thrown error by classattaform
Type-only imports in a .d.ts fileattaform/types

The Zod-default story

attaform and attaform/zod are the same surface: the barrel re-exports the unified Zod binding, so useForm infers your field types from a Zod schema out of the box. The abstraction underneath stays schema-agnostic. attaform/abstract exposes it directly through useAbstractForm, which takes an AbstractSchema adapter instead of a Zod schema, and every Zod entry is a thin typed wrapper over that same core. If you're integrating a schema library Attaform doesn't ship an adapter for, AbstractSchema is the contract to implement.

Where to next