> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fluid.app/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> For new direct REST integrations, use the v2026-04 surfaces. The @fluid-app FairShare SDK continues to use its own published public-v2025-06 contract.
> Authenticate with the header Authorization: Bearer <token>; public storefront read endpoints require no auth.
> Lists use cursor pagination via the page[cursor] and page[limit] query params; follow meta.pagination.next_cursor until it is null.
> When the same operation exists on more than one surface, use the newest: dated API versions are newer than unversioned ones, and later dates win (v2026-04 > v2025-06 > unversioned v0/v1.1). Fall back to a legacy or unversioned operation only when no newer versioned equivalent exists — the company-v0 notes below list the known superseded operations. /api/company/v1 and /api/v1/... paths are documented in no spec here and must never be used (/api/v1.1/... is distinct and documented in company-v0). Use page/per_page offset pagination only where a spec documents it — in practice the unversioned company-v0 admin surface; every versioned surface uses cursor pagination.
> The OpenAPI specs under api-reference/ are the authoritative contracts; prefer them over prose when in doubt. api-reference/storefront-v2026-04.yaml covers the v2026-04 storefront surface (/api/v202604/... paths); api-reference/auth-v0.yaml covers the unversioned auth surface (/api/... paths — authentication, MFA, social auth, and token exchange); api-reference/checkout-v2026-04.yaml covers the v2026-04 checkout surface (/api/checkout/v2026-04/... paths — carts, cart auth, discounts, items, subscriptions, orders, enrollments, and store config); api-reference/public-v2025-06.yaml covers the Public SDK surface used by the @fluid-app FairShare SDK, including its parallel cart lifecycle, browser integrations, versioned payment callbacks, unversioned public utilities, and the cart price-override operation; api-reference/payment-v2026-04.yaml covers the v2026-04 payment gateway admin surface (/api/payment/v2026-04/... paths, bearer-authenticated — gateway CRUD, gateway purchase/authorize/$0-verify, transaction list/show and capture/void/credit, and merchant payment configuration); api-reference/payments-v2026-04.yaml covers the v2026-04 cart payment surface (/api/payments/v2026-04/carts/{cart_token}/... paths, authenticated by the cart token in the path with no bearer — payment-method selection, VGS card tokenization, 3D Secure verification, and PayPal/Braintree/Klarna/Apple Pay flows); api-reference/commerce-v2026-04.yaml covers the v2026-04 commerce order-editing surface (/api/v202604/orders/{order_id}/edits paths, bearer-authenticated — post-checkout order edits that atomically insert items and add adjustments/discounts, with an optional dry-run preview); api-reference/webhooks-v0.yaml covers the unversioned webhooks surface (/api/... paths — webhook registration, delivery payloads, callback registrations, company events, and webhook/callback schemas); api-reference/company-v0.yaml covers the legacy unversioned company admin surface (/api/... paths, bearer-authenticated — company settings and management, customers, users, roles, subscription plans, subscription bundles, subscriptions, media, pages, catch-ups, inventory levels, domains, agreements, and admin order actions). company-v0 caveats: it is the legacy v0 admin contract and its lists use flat page/per_page offset pagination, which is expected there despite the general cursor-pagination rule; where an operation exists in both company-v0 and a versioned spec, prefer the versioned spec — the subscriptions lifecycle (list/create/show/update, cancel, pause, reactivate, resume, retry, skip, failed-cycle-waiver, discounts) and subscription bundles are superseded by checkout-v2026-04, and company pages/media CRUD plus the public pages, categories, products, and media list endpoints are superseded by storefront-v2026-04. Subscription plan management (/api/subscription_plans, resource-wrapped {"subscription_plan": {...}} bodies) exists only in company-v0. api-reference/members-v2025-06.yaml covers the v2025-06 unified Member identity surface (/api/v2025-06/members/... paths, bearer-authenticated — member list/create/show/update, lookup by email/username/external_id/legacy_customer_id, member-type assignment, and the sponsor genealogy read). Prefer it over the customers and reps surfaces when the member type matters: /customers does not serialize member_type. api-reference/analytics-v2026-04.yaml covers the v2026-04 Home dashboard analytics surface (/api/v202604/analytics/dashboard/... paths, bearer-authenticated — read-only endpoints for the Home > Overview, Home > Live, and Home > Field tabs, each accepting an optional country ISO alpha-2 query param that scopes aggregations to a single country).
> api-reference/analytics-v0.yaml covers the unversioned analytics surface that backs the fluid-admin Traffic tab (/api/analytics/... and /api/analytics/traffic/... paths, bearer-authenticated — the legacy shares/views/visitors summary plus traffic overview, ranked campaigns, sources, geographies, flows, and per-rep breakdown, all sharing one reporting-period contract).
> Successful responses wrap the resource payload alongside a top-level integer status and a meta object.
> Portal Definition authoring edits and synchronizes the portal JSON resource graph. Widget Package authoring builds either a company-owned or Droplet-owned Remote DOM package. These are separate contracts; do not imply that one defines the other.
> For Widget Package worker code, use only @fluid-app/portal-sdk/widgets/worker. Use only the Portal Definition and Widget Package workflows and public entry points documented here; do not infer support for undocumented surfaces.
> Every portal function and declarative capability used by a widget must appear in that widget's uses array. Use the same typed function value in uses; do not invent capability-name strings.
> Widget styling must use the portal's semantic theme variables for colors, typography, spacing, radii, borders, focus, and charts whenever a token represents the visual decision. Do not create a separate light or dark palette or duplicate theme controls as widget properties.
> Prefer worker-safe Fluid UI components exported by @fluid-app/portal-sdk/widgets/worker when they fit the interaction. When no exported component fits, use semantic HTML, accessible behavior, and the portal theme variables.
> A Portal Definition push updates the remote working definition. A portal version is an immutable snapshot, and activation is a separate live release operation.

# Build reusable layouts with section slots

> Create Liquid containers with named drag-and-drop slots, arrange existing sections in responsive layouts, and give coding agents a precise implementation contract.

A container is an ordinary Liquid section with named **slots**. Each slot holds an ordered list of other section instances. You design the layout; editors choose the sections that fill it.

Use containers for a feature panel beside smaller cards, a content area with a sidebar, or a five-panel showcase. Slots are not limited to left and right columns.

<Note>
  Section slots require container rendering and editor authoring support in your environment. Adding a file to your local theme does not install or publish it in a company's theme.
</Note>

## Understand the building blocks

| Building block    | Responsibility                                                     |
| ----------------- | ------------------------------------------------------------------ |
| Layout            | The outer page shell                                               |
| Page template     | The page's root section placements and saved section configuration |
| Container section | Reusable Liquid markup and CSS that arrange named slots            |
| Slot              | An insertion point for an ordered list of whole sections           |
| Child section     | A normal section instance with its own settings and blocks         |
| Block             | Content within a section, not a replacement for a section slot     |

Your templates remain Liquid. The JSON inside `{% schema %}` stores declarations or configuration; it is not a JSON template migration. Do not create Shopify-style JSON section-group files for this feature.

Navbar and footer templates remain separate from page containers, including country-specific variants. They are not eligible slot children.

## Create your first container

Create `sections/editorial_grid/index.liquid` in your theme:

```liquid theme={null}
{{ 'section-editorial-grid.css' | asset_url | stylesheet_tag }}

<div class="editorial-grid">
  {% section_slot 'main' %}
  {% section_slot 'aside' %}
</div>

{% schema %}
{
  "name": "Editorial grid",
  "settings": [],
  "slots": [
    { "id": "main", "name": "Main content" },
    { "id": "aside", "name": "Sidebar" }
  ],
  "presets": [
    { "name": "Editorial grid" }
  ]
}
{% endschema %}
```

The definition's `slots` array declares the available drop targets. Each `{% section_slot 'main' %}` tag renders the corresponding slot and its assigned children at that position in your markup.

Create `assets/section-editorial-grid.css`:

```css theme={null}
.editorial-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 24px;
}

.editorial-grid > [data-fluid-section-slot] {
  display: grid;
  align-content: start;
  gap: 24px;
  min-width: 0;
}

@media (min-width: 900px) {
  .editorial-grid {
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  }
}
```

This example uses a two-to-one desktop split and stacks on small screens. The gap on each slot separates multiple child sections inside it. Replace the example spacing with your theme's tokens where available.

### Follow the slot contract

* Give each slot a unique, stable ID and a readable name.
* Use 1–64 ASCII letters, numbers, underscores, or hyphens for slot and section instance IDs. Avoid the reserved identifiers `__proto__`, `constructor`, and `prototype`.
* Pass a quoted literal to the tag. Dynamic slot names are not supported.
* Declare every rendered slot in the section schema, and render each slot once.
* Keep slot IDs stable after publishing. Renaming a slot requires updating its saved assignments too.

For example, this is valid:

```liquid theme={null}
{% section_slot 'main' %}
```

This is not valid:

```liquid theme={null}
{% section_slot section.settings.slot_name %}
```

An undeclared slot renders nothing. A declared, empty slot still renders its wrapper.

## Add sections in the editor

After installing the container and its stylesheet in your target theme:

1. Open a compatible page in the **Page Editor**.
2. Add the container from **Sections**.
3. Drag a new section into a slot in the preview, or move an existing page section into it.
4. Use **Layers** to inspect nested sections, reorder them, or move them between slots and back to the page.
5. Edit each child's settings and blocks as you would for a root section.
6. Save, reload, and inspect the result before publishing.

The editor supplies visible drop guides for empty slots. Those guides are editor UI, not storefront content. Visitors see your container styling and the sections you add—not the editor's drop instructions.

Existing section controls continue to support editing, hiding, duplication, deletion, and undo/redo. Duplicating a container copies its subtree with new section and block IDs. Deleting a container removes its children too.

<Note>
  Slot placement does not remove a section's page-type requirements. A section that needs product context still needs a product page. Also test its CSS at the slot's width: a full-width hero does not automatically become a compact card.
</Note>

## See the saved Liquid template

The editor keeps all section instances in the page schema's flat `sections` map. A container instance's `slots` object points to child IDs; it does not embed child objects.

Here is a complete minimal page body. It assumes you have installed the editorial grid above and the text section below. Preserve any existing layout declaration or surrounding page markup when adapting it.

```liquid theme={null}
{% section 'editorial_grid', id: 'summer_grid' %}

{% schema %}
{
  "sections": {
    "summer_grid": {
      "type": "editorial_grid",
      "settings": {},
      "slots": {
        "main": ["summer_story"],
        "aside": ["delivery_note", "pickup_note"]
      }
    },
    "summer_story": {
      "type": "editorial_text",
      "settings": {
        "heading": "Make room for summer",
        "body": "Discover the collection made for long days outdoors."
      }
    },
    "delivery_note": {
      "type": "editorial_text",
      "settings": {
        "heading": "Delivered to your door",
        "body": "Choose your delivery option at checkout."
      }
    },
    "pickup_note": {
      "type": "editorial_text",
      "settings": {
        "heading": "Prefer to collect?",
        "body": "Explore pickup options near you."
      }
    }
  }
}
{% endschema %}
```

Only the root container has a standalone section tag. Do not also add root tags for its children; the slot renders them. The order of IDs in each slot array is the child render order.

Create the example child at `sections/editorial_text/index.liquid`:

```liquid theme={null}
<article class="editorial-text">
  <h2>{{ section.settings.heading | escape }}</h2>
  <p>{{ section.settings.body | escape }}</p>
</article>

{% schema %}
{
  "name": "Editorial text",
  "settings": [
    { "type": "text", "id": "heading", "label": "Heading" },
    { "type": "textarea", "id": "body", "label": "Body" }
  ],
  "presets": [
    { "name": "Editorial text" }
  ]
}
{% endschema %}
```

The child needs no slot-specific markup. Existing sections retain their own settings, blocks, and block ordering when placed inside a container.

A hidden slotted child has `"disabled": true` on its section instance. Use the editor's hide/show controls when moving between root and nested placements, so the saved visibility representation stays consistent.

### Do not confuse the two slots shapes

| Location                              | Shape                                                 | Meaning                                     |
| ------------------------------------- | ----------------------------------------------------- | ------------------------------------------- |
| Container definition schema           | `"slots": [{ "id": "main", "name": "Main content" }]` | Declare the slots your layout offers        |
| Container instance in the page schema | `"slots": { "main": ["summer_story"] }`               | Assign existing section IDs in render order |

## Design a five-slot showcase

You control slot placement through ordinary HTML and CSS. This example gives you one large feature panel and four supporting panels. It uses container width, rather than viewport width, so the layout can also adapt when nested.

Create `sections/panel_showcase/index.liquid`:

```liquid theme={null}
{{ 'section-panel-showcase.css' | asset_url | stylesheet_tag }}

<div class="panel-showcase">
  <div class="panel-showcase__grid">
    {% section_slot 'feature' %}
    {% section_slot 'spotlight' %}
    {% section_slot 'story' %}
    {% section_slot 'collection' %}
    {% section_slot 'action' %}
  </div>
</div>

{% schema %}
{
  "name": "Panel showcase",
  "settings": [],
  "slots": [
    { "id": "feature", "name": "Feature — large panel" },
    { "id": "spotlight", "name": "Spotlight" },
    { "id": "story", "name": "Story" },
    { "id": "collection", "name": "Collection" },
    { "id": "action", "name": "Call to action" }
  ],
  "presets": [
    { "name": "Panel showcase" }
  ]
}
{% endschema %}
```

Create `assets/section-panel-showcase.css`:

```css theme={null}
.panel-showcase {
  container: panel-showcase / inline-size;
  padding: 24px;
  background: var(--color-surface-2, #f5f5f7);
  border-radius: var(--rounded-2xl, 24px);
}

.panel-showcase__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 24px;
}

.panel-showcase__grid > [data-fluid-section-slot] {
  display: grid;
  align-content: start;
  min-width: 0;
  gap: 24px;
  background: var(--color-surface, #fff);
  border: 1px solid var(--color-border, #e4e4e7);
  border-radius: var(--rounded-xl, 16px);
}

@container panel-showcase (min-width: 560px) {
  .panel-showcase__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .panel-showcase__grid > [data-fluid-section-slot="feature"] {
    grid-column: span 2;
  }
}

@container panel-showcase (min-width: 960px) {
  .panel-showcase__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .panel-showcase__grid > [data-fluid-section-slot="feature"] {
    grid-row: span 2;
  }
}
```

The feature spans two columns and two rows at wide widths. At medium widths, it spans the first row above a two-column grid. At narrow widths, all five slots stack in source order.

Use direct-child selectors, as above, to keep a parent container's styles from selecting slots inside a nested container. Keep reading order meaningful without CSS, and check keyboard focus order when changing visual placement. Avoid fixed heights or clipping that could hide a child's content.

### Style the generated wrapper

The slot tag generates this wrapper; you do not write it yourself:

```html theme={null}
<div
  data-fluid-section-slot="feature"
  data-fluid-container-id="summer_showcase"
  data-fluid-slot-name="Feature — large panel"
>
  <!-- Assigned sections render here. -->
</div>
```

Use the slot attribute for scoped styling. The container attribute identifies the placement, not the reusable definition. Do not manufacture these attributes to create drop targets—use the Liquid tag and schema declaration together.

## Reuse and nesting

You can place the same container definition more than once. Each placement has independent settings and child assignments. This is reusable layout code, not globally synchronized content.

Publishing an updated shared definition changes the layout used by its placements. Changing one placement's child settings does not update another placement.

When adding a slot to an already-used definition, initialize its assignment array in every existing placement too—for example, `"new_slot": []`. Publishing the definition alone does not add that assignment to saved instances. Before removing a slot, move or deliberately remove its assigned children; do not leave them stranded in the page configuration.

A slot can contain another container. Keep these limits in mind:

| Rule                                         | Limit                                                 |
| -------------------------------------------- | ----------------------------------------------------- |
| Children in one slot                         | 25                                                    |
| Descendant sections under one root container | 100, including nested containers                      |
| Container depth                              | Four container levels, counting the root as level one |
| Ownership                                    | One parent slot per child instance                    |
| Cycles                                       | A container cannot contain itself or an ancestor      |

Ordinary child sections can sit inside the fourth container level; a fifth container level is not supported. Use separate child instances if you need similar content in multiple slots.

The renderer skips missing, disabled, invalid, or already-claimed child references. Do not rely on that behavior to repair a malformed template: validate ownership, IDs, and limits before saving generated content.

## Install and publish safely

1. Confirm that the environment supports both container rendering and editor authoring.
2. Install the container definition, its stylesheet, and any new child definitions in the intended company's theme. Use your existing [theme development workflow](/themes/cli).
3. Verify that the editor is using that theme and that the required definitions are published for rendering.
4. Add a container to a draft page. Test empty and populated slots, nested placements, and narrow widths.
5. Save and reload. Confirm that child order, settings, and blocks persist.
6. Preview and publish through your normal [Page Editor workflow](/themes/page-editor).

Adding a container definition to a root theme does not install it into an existing company's cloned theme. Install and verify the required definitions and assets in that target theme. Avoid replacing an entire customized theme just to add a container.

<Warning>
  Keep container rendering available while published pages use slots. Turning off new authoring is not a rollback of published content. Before removing rendering support, move children back to root placements or replace the affected pages and verify the published result.
</Warning>

## Troubleshoot a container

| Symptom                                                               | What to check                                                                                                                                              |
| --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Container is missing or unavailable in **Sections**                   | Confirm authoring availability, the selected theme, the installed definition, a valid slot declaration, and page-type compatibility.                       |
| Empty container has no visible drop areas in the preview              | Confirm the editor supports slot guides and that the published definition renders the declared tags. Check for missing CSS, hidden ancestors, or clipping. |
| Layout looks unstyled                                                 | Confirm the stylesheet exists in the same target theme and its asset URL loads successfully.                                                               |
| A child does not render                                               | Check its ID in the flat sections map, its type and definition, hidden state, slot assignment, ownership, and nesting limits.                              |
| **Layers** asks you to correct the template before arranging sections | Repair malformed assignments in the code editor: check missing IDs, repeated ownership, cycles, and the documented limits.                                 |
| A child appears at the page root as well                              | Remove its root section tag; keep the child entry and slot assignment.                                                                                     |
| A child overflows a narrow panel                                      | Inspect the child's fixed widths, viewport-based sizing, and minimum widths. Container placement does not rewrite child CSS.                               |
| Local changes are absent from the published storefront                | Verify the company, active theme, installed files, published definitions, and published page—not only your local checkout.                                 |

## Implementation checklist for coding agents

Treat this page as the section-slot contract. Read the target theme before editing it, and preserve its existing conventions and content.

* Confirm feature availability; do not infer it from the presence of this guide.
* Keep templates in Liquid. Do not introduce JSON template or section-group files.
* Create an ordinary section definition with a schema slot array and matching literal slot tags.
* Design responsive geometry in scoped CSS; use the target theme's tokens where available.
* Keep instances in the flat sections map. Store only ordered child IDs in instance slot assignments.
* Emit root section tags only for root placements. Preserve child settings, blocks, and ordering when moving instances.
* Generate unique instance IDs. Validate one-parent ownership, no cycles, and the documented limits.
* Do not nest navbar or footer templates, or bypass page-type compatibility.
* Do not rename existing slot IDs without migrating their assignments.
* Test drag-and-drop, move-to-root, hide/show, duplicate/delete, undo/redo, save/reload, and published rendering.
* Check an unchanged flat page and country-specific navbar/footer output for regressions.
* Report which files changed and which checks ran. Installing files, publishing a theme, and publishing a page are separate actions; confirm the target and authorization before each remote change.

### Copyable task brief

```text theme={null}
Build a reusable Liquid container for this Fluid theme using the Section slots guide.

First inspect the theme's section structure, styling tokens, and page context.
Confirm that container rendering and editor authoring are available.

Create five slots: feature, spotlight, story, collection, and action.
Use one large feature panel with four supporting panels at wide widths,
and stack all slots in meaningful source order at narrow widths.
Provide the complete section definition and its scoped stylesheet.

Keep Liquid templates and the flat section-instance map.
Use a schema array to declare slots and quoted section_slot tags to render them.
For saved placements, use ordered child IDs in the container's slots object.
Do not add root section tags for slotted children.
Preserve existing sections, settings, blocks, and navbar/footer templates.

Validate IDs, ownership, cycles, depth, and descendant limits.
Verify empty-slot guides, child placement, narrow layouts, and save/reload.
Do not publish or overwrite an existing theme without explicit authorization.
Report completed checks and any environment-dependent checks still needed.
```

For smaller pieces of reusable content, see [Blocks and components](/themes/blocks-and-components). For section controls and placement restrictions, see [Schema components](/themes/schema-components).
