The custom field stores arbitrary JSON and delegates rendering and type-specific validation to a component you provide.
Options
| Option | Type | Behavior |
|---|---|---|
component | string | Selects a renderer from the SDK customComponents map |
config | Record<string, unknown> | Passes JSON configuration to that renderer |
required | boolean | Lets core reject an empty value |
Core doesn't know the shape of a custom answer. It checks that a required field isn't empty, then preserves the JSON value as-is — richer validation and accessible interaction are your component's job.
Custom fields are code-only. They don't appear in the dashboard's Add block palette because the dashboard can't supply your host component.
Define and render a custom field
tsx
const form = defineForm({
id: "delivery-area",
pages: [{
id: "main",
blocks: [{
id: "location",
kind: "custom",
component: "map-pin",
label: "Drop a pin",
required: true,
config: { zoom: 12 },
}],
}],
});
<FilloForm
form={form}
client={client}
customComponents={{ "map-pin": MapPinField }}
/>Custom fields can't be prefilled from a URL. Use initialData when the component can safely accept a known initial value.
Related
- Custom UI: Implement the renderer contract and full headless layouts.
- Schema and validation: Understand what core can and can't validate.
- Fields: Use a built-in type when its value model already fits.