BuzzForm
Use @buildnbuzz/form-react. The old @buildnbuzz/buzzform package is deprecated.
Quick Start
Install
pnpm add @buildnbuzz/form-react
npx shadcn@latest add @buzzform/all
Add "@buzzform": "https://form.buildnbuzz.com/r/{name}.json" to registries in components.json first.
Provider setup (recommended — app root)
import { FormProvider } from "@buildnbuzz/form-react";
import { registry } from "@/components/buzzform/registry";
// In layout.tsx
<FormProvider registries={{ fields: registry }}>{children}</FormProvider>;
Define schema + render form
import { defineSchema, type InferType } from "@buildnbuzz/form-react";
import {
Form,
FormContent,
FormFields,
FormSubmit,
} from "@/components/buzzform/form";
const schema = defineSchema({
fields: [
{
type: "text",
name: "name",
label: (
<span className="flex items-center gap-1.5">
Name
<Tooltip>
<TooltipTrigger render={<InfoIcon className="size-4" />} />
<TooltipContent>Your full legal name.</TooltipContent>
</Tooltip>
</span>
),
required: true,
},
{ type: "email", name: "email", label: "Email", required: true },
],
});
type FormData = InferType<typeof schema.fields>;
export function ContactForm() {
return (
<Form
schema={schema}
value }) => console.log(value as FormData)}
>
<FormContent>
<FormFields />
<FormSubmit>Submit</FormSubmit>
</FormContent>
</Form>
);
}
Key Concepts
- Use
defineSchema from @buildnbuzz/form-react (NOT @buildnbuzz/form-core) to enable ReactNode (JSX) in labels/descriptions.
- Unified Expressions (
Expr<T>): Unified system for all dynamic field properties (label, disabled, condition, etc.).
$data / $context / $args: JSON Pointer paths (starts with /).
$text: String interpolation (e.g., { $text: "Hello ${/name}" }, supports ${/args/min}).
$when: Ternary logic (e.g., { $when: condition, $then: a, $else: b }).
$fn: Registry calls (e.g., { $fn: "calc", args: { x: 1 } }).
- FormRegistries: Unify components (
fields), validators, and functions (fns) into one object on FormProvider or Form.
- Preference Rule: Prioritize registry functions (
$fn) over inline functions (ctx) => T for complex logic to maintain JSON serializability. Use inline functions only if explicitly requested.
- Inference:
InferType for primitive: true arrays produces flat arrays (string[]) if the child name is empty or omitted.
condition unmounts the field; hidden hides UI but keeps data/validation.
- Option Resolvers enable async option loading. Reference via
{ resolver: "key" } in options.
Imports
import {
defineSchema,
type InferType,
type FormSchema,
defineOptionResolvers,
type OptionResolverRegistry,
useForm,
FormProvider,
type FormRegistries,
RenderFields,
Field,
Form,
walkFields,
isDataField,
toDotNotation,
fromDotNotation,
} from "@buildnbuzz/form-react";
// Shadcn form components (installed via registry)
import {
Form,
FormContent,
FormFields,
FormActions,
FormSubmit,
FormReset,
FormMessage,
} from "@/components/buzzform/form";
import { registry } from "@/components/buzzform/registry";
Read These When Needed
- Complete example with every feature:
examples/onboarding.ts (tested in examples/onboarding.test.ts)
- Cascading dropdowns with async options:
registry/shadcn/examples/country-state-form.tsx
- Schema & field types:
rules/schema.md
- Validation:
rules/validation.md
- Dynamic behavior ($data, $context, conditions):
rules/dynamic.md
- Rendering & custom fields:
rules/rendering.md
- Migration from deprecated package:
references/migration.md
Option Resolver Quick Example
const resolvers = defineOptionResolvers({
listCountries: async () => {
const res = await fetch("https://countriesnow.space/api/v0.1/countries");
const json = await res.json();
return json.data.map((c: { country: string }) => ({
label: c.country,
value: c.country,
}));
},
listStates: async ({ data }) => {
if (!data.country) return [];
const res = await fetch(`/api/states?country=${data.country}`);
const json = await res.json();
return json.states.map((s: { name: string }) => ({
label: s.name,
value: s.name,
}));
},
});
const schema = defineSchema({
fields: [
{ type: "select", name: "country", options: { resolver: "listCountries" } },
{
type: "select",
name: "state",
options: { resolver: "listStates" },
dependencies: ["/country"], // auto re-fetches + clears value
},
],
});
<Form schema={schema} optionResolvers={resolvers}>
<FormContent>
<FormFields />
<FormSubmit />
</FormContent>
</Form>;
Source: buildnbuzz/buzzform — distributed by TomeVault.
1---2name: buzzform3description: Use when working with BuzzForm schema-driven forms, `@buildnbuzz/form-core`, `@buildnbuzz/form-react`, or any related APIs like `defineSchema`, `InferType`, `FormProvider`, `useDataField`, `useLayoutField`, `RenderFields`, `extractDefaults`, registry-based rendering, validation, conditions, or dynamic behavior. Also use for migration from deprecated `@buildnbuzz/buzzform`. Activate this skill whenever the user mentions BuzzForm, form schemas, form registries, TanStack Form integration with BuzzForm, conditional fields, `$data`/`$context` dynamic values, or field type configuration. Even if the user doesn't say "BuzzForm" explicitly, use this skill if they're working in a project that imports from `@buildnbuzz/*` packages. Do NOT trigger for raw TanStack Form usage without BuzzForm, drag-and-drop form builders, or other form libraries like Formik, React Hook Form, or Zod.4---56# BuzzForm78Use `@buildnbuzz/form-react`. The old `@buildnbuzz/buzzform` package is deprecated.910## Quick Start1112**Install**1314```bash15pnpm add @buildnbuzz/form-react16npx shadcn@latest add @buzzform/all17```1819> Add `"@buzzform": "https://form.buildnbuzz.com/r/{name}.json"` to `registries` in `components.json` first.2021**Provider setup (recommended — app root)**2223```tsx24import { FormProvider } from "@buildnbuzz/form-react";25import { registry } from "@/components/buzzform/registry";2627// In layout.tsx28<FormProvider registries={{ fields: registry }}>{children}</FormProvider>;29```3031**Define schema + render form**3233```tsx34import { defineSchema, type InferType } from "@buildnbuzz/form-react";35import {36 Form,37 FormContent,38 FormFields,39 FormSubmit,40} from "@/components/buzzform/form";4142const schema = defineSchema({43 fields: [44 {45 type: "text",46 name: "name",47 label: (48 <span className="flex items-center gap-1.5">49 Name50 <Tooltip>51 <TooltipTrigger render={<InfoIcon className="size-4" />} />52 <TooltipContent>Your full legal name.</TooltipContent>53 </Tooltip>54 </span>55 ),56 required: true,57 },58 { type: "email", name: "email", label: "Email", required: true },59 ],60});6162type FormData = InferType<typeof schema.fields>;6364export function ContactForm() {65 return (66 <Form67 schema={schema}68 onSubmit={({ value }) => console.log(value as FormData)}69 >70 <FormContent>71 <FormFields />72 <FormSubmit>Submit</FormSubmit>73 </FormContent>74 </Form>75 );76}77```7879## Key Concepts8081- Use `defineSchema` from `@buildnbuzz/form-react` (NOT `@buildnbuzz/form-core`) to enable `ReactNode` (JSX) in labels/descriptions.82- **Unified Expressions (`Expr<T>`):** Unified system for all dynamic field properties (`label`, `disabled`, `condition`, etc.).83 - `$data` / `$context` / `$args`: JSON Pointer paths (starts with `/`).84 - `$text`: String interpolation (e.g., `{ $text: "Hello ${/name}" }`, supports `${/args/min}`).85 - `$when`: Ternary logic (e.g., `{ $when: condition, $then: a, $else: b }`).86 - `$fn`: Registry calls (e.g., `{ $fn: "calc", args: { x: 1 } }`).87- **FormRegistries:** Unify components (`fields`), validators, and functions (`fns`) into one object on `FormProvider` or `Form`.88- **Preference Rule:** Prioritize registry functions (`$fn`) over inline functions `(ctx) => T` for complex logic to maintain JSON serializability. Use inline functions only if explicitly requested.89- **Inference:** `InferType` for `primitive: true` arrays produces flat arrays (`string[]`) if the child `name` is empty or omitted.90- `condition` **unmounts** the field; `hidden` hides UI but keeps data/validation.91- **Option Resolvers** enable async option loading. Reference via `{ resolver: "key" }` in `options`.9293## Imports9495```ts96import {97 defineSchema,98 type InferType,99 type FormSchema,100 defineOptionResolvers,101 type OptionResolverRegistry,102 useForm,103 FormProvider,104 type FormRegistries,105 RenderFields,106 Field,107 Form,108 walkFields,109 isDataField,110 toDotNotation,111 fromDotNotation,112} from "@buildnbuzz/form-react";113114// Shadcn form components (installed via registry)115import {116 Form,117 FormContent,118 FormFields,119 FormActions,120 FormSubmit,121 FormReset,122 FormMessage,123} from "@/components/buzzform/form";124import { registry } from "@/components/buzzform/registry";125```126127## Read These When Needed128129- Complete example with every feature: `examples/onboarding.ts` (tested in `examples/onboarding.test.ts`)130- Cascading dropdowns with async options: `registry/shadcn/examples/country-state-form.tsx`131- Schema & field types: `rules/schema.md`132- Validation: `rules/validation.md`133- Dynamic behavior ($data, $context, conditions): `rules/dynamic.md`134- Rendering & custom fields: `rules/rendering.md`135- Migration from deprecated package: `references/migration.md`136137## Option Resolver Quick Example138139```tsx140const resolvers = defineOptionResolvers({141 listCountries: async () => {142 const res = await fetch("https://countriesnow.space/api/v0.1/countries");143 const json = await res.json();144 return json.data.map((c: { country: string }) => ({145 label: c.country,146 value: c.country,147 }));148 },149 listStates: async ({ data }) => {150 if (!data.country) return [];151 const res = await fetch(`/api/states?country=${data.country}`);152 const json = await res.json();153 return json.states.map((s: { name: string }) => ({154 label: s.name,155 value: s.name,156 }));157 },158});159160const schema = defineSchema({161 fields: [162 { type: "select", name: "country", options: { resolver: "listCountries" } },163 {164 type: "select",165 name: "state",166 options: { resolver: "listStates" },167 dependencies: ["/country"], // auto re-fetches + clears value168 },169 ],170});171172<Form schema={schema} optionResolvers={resolvers}>173 <FormContent>174 <FormFields />175 <FormSubmit />176 </FormContent>177</Form>;178```179180---181> Source: [buildnbuzz/buzzform](https://github.com/buildnbuzz/buzzform) — distributed by [TomeVault](https://tomevault.io).182<!-- tomevault:4.0:skill_md:2026-07-04 -->