The repeating group field renders a small template of fields as a card, and lets the respondent add or remove instances of it — a guest list, order line items, or any "one row per thing" question. Each instance stores its own answers for every field in the template.
Options
| Option | Type | Default | Behavior |
|---|---|---|---|
fields | Field[] | required | The repeated template, up to 12 fields |
maxInstances | number | required | Upper bound on instances, 1 through 20 |
minInstances | number | 1 | Lower bound, 0 through maxInstances |
addLabel | string | "Add another" | Label on the add-instance button |
itemLabel | string | the field's label | Names one instance — headings, announcements, and export columns |
maxInstances is required and bounded (1–20) so a form can never grow unbounded mid-fill; an out-of-range minInstances or maxInstances is a schema error, not a silent clamp. The container's own required is always false — minInstances alone governs whether the field needs an answer, the same way hidden and calculated fields are never required.
Value shape
A repeating group stores an array of objects, one per instance, each one keyed by child field ID:
data.guests = [
{ name: "Ada Lovelace", email: "ada@example.com" },
{ name: "Grace Hopper", email: "grace@example.com" },
];A child's value uses the exact same shape a top-level field of that kind would store. An absent key means zero instances — unanswered only when minInstances is 0. Instances keep the order the respondent added them in; there is no respondent-facing reordering.
Template fields
Template fields are drawn from a restricted set: short_text, long_text, email, url, phone, number, select, multi_select, dropdown, checkbox, date, rating, and linear_scale. A nested repeating_group, calculated, file_upload, signature, matrix, ranking, hidden, or custom child is a schema error — each is more instance-plumbing than a v1 group takes on.
A child's visibleIf may reference only another field in the same group, evaluated per instance over that instance's own answers. Nothing outside the group can reference a child field, and a child can't reference anything outside the group — both directions are schema errors, so a group's logic never depends on (or leaks into) the rest of the form.
Validation
An instance count outside minInstances–maxInstances is a real validation error in both directions on submit — unlike a calculated field, the count is respondent input (a group with minInstances: 2, maxInstances: 3 rejects one instance with "Add at least 2 entries" and rejects a fifth with "At most 3 entries"). Each child is validated per instance with the same rules a top-level field of that kind uses. A failing child's error is keyed ${groupId}.${index}.${childId} — guests.0.email names the first instance's email child when the group's id is guests — dot-safe everywhere a plain field id is (DOM ids, aria-describedby, the client errors map), and it's the documented way to address one instance's field from outside a renderer. A key inside a submitted instance that doesn't match any child id is dropped silently rather than rejected, the same convention an unrecognized top-level field id already follows.
Add a repeating group
In the dashboard, select Add block, choose Repeating group, then add child fields to the template the same way you would to a page, and set the instance bounds.
In code:
const guests = {
id: "guests",
kind: "repeating_group",
label: "Guests",
itemLabel: "Guest",
minInstances: 1,
maxInstances: 6,
fields: [
{ id: "name", kind: "short_text", label: "Name", required: true },
{ id: "email", kind: "email", label: "Email" },
],
} as const;With JSX (React), the template is written as ordinary field children — the one place a <Fillo.*> element nests other field elements instead of configuring them through props:
<Fillo.RepeatingGroup id="guests" label="Guests" itemLabel="Guest" minInstances={1} maxInstances={6}>
<Fillo.Text id="name" label="Name" required />
<Fillo.Email id="email" label="Email" />
</Fillo.RepeatingGroup>Only field elements are allowed as children — a <Fillo.Page>, <Fillo.Option>, or content block there is a compile-time error, the same fail-loud rule as an unsupported child kind.
Where instances show up
The responses grid shows one summary cell per response ("3 × Guest: Ada, Grace, Alan"); opening the response shows every instance in full, each one its own "Guest n" card. CSV export writes wide, deterministic columns — maxInstances times the number of child fields, headed "Guest 1 — Name", "Guest 1 — Email", "Guest 2 — Name", and so on, from the schema rather than from any one response, so the header never shifts between rows. Webhooks, the API, and Zapier carry the raw instance array in answers and the same one-line summary in formatted. Google Sheets and Notion carry that same one-line summary text in v1 — a dedicated child record per instance (a second Sheets tab, a linked Notion database) is a deliberate later step, not part of this release.
SDK compatibility
A form containing a repeating group serves a raised minimum SDK version (0.13.0) from the public form endpoint. An older SDK doesn't recognize the repeating_group kind and would drop the whole field silently, so it fails fast with an update message instead of rendering an incomplete form.
Related
- Conditional logic: How a child field's
visibleIfis scoped to its own group. - Schema and validation: Instance-count and per-child validation rules.
- Matrix: A different repeat shape — the same rows against one shared set of columns.