---
title: "Repeating group"
description: "Let a respondent add several instances of the same small set of fields, like guests or line items."
group: "Build forms"
order: 20
type: "reference"
parent: "fields"
keywords:
  - "repeating group"
  - "repeater"
  - "instances"
  - "line items"
  - "array"
  - "validation"
  - "jsx"
updated: "2026-07-20"
---

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:

```ts
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:

```ts
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:

```tsx
<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](/docs/logic): How a child field's `visibleIf` is scoped to its own group.
- [Schema and validation](/docs/schema): Instance-count and per-child validation rules.
- [Matrix](/docs/fields/matrix): A different repeat shape — the same rows against one shared set of columns.
