Skip to main content
A schema describes the controls and content structure that Fluid exposes in the visual editor. Place valid JSON between {% schema %} and {% endschema %} in a section or standalone block.
The schema tag does not render HTML. Your Liquid markup reads the values that an editor selects.

Define a section schema

A section schema can use these top-level fields:

Limit a section to certain templates

Use enabled_on to allow a section only on the templates you list. In the Page Editor, the section then appears under Not available here on every other template. This section is allowed only on product templates:
A section without enabled_on is available on every template. Lint accepts disabled_on, but the editor ignores it, so list the allowed templates in enabled_on instead.

Define a setting

Every setting needs a supported type. Every value-producing setting needs a unique, non-empty id within its settings array. Use the ID to read the saved value:
Common setting fields include: Section and block controls ignore unit and placeholder. The theme panel reads unit on typography presets. See settings schema. Keep IDs stable after a theme ships. Changing an ID disconnects the schema from existing saved values.

Choose a setting type

Section and block settings render the same control for each type, with one exception: blocks do not accept image. Use image_picker, which renders the same control in both. In a block, a type without a control renders the word Unknown instead of an input. Where an alias is shown, use one spelling consistently within a theme. Settings in config/settings_schema.json render in the theme panel, which supports fewer types. See settings schema.

Text and URL

text is not plain text. It saves HTML, such as Free delivery on <strong>every</strong> order. Use plaintext for any value that ends up in an HTML attribute, a CSS value, a URL, or a script.
The variable picker in both rich-text editors inserts a Liquid tag such as {{ company.name }}. Fluid renders Liquid tags in saved setting values before your template reads them, so the page shows the current value. The url picker lists store destinations, such as the home page, pages, products, collections, categories, posts, and media. It saves the selected destination’s URL. Editors can also type any URL.

Numbers

Define min, max, and step on every range. Without them, the slider runs from 0 to 100 in steps of 1.
Use number for open-ended values. min, max, and step are optional; when set, the editor keeps entries between min and max.
An editor can clear a number field, so give the value a fallback in Liquid:

Choices

Use label and value for each explicit select or radio choice:
Select and radio values are saved as strings, even when you write a number. Compare them with quoted values in Liquid: {% if section.settings.columns == '3' %}. To share one list of choices across several settings, use an option group.

Color and fonts

Apply a color_background value with the background property. background-color ignores gradients.
List the fonts a font picker offers in options, or point options at an option group. Without options, the picker offers system fonts: System UI, Apple System, Segoe UI, Roboto, Helvetica, Arial, and Sans Serif.

Images, video, and media

Each picker also shows an alt text field. The editor saves alt text in a companion setting named <id>_alt, so do not declare it yourself. Choosing a new image or video clears the alt text. Render a picker’s value with the media_tag filter, which builds responsive markup and renders nothing for an empty value:

Read a media picker

A media_picker saves an object, because it carries both the file and its embed options:
Read url from the object: {{ section.settings.banner_media.url }}, not {{ section.settings.banner_media }}. embed_settings can be missing, so check the object before you read nested values. A positive fluid_media_id identifies a Fluid media item, which you render with the media widget. The ID can be 0 for a plain file, so compare it with > 0. Liquid treats 0 as true, so != blank does not work here.
embed_type maps to the widget’s embed-type attribute: See the media widget for its other attributes.

Layout

Corner and side values are numbers of pixels. A value linked to a theme preset is a CSS variable reference, such as var(--spacing-lg). Padding and radius presets come from the padding and corner_radius groups, and border and overlay colors from color_schema. See linked CSS presets. Add px only to plain numbers:
A border saves its width with the unit, such as { "width": "2px", "color": "#d0d5dd" }. A gradient overlay saves an object like this:
mode is solid or gradient, and gradientType is linear or radial. opacity and position run from 0 to 100; position is optional. A color can be a hex value or a var(--...) preset reference. Render nothing when enabled is false.

Organization

Use header to group the settings that follow it:
Each header starts a collapsible group that runs to the next header. The group’s title is the header’s content, or its label. The first group opens by default, and settings before the first header appear above all groups. A group disappears when its header’s visible_if is false, or when every setting in it is hidden. A header organizes controls. It does not create a value that you read in Liquid.

Resource selectors

Resource pickers save record IDs. Fluid resolves the following setting types into Liquid resource values before your template reads them: media has no control in the section or block panel. Set its value to a media ID or slug in a preset. An unset resolved setting is an empty object, or an empty array for product_list. Liquid treats an empty object as true, so test it with != blank:

Let editors choose several products

Use product_list when the editor should choose several products. Set limit to cap the selection. Iterate the resolved value:

Pickers that Fluid does not resolve

These types also open a picker, but Liquid receives the saved ID, or an array of IDs: Look the records up yourself, or use a resolved type instead.
The plural types are not aliases of the singular ones. products opens a multi-select picker and saves unresolved IDs, while product saves one product that Fluid resolves. For several resolved products, use product_list.

Types from other platforms

fluid theme lint rejects these types with Invalid settings type. Use the Fluid equivalent:

Show settings conditionally

Add visible_if to show a setting only when a condition is true. Write the condition as an expression, with or without {{ }}:
A section setting’s condition reads section.settings.<id>. A block setting’s condition can read block.settings.<id> as well as section.settings.<id>. && and || work as and and or. A value can be a setting path, a quoted string, a number, true, false, or null. and binds tighter than or. A string compared with a number compares as a number, so '3' == 3 is true.
visible_if only hides the control in the editor. A hidden setting keeps its saved value, and Liquid still receives it, so check the same condition in your template. If the editor cannot evaluate a condition, it shows the setting. The theme panel ignores visible_if.

Define inline blocks

Inline blocks belong to one section. A block definition needs type and name when it defines settings.
Block settings must be an array. Duplicate block types are ambiguous and produce a validation warning. Duplicate setting IDs produce an error. Render inline blocks from section.blocks:
Standalone block references contain only type. Use @theme to accept public standalone blocks and @app to accept compatible extension blocks. See blocks and components for rendering and nesting patterns.

Add presets

A preset can provide a display name, picker category, initial settings, and initial blocks.
Use preset values that match IDs declared in the section and block schemas. A preset does not add new setting definitions.

Reuse option groups

Use an option group when several section or block settings should share a choice list defined by the root theme. This keeps choices such as type scales consistent across the editor. First, add option_group metadata to settings in config/settings_schema.json:
Each matching option_group.id contributes one choice. The editor uses option_group.label as the choice label and option_group.value as its saved value. Duplicate values are collapsed to the first matching choice. Then set options to the plain option-group ID:
Use only letters, numbers, _, and - in an option-group ID. If the group is missing or malformed, the editor cannot resolve choices for the setting. An explicit options array continues to work and takes precedence over option-group resolution.
Do not use a Liquid expression or an object in options to reference an option group. Use the plain group ID, such as "type_scale".
See root theme configuration for the rest of the settings flow.

Validate before publishing

Before you publish a schema:
  • Confirm that the schema body is valid JSON.
  • Give each value-producing setting a unique, non-empty ID.
  • Use only supported setting types, and image_picker rather than image in blocks.
  • Use plaintext, not text, for values that go into attributes, CSS, or URLs.
  • Test resolved resource settings with != blank.
  • Define block settings as an array.
  • Give inline blocks a name.
  • Confirm that preset values match declared IDs and block types.
  • Confirm that named standalone blocks exist.
  • Test default and edited values in the visual editor.
Run fluid theme lint --json to catch schema and reference problems before you push. See the CLI guide for the complete local workflow.