For developers
Connect settings to Content Lists.
Owners connect sections to Content Lists in the editor. Declare what your component can show, then render the values Mirin hands it when the page renders.
On this page
Two ways to connect
Owners connect components to Content Lists in the editor. A connection is saved on the page and resolved when the page renders, so your component receives plain values, never the connection.
One setting, one entry
A text setting shows one field of one entry, such as the title of a class.
- The page saves a
__bindingobject in place of the text. - When the page renders, Mirin swaps it for that field’s value.
One setting, a whole list
A content_list setting shows many entries, sorted and limited the way the owner chooses.
- The page saves a
__contentListBindingobject. - When the page renders, Mirin swaps it for the list’s entries.
Connect a text setting to an entry
Every string, text, textarea and richtext setting shows Connect content list under its field. Nothing extra goes in the schema.
Class Spotlight
Class spotlight
This week’s class
A short note about the class we are featuring this week.

{ "heading": "This week’s class", "intro": "A short note about the class we are featuring this week.", "photo": { "url": "/images/home-next/salt-stone-pilates.webp", "alt": "Two people doing lunges on reformers in a bright studio with a window over a harbor." }}- Choose Connect content list under the field.
- In Connect to a record, keep Pick an entry, then choose the List, the Record and the Field.
- Choose Apply. The field shows the connection with Unbind beside it, and Change content connection underneath. Unbind puts the default back.
Which fields a setting accepts
- A plain text setting
- Accepts text, long text, number, true or false, date, URL, email and slug fields.
- A textarea or richtext setting
- Accepts text, long text and rich text fields.
Other fields stay in the list, disabled and marked incompatible. Use this page’s entry works on dynamic pages, where each page shows one entry of a list.
Connect a dynamic page automatically
On a dynamic page, adding a section can connect it to the page’s entry straight away. Mark the settings that describe the entry with supportsBinding: true, and leave layout and button settings unmarked.
{
"type": "instructor_profile",
"displayName": "Instructor Profile",
"category": "content",
"description": "One instructor's photo, name, role and short bio.",
"props": {
"name": { "type": "string", "displayName": "Name", "supportsBinding": true, "default": "Instructor name" },
"photo": { "type": "image", "displayName": "Photo", "supportsBinding": true, "default": { "url": "", "alt": "" } },
"role": { "type": "string", "displayName": "Role", "supportsBinding": true, "default": "Instructor" },
"bio": { "type": "textarea", "displayName": "Short bio", "supportsBinding": true, "default": "" },
"buttonText": { "type": "string", "displayName": "Button text", "default": "Book with me" }
}
}Add section
A dynamic page for the Instructors list, previewing Maya Brooks.
Instructor Profile
Content · v1.0.0
These fields can be edited independently on each page after you add this section.
- Namestring
- Photoimage
- Rolestring
- Short biotextarea
- Button textstring

Instructor
Instructor name
A few lines about how this instructor teaches.
{ "type": "instructor_profile", "displayName": "Instructor Profile", "props": { "name": { "type": "string", "displayName": "Name", "supportsBinding": true, "default": "Instructor name" }, "photo": { "type": "image", "displayName": "Photo", "supportsBinding": true, "default": { "url": "/images/home-next/salt-stone-pilates.webp", "alt": "Two people doing lunges on reformers in a bright studio with a window over a harbor." } }, "role": { "type": "string", "displayName": "Role", "supportsBinding": true, "default": "Instructor" }, "bio": { "type": "textarea", "displayName": "Short bio", "default": "A few lines about how this instructor teaches." }, "buttonText": { "type": "string", "displayName": "Button text", "supportsBinding": true, "default": "Book with me" } }}- What connects
- A marked setting whose key or displayName matches a field’s slug or name. Case, spaces and punctuation are ignored, and a near miss stays unconnected.
- One setting per field
- Each field connects to the first matching setting only.
- What the owner sees
- A message such as Connected 3 fields, with the names of the fields that now come from the entry on this page.
- Any setting type
- Marked image, link, number and color settings connect too. What each one receives is under What a connected setting receives.
Show a whole list
Declare a content_list setting with editable: true. The owner sees Connect a Content List, picks a list in the drawer, and checks how its fields fill your slots.
{
"type": "class_schedule",
"displayName": "Class Schedule",
"category": "content",
"description": "Upcoming classes from a connected Content List.",
"props": {
"heading": { "type": "string", "displayName": "Heading", "default": "Upcoming classes" },
"classes": {
"type": "content_list",
"displayName": "Classes",
"editable": true,
"itemShape": {
"title": { "type": "string", "required": true },
"startsOn": { "type": "date" },
"photo": { "type": "image" },
"instructor": { "type": "string" }
},
"defaultSort": "starts:asc",
"defaultLimit": 3
}
}
}Class Schedule
Connected list
Classes
Used on this page only
Display options
These display options apply to this section only.
Class schedule
Upcoming classes
Stretch and RestoreSat, Oct 3 · Nora Ellis
Reformer FlowTue, Oct 6 · Maya Brooks
Core and BalanceThu, Oct 8 · Nora Ellis
{ "heading": "Upcoming classes", "classes": { "__contentListBinding": { "collectionSlug": "classes", "collectionId": "c7k2m9x4q1", "fieldMap": { "title": "title", "startsOn": "starts", "photo": "photo", "instructor": "instructor" }, "limit": 3, "sort": "starts:asc" } }}- editable
trueshows Connect a Content List, so the owner chooses the list. Without it the owner cannot choose one.- itemShape
- The slots each entry fills, each with a type and an optional required. The Field map suggests a field for every slot, first by a matching slug or name, then by the first field that fits.
- defaultSort
- The sort a new connection starts with, such as
starts:ascorpublished_at:desc. - defaultLimit
- How many entries a new connection shows.
Without itemShape, the drawer says the component does not declare an item shape, so no field map is needed. Entries then carry only their own field slugs.
Render the entries
When the page renders, the setting arrives as an array. Each entry has id, slug, primaryValue, publishedAt and data. data holds the entry’s fields by slug, plus each slot name from the field map.
type Photo = { url?: string; alt?: string };
type ClassEntry = {
id: string;
slug: string | null;
primaryValue: string | null;
publishedAt: string | null;
data: { title?: string; startsOn?: string; photo?: Photo; instructor?: string };
};
type ClassScheduleProps = {
heading?: string;
classes?: ClassEntry[];
};
export default function ClassSchedule({ heading = '', classes }: ClassScheduleProps) {
const entries = Array.isArray(classes) ? classes : [];
return (
<section className="class-schedule">
<h2>{heading}</h2>
{entries.length === 0 ? (
<p>No classes to show yet.</p>
) : (
<ul>
{entries.map((entry) => (
<li key={entry.id}>
{entry.data.photo?.url && <img src={entry.data.photo.url} alt={entry.data.photo.alt ?? ''} />}
<strong>{entry.data.title}</strong>
<span>{entry.data.startsOn} with {entry.data.instructor}</span>
</li>
))}
</ul>
)}
</section>
);
}Until an owner connects a list, the setting is not an array, so check it before you map over it. Only published entries reach the page.
Sort, limit and pages
Under Display options, Sort by and Show up to apply to this section only. Sort by offers the list’s text, long text, slug, number, date, email and URL fields in either direction. Use list default clears the sort.
- <field slug>:asc or :desc
- By that field of the connected list.
- published_at:desc
- Newest published first. Used when no sort is set.
- created_at:asc or :desc
- By when each entry was created.
- updated_at:asc or :desc
- By when each entry last changed.
- primary_value:asc or :desc
- By each entry’s primary value, such as its title.
There is no published_at:asc. A sort the list cannot use returns no entries, so a field slug in defaultSort only works with a list that has that field.
Pages on a long list
Without a limit, a page shows up to 50 entries. When a list has more entries than the limit, the published page adds Previous page and Next page links under the section, with a line such as Page 2 of 3. Each of those pages has its own address ending in ?page=2.
What a connected setting receives
Mirin converts the entry’s value to fit the setting’s type before your component renders.
- string or text
- The field as text. Numbers and true or false become text, and a rich text field becomes its plain text.
- textarea or richtext
- The field’s value, cleaned before your component receives it.
- link or url
- A full http, https, mailto or tel address, or a path starting with / or #. Anything else arrives as
null. - image
- An object with url and alt, from an image field only. Any other field arrives as
null. - number
- A number, from a number field or from text that reads as one. Anything else arrives as
null. - boolean
- true or false.
- color
- A hex, rgb, hsl or named color. Anything else arrives as
null.
Handle null
A connection arrives as null when its entry is deleted or unpublished, when its field was removed, or when the value does not convert. Default parameter values do not replace null, so give each value a fallback.
type InstructorProfileProps = {
name?: string | null;
photo?: { url: string; alt: string } | null;
role?: string | null;
};
export default function InstructorProfile({ name, photo, role }: InstructorProfileProps) {
return (
<section className="instructor-profile">
{photo?.url && <img src={photo.url} alt={photo.alt} />}
<h2>{name ?? 'Our instructor'}</h2>
{role && <p>{role}</p>}
</section>
);
}Content List fields in data
Inside a list entry, data keeps each field in its own shape.
- text, longText, slug, url, email, select
- Text.
- number
- A number.
- boolean
- true or false.
- date
- Calendar date text, such as 2026-10-06.
- image
- An object with assetId, alt, decorative and url.
- richtext
- A rich text document as JSON, not HTML.
- color
- Lowercase hex text, #rrggbb or #rrggbbaa.
Keep a date on its own day
Preserve the selected day when you format a date. Do not convert it to the visitor’s time zone. Compare event days in the venue’s time zone, keeping today’s events current through the end of that day.
Troubleshooting
What to check when a connection does not show what you expect.
- Why does a connected setting render empty?
- Its entry is unpublished or deleted, its field was removed, or the value does not fit the setting. The setting arrives as null.
- Why does a list render no entries?
- No list is connected yet, the list has no published entries, or the sort names a field the list does not have.
- Why is a field disabled in the picker?
- Its type does not fit the setting. A plain text setting cannot show an image or a select field.
- Why does the drawer show no field map?
- The setting has no itemShape. Add one so owners can match fields to your slots.
- Why did a section not connect on a dynamic page?
- The setting is not marked supportsBinding: true, or neither its key nor its displayName matches a field’s slug or name.