Skip to main content

The Fillo API, on one page.

Every prop, hook, client method, settings key, theme token, and renderer string in @usefillo/react, @usefillo/core, and @usefillo/dom. The token and string tables render from the SDK’s own exports, so they can’t drift.

Task-shaped docs: install at /docs/embed, JSX authoring at /docs/authoring, slots and data-* attributes at /docs/styling.

On this page

<FilloForm>

The framed renderer. Pass formId (a published, dashboard-hosted form) or form (a schema or a code-defined form); code forms need client to save responses.

PropTypeWhat it does
formIdstringFetch a published form by id or slug. With only this prop, a default client (→ fillo.so) is created.
formFormSchema | CodeFormRender a schema directly, or a defineForm() / Fillo.defineForm() form — which also syncs.
clientFilloClientFrom createClient(). Required for code-defined forms that should save responses.
themeFormThemeTheme tokens. Precedence: appearance.theme, then this prop, then the code form's theme, then the dashboard theme.
appearanceFilloAppearanceThe styling contract: theme + per-slot classNames + per-field overrides. See /docs/styling.
stringsPartial<FilloStrings>Override any visitor-facing renderer string (localized sites).
componentsFieldComponentsSwap any built-in field kind for your own component.
customComponentsCustomComponentsRenderers for your own `custom` field kinds, keyed by the field's `component`.
initialDataResponseDataPre-filled answers, keyed by field id.
onChange(data: ResponseData) => voidFires with the full answer map on every edit.
onSubmitted(responseId: string | undefined, data: ResponseData) => voidRuns after Fillo records the response.
onError(error: FilloError) => voidObserve load and code-form sync failures (otherwise only logged).
showTitleboolean (default true)Render the form's own title/description header. Set false when the page already has the heading.
renderSuccess() => ReactNodeCustom success screen.
renderError(error: FilloError) => ReactNodeCustom error screen — receives the failure (e.g. 404 vs network).
classNamestringExtra classes on the root element.

<FilloProvider> + <FormField>

The headless escape hatch: runs the same engine, renders no layout. Compose your own with <FormField>, useField(), and useFillo()— render every required field, or submission fails on a field the visitor can’t see.

PropTypeWhat it does
formFormSchema | CodeForm (required)The schema to run. A defineForm() form also syncs, exactly like <FilloForm>.
clientFilloClientSubmission (and sync) target.
formIdstringExplicit submission target for a plain schema.
appearanceFilloAppearanceSlot classes for FormField-rendered fields.
stringsPartial<FilloStrings>Renderer string overrides.
initialDataResponseDataPre-filled answers.
onChange / onSubmittedas on <FilloForm>Same callbacks, same timing.
childrenReactNodeYour layout — fields go wherever you render them.

<FormField> renders one field with the default (or overridden) component, in your layout:

PropTypeWhat it does
idstring (required)Which field to render. Returns null for unknown ids and for fields hidden by conditional logic.
componentsFieldComponentsPer-kind overrides, scoped to this one field.
customComponentsCustomComponentsCustom-kind renderers, scoped to this one field.

<Fillo.Form> extras

The JSX authoring root (guide: /docs/authoring). Besides every <FilloForm> prop above (except form/formId), it takes the schema-level props:

PropTypeWhat it does
idstring (required)Workspace handle — the form's identity across syncs.
title / descriptionstringForm header copy, compiled into the schema.
settingsFormSettingsThe settings.* keys below, compiled into the schema.
themeFormThemeTheme tokens, compiled into the CodeForm (they sync to the hosted page).
clientFilloClientSync + submission target.
childrenFillo.* elementsThe schema: pages or blocks. Never rendered — compiled.

Hooks

useFillo() returns the full engine API — it throws outside <FilloForm> / <FilloProvider>:

MemberTypeWhat it is
formFormSchemaThe normalized schema being rendered.
formIdstring | undefinedSubmission target, once known (code forms resolve it after sync).
clientFilloClient | undefinedThe client in use.
dataResponseDataCurrent answers, keyed by field id.
errorsRecord<string, string>Validation messages, keyed by field id.
setValue(fieldId, value) => voidWrite an answer. Clears that field's error; re-checked on next/submit.
pageIndex / pageCountnumberCurrent page (0-based) and total pages.
pageFormPageThe current page.
blocksBlock[]The current page's blocks after conditional-visibility logic.
isFirstPage / isLastPagebooleanPosition flags for your own footer.
next() / back()() => voidPage navigation. next() validates the current page first and stays put on errors.
submit()() => Promise<void>Validates everything, submits, and settles state. Rejections also land in submitError.
status"idle" | "submitting" | "submitted" | "error"Engine status (also on the root as data-state).
uploadingbooleanTrue while any file upload is in flight — submit is blocked.
submitErrorstring | undefinedMessage of the last failed submit; cleared on edit/retry.
setUploading(fieldId, busy) => voidUsed by upload fields to gate submission.

useField(id) drives one field — the lowest-level hook:

MemberTypeWhat it is
fieldField | undefinedThe field's schema entry, or undefined if no field has this id.
valueFieldValueThe current answer.
errorstring | undefinedThe current validation message.
setValue(value: FieldValue) => voidWrite the answer.

useFilloController(options) is the React binding both components use — same options as <FilloProvider>. Outside React, the identical engine is createFormController() from @usefillo/core or @usefillo/dom.

hooks in a headless layout
import { FilloProvider, FormField, useField, useFillo } from "@usefillo/react";

function SubmitBar() {
  const { isLastPage, next, submit, status } = useFillo();
  return (
    <button onClick={() => (isLastPage ? void submit() : next())}>
      {status === "submitting" ? "Sending…" : isLastPage ? "Send" : "Next"}
    </button>
  );
}

function BareEmail() {
  const { value, error, setValue } = useField("email");
  return <input value={String(value ?? "")} onChange={(e) => setValue(e.target.value)} aria-invalid={!!error} />;
}

createClient

one client per app
import { createClient } from "@usefillo/react"; // or "@usefillo/dom"

const client = createClient({
  key: process.env.NEXT_PUBLIC_FILLO_KEY!, // pk_… — public by design
});
OptionTypeWhat it does
keystringPublishable workspace key (pk_…) — safe to ship in client code. Required only for syncing code-defined forms.
baseUrlstringTarget a different Fillo server (staging, tests, a proxy on your own domain). Wins over sameOrigin.
sameOriginbooleanInternal: Fillo's own first-party pages only. Not for embedding.
fetchtypeof fetchCustom fetch implementation.

Methods — requests time out after 30 seconds; failures throw FilloError with status and, on 429, retryAfterSec:

MethodReturnsWhat it does
getForm(idOrSlug)Promise<PublishedForm>Fetch a published form: { id, slug, schema, theme, closed?, branding? }.
submit(formId, data, meta?)Promise<SubmitResult>Record a response. Validation failure returns { ok: false, errors } (per field) instead of throwing.
syncForm(handle, schema, theme?)Promise<SyncFormResult>Upsert a code-defined form into the workspace. Needs `key`; returns the canonical formId and lifecycle status.
uploadFile(formId, file, { fieldId, onProgress?, signal?, sessionId?, uploadToken? })Promise<FileValue>Resumable chunked upload straight to the form's storage; the FileValue goes into response data.

settings.* keys

On defineForm({ settings }), <Fillo.Form settings={…}>, or the dashboard. All optional.

KeyTypeWhat it does
submitMode"button" | "auto"Default "button". "auto" submits after a single discrete answer and hides the final submit button — one-tap votes, CSAT, NPS.
submitLabelstringCustom submit button text.
successTitlestringThank-you screen title (wins over the strings default).
successMessagestringThank-you screen body (wins over the strings default).
redirectUrlstringRedirect after submit instead of the success screen. http(s) only.
showProgressbooleanProgress bar on multi-page forms (default true).
submissionLimit"multiple" | "once_per_visitor"Default "multiple". once_per_visitor remembers this browser answered and sends a server-side de-duplication key.
notifyEmailstringNotify this address on every submission.
sendReceiptbooleanEmail respondents a receipt (to the first answered email field).

Theme tokens

Generated from FILLO_THEME_VARS (exported by @usefillo/core). Tokens with a FormTheme key are set inline by the theme prop / defineForm({ theme }) and sync to the hosted page; the rest are stylesheet-only — override them from your CSS on any ancestor. FormTheme.colorScheme is not a variable: it sets data-fillo-color-scheme on the root.

CSS variableFormTheme keyWhat it paints
--fillo-primaryprimaryButtons, focus rings, selection.
--fillo-bgbackgroundForm background.
--fillo-texttextBody text.
--fillo-radiusradiusCorner radius scale.
--fillo-fontfontFamilyFont family.
--fillo-mutedstylesheet-onlyDescriptions, hints, placeholders.
--fillo-borderstylesheet-onlyInput borders, dividers.
--fillo-control-bgstylesheet-onlyInput backgrounds.
--fillo-errorstylesheet-onlyValidation messages.
--fillo-primary-contraststylesheet-onlyText on primary buttons.

Strings

Generated from DEFAULT_STRINGS (exported by @usefillo/core). Override any subset via the strings prop; schema-authored text — labels, success copy in settings — always wins.

KeyDefaultShown
backBackBack button on multi-page forms.
nextNextNext button between pages.
submitSubmitSubmit button on the last page (settings.submitLabel wins).
submittingSubmitting…Submit button while the request is in flight.
uploadingUploading…Submit button while a file upload is in flight.
optional (optional)Suffix on non-required field labels.
otherOtherThe "Other" free-text choice row.
otherPromptOther — please specifyThe "Other" dropdown entry prompt.
otherPlaceholderYour answerPlaceholder of the "Other" free-text input.
choosePlaceholderChoose…Dropdown placeholder when the field sets none.
successTitleThanks!Success screen title (settings.successTitle wins).
successMessageYour response has been recorded.Success screen body (settings.successMessage wins).
closedThis form is no longer accepting responses.The form is no longer accepting responses.
notLiveThis form isn't live yet.An unpublished code form, in production.
submitFailedThis form can't submit right now. Please try again in a moment.Fallback when a submit fails without a server message.
loadFailedNotFoundForm not found — check the form id and that it's published.A hosted form id/slug that doesn't resolve (404).
loadFailedNetworkCouldn't reach the server — check your connection or CORS.The load request never reached the server.
loadFailedThis form could not be loaded.Any other load failure.
renderFailedThis form could not be rendered.The schema failed validation and can't render.

@usefillo/dom

renderForm(target, options) target is an element or a selector string; returns a handle.

render + drive
import { renderForm } from "@usefillo/dom";
import "@usefillo/dom/styles.css";

const instance = renderForm("#form", {
  formId: "customer-onboarding",
  onSubmitted: (id, data) => console.log("response", id, data),
});

// instance.setValue("email", "jane@example.com");
// await instance.submit();
// instance.destroy();
OptionTypeWhat it does
formFormSchema | CodeFormRender a schema or a defineForm() form (which also syncs).
formIdstringFetch a published form by id or slug (a default client is created if none is passed).
clientFilloClientSubmission (and sync) target.
themeFormThemeTheme tokens applied to the root.
initialDataResponseDataPre-filled answers.
classNamestringExtra classes on the rendered form.
componentsPartial<Record<FieldKind, FieldRenderer>>Swap any built-in field kind; a FieldRenderer returns an HTMLElement.
customComponentsRecord<string, FieldRenderer>Renderers for your own `custom` field kinds.
onChange / onSubmitted / onErroras on <FilloForm>Same callbacks, same timing.
renderSuccess(api: FilloDomApi) => HTMLElementCustom success screen.
renderError(error: FilloError) => HTMLElementCustom error screen.

The returned handle:

MemberTypeWhat it is
elementHTMLElementThe rendered root.
statusFormStatus | "loading" | "closed"Engine status, plus the wrapper-only fetching/closed states.
dataResponseDataCurrent answers.
formFormSchema | nullThe resolved schema (null while loading).
setValue(fieldId, value)voidWrite an answer programmatically.
next() / back()voidPage navigation (next validates first).
submit()Promise<void>Validate and submit.
destroy()voidTear down the DOM and every listener.

Also exported: createFormElement(options) (build a detached node), the <fillo-form> web component (registerFilloElement(); publishable-key / form-id attributes, fillo-change / fillo-submit / fillo-error events), and createFormController() — the render-nothing engine for Vue, Svelte, or vanilla layouts.

Was this page useful?

Was this page helpful?
Powered by Fillo