Knowledge Hub
What section schema does
Section schema is the JSON contract between your Liquid markup and the Shopify theme editor. It declares which parts of a section merchants can edit—headings, images, links, colors, collection pickers—and how repeatable rows behave as blocks. Without schema, a section is frozen HTML. With thoughtful schema, the same section powers dozens of storefront layouts.
Schema lives inside {% schema %} tags at the bottom of section.liquid files. Shopify validates it on save and renders form fields in the editor sidebar. The /liquid-schema-generator and /converter both output schema aligned with Online Store 2.0 rules.
Schema structure overview
- name — display name in the theme editor and Add section list
- tag — optional semantic wrapper (section, header, footer)
- class — optional CSS class on the section wrapper
- settings — array of section-level setting objects
- blocks — array of block type definitions
- max_blocks — limit repeatable rows
- presets — default configurations surfaced in Add section
- default — fallback values for settings
Full schema skeleton
{% schema %}
{
"name": "Feature grid",
"tag": "section",
"settings": [],
"blocks": [
{
"type": "feature",
"name": "Feature",
"settings": []
}
],
"max_blocks": 12,
"presets": [{ "name": "Feature grid", "blocks": [{ "type": "feature" }] }]
}
{% endschema %}Section settings deep dive
Section settings apply to the whole section—module heading, background color, collection picker, padding controls. Each setting needs a unique id, a type, and a merchant-facing label. Optional help_text and info fields reduce support tickets.
Common setting types
- text — single-line strings for headings and labels
- richtext — multi-paragraph copy with basic formatting
- image_picker — uploads tied to image_url and image_tag filters
- url — link picker for CTAs and external URLs
- collection / product — resource pickers for merchandising sections
- range — numeric sliders for padding, font size, product limits
- checkbox — boolean toggles for show/hide features
- select — enumerated options mapped to CSS modifier classes
- color — hex color picker for backgrounds and text
Typed settings example
{
"type": "range",
"id": "padding_top",
"min": 0,
"max": 100,
"step": 4,
"unit": "px",
"label": "Top padding",
"default": 36
}Blocks in schema
Blocks define repeatable content types—FAQ items, slides, feature cards. Each block type has its own settings array. In Liquid you loop {% for block in section.blocks %} and read block.settings. Merchants add, remove, and reorder blocks in the editor.
Use max_blocks to prevent performance issues. Name block types clearly—faq_item not block_1. See /dynamic-shopify-blocks-guide for slider, FAQ, and tab block patterns.
Presets and defaults
Presets make sections discoverable. A preset needs a name and can seed settings values and block rows. Without presets, merchants must configure sections from scratch every time.
Preset with seeded blocks
"presets": [{
"name": "FAQ — Shipping",
"blocks": [
{ "type": "faq_item", "settings": { "question": "How long is shipping?" } },
{ "type": "faq_item", "settings": { "question": "Do you ship internationally?" } }
]
}]Schema best practices
- Keep setting counts manageable—under 15 section settings when possible.
- Use stable ids; renaming breaks existing merchant data.
- Group related settings with header and paragraph types for editor UX.
- Match setting types to content—never use text for images.
- Validate JSON before deploy; trailing commas break schema parsing.
- Test on Dawn first; OS 2.0 conventions transfer to most themes.
From schema to production sections
Start from HTML in /converter, refine schema in /liquid-schema-generator, and cross-reference patterns in /shopify-cheat-sheet. For component-specific schema—heroes, banners, product grids—see /convert-hero-section-html-to-liquid and related component guides.
Schema is the contract merchants sign without reading
Section schema is JSON inside {% schema %} tags that tells Shopify which form fields to render in the theme editor. Merchants never see the raw JSON—they see labels, help text, and grouped controls. Your job as a developer is to design that form so a store owner with no code knowledge can manage content without breaking layout. Every id becomes a persistent key in template JSON across every store that installs your section. Renaming an id orphan existing values. Changing a text setting to image_picker does not migrate data. Treat setting ids like database column names: stable, descriptive, and prefixed when sections grow large—hero_heading not heading if you also have card_heading in blocks. The /converter generates initial ids from HTML content; refine them before production. Pair this guide with /liquid-schema-generator when you need to prototype schema without writing Liquid first.
Schema to storefront pipeline
{% schema %} JSON
│
├─► Theme editor UI (labels, types, defaults)
│ │
│ ▼
│ Merchant saves settings
│ │
▼ ▼
Liquid template reads section.settings
│
▼
HTML in storefront previewSchema never renders directly. It configures values that Liquid reads at render time and that JSON templates can seed with defaults.
Setting types beyond the obvious text and image
richtext is for body copy with bold, links, and lists—do not use it for headings that need a single plain string; text is easier for merchants to manage and style consistently. inline_richtext is newer and suits shorter formatted strings in compact UI slots. color and color_background pair for text on tinted bands—Dawn uses color_scheme settings that map to theme CSS variables, which is cleaner than raw hex pickers when you want merchants inside brand tokens. collection and product pickers return objects, not handles—you still access collection.products in Liquid after assignment. link_list powers navigation menus. font_picker exposes theme font library choices. video and video_url settings support hero media; know which your CSS expects. checkbox gates features: show_vendor, enable_autoplay. range controls numeric CSS—padding, columns, product counts—with min, max, step, and unit. select enumerates layout variants; map option values to BEM modifiers in Liquid rather than spelling out full class names merchants could mistype.
- header — non-input section break in the editor sidebar; use to group related settings
- paragraph — static helper copy; reduces Slack questions about what 'aspect ratio' means
- text_alignment — horizontal alignment without custom select options
- liquid — advanced escape hatch; avoid unless you document it for power users only
- number — integers where range sliders feel imprecise (grid column count with fixed steps)
visible_if and conditional settings (OS 2.0)
Crowded sidebars overwhelm merchants. visible_if hides settings until a parent toggle is enabled—show overlay opacity only when overlay is checked. The condition references another setting id with a simple equality expression. This pattern keeps FAQ sections readable: a 'Show button' checkbox reveals url and label fields. Document the dependency in help_text anyway; some merchants enable fields via JSON template defaults without touching the toggle first. Test that hidden settings retain values when toggled off—merchants expect hidden options to remember previous input. When exporting from /converter, add visible_if manually for advanced UX; the generator focuses on structural correctness first. Compare your final schema against Dawn's built-in sections for naming conventions: padding_top and padding_bottom mirror Shopify's own spacing vocabulary so agency developers instantly know what a setting does.
visible_if on a dependent url setting
{
"type": "checkbox",
"id": "show_cta",
"label": "Show call-to-action button",
"default": true
},
{
"type": "url",
"id": "cta_link",
"label": "Button link",
"visible_if": "{{ section.settings.show_cta }}"
}The dependent field appears only when show_cta is true, keeping the sidebar compact.
Blocks: types, limits, and editor ergonomics
Each block type in the blocks array is a template for repeatable rows. Merchants add rows from the editor; each row has its own block.settings scoped to that type. Use distinct type strings—testimonial not block—and human-readable name values that appear in the Add block menu. max_blocks caps count; without it a merchant can add fifty FAQ items and slow the editor. min_blocks is rarely used but can enforce at least one slide in a carousel section. blocks can define limit per type in some theme patterns, but usually one max_blocks covers the whole section. In Liquid, branch on block.type when multiple block types coexist in one section—slides versus static promo tiles in the same file. Each block wrapper needs block.shopify_attributes for editor sync. presets can seed multiple block types with settings objects so the first insert looks like the demo, not an empty shell.
Presets, defaults, and JSON template seeding
presets make sections discoverable in Add section. Each preset needs a name; optionally include settings and blocks arrays to pre-fill content. Multiple presets can target the same section file—'FAQ — Shipping' and 'FAQ — Returns' as two entry points with different seeded questions. default on individual settings applies when a section is first added without an explicit value in JSON. Template JSON in templates/index.json can set settings per section instance—useful for homepage hero copy that should differ from preset defaults on inner pages. blocks in presets use type and settings keys; block ids are generated by Shopify on insert, so do not hardcode block ids in presets unless you know the JSON template workflow. When clients ask why their new section is missing from Add section, ninety percent of the time presets array is empty or schema failed validation. Run theme check before you blame the platform.
Preset with settings and blocks
"presets": [
{
"name": "Feature grid — 3 columns",
"settings": {
"heading": "Why shop with us",
"columns": 3
},
"blocks": [
{ "type": "feature", "settings": { "title": "Free shipping" } },
{ "type": "feature", "settings": { "title": "Easy returns" } },
{ "type": "feature", "settings": { "title": "Expert support" } }
]
}
]Seeded blocks give merchants a realistic starting layout instead of an empty for loop.
Schema metadata: tag, class, enabled_on, disabled_on
tag wraps the section in a semantic HTML element—section, header, footer, aside. It affects accessibility landmarks and sometimes CSS hooks. class adds a static class on the wrapper alongside Shopify's section classes. enabled_on and disabled_on restrict which templates and page types may use the section—critical for app-like sections that only belong on product pages. A testimonial slider might use enabled_on templates including product and index. disabled_on groups can exclude header and footer section groups when a banner must not appear in global chrome. These keys reduce merchant error: they cannot drop a product-only reviews section onto the password page. Document restrictions in the section name suffix if needed—'Reviews (product only)' in the preset name saves a support thread.
Production schema review workflow
- 01
Validate JSON syntax
Trailing commas, unquoted keys, and duplicate ids break parsing. Paste into a JSON validator or run theme check. One duplicate id silently overwrites the earlier field in some editor versions.
- 02
Count settings and group with headers
More than fifteen ungrouped fields slows content entry. Insert header and paragraph types every five to seven controls. Match Dawn's spacing vocabulary for padding and color_scheme.
- 03
Test empty, partial, and max-filled states
Clear every optional field in the editor preview. Add blocks until max_blocks. Confirm Liquid if blank guards prevent empty headings and broken image tags.
- 04
Cross-check with /shopify-cheat-sheet filter patterns
image_picker settings should pipe through image_url widths your CSS expects. url settings should not be concatenated into attributes without escape filters when merchants paste query strings.
- 05
Ship handoff notes with stable ids
Export a table of setting ids, labels, and intended content owner (marketing vs merchandising). Clients rename labels in translations later; ids must never change.
Schema design is where developer empathy shows. Merchants do not think in Liquid objects—they think in headlines, photos, and buttons. Label fields the way a marketer speaks: 'Hero heading' not h1_text unless your audience is strictly technical. help_text should answer 'what happens if I leave this blank' in one sentence. When you inherit a legacy theme with cryptic ids, wrap new sections with clean schema rather than patching Vintage sections that mix global theme settings with section settings. Online Store 2.0 rewards sections that are self-contained. The /converter accelerates first drafts; your schema review is what makes the section maintainable for three years of merchant edits, not three days until launch.
Translating schema labels
Shopify themes support locale files in locales/en.default.schema.json for translation keys on schema labels and options. Schema uses t:namespaced.keys instead of literal English strings when you ship multilingual themes. Beginners can start with English literals; agencies planning international stores should namespace keys from day one—sections.your_section.settings.heading.label—so translators never edit Liquid. Option labels in select settings also accept translation keys. Preset names appear in Add section and benefit from translation too. This is easy to defer and painful to retrofit when fifty sections exist. Dawn's locale files are the reference implementation; copy the key structure, not the strings.
Schema review checklist before merge
Before any schema ships to a client theme, run this mental checklist: every setting has a unique id within the section; every image_picker has a blank guard in Liquid; every block type has a human name; max_blocks is set when repeatables exist; at least one preset exists if merchants should add the section; header settings group related controls; help_text explains blank behavior; select option values map to stable CSS modifiers, not display copy. Compare against /shopify-cheat-sheet image filter chains—width parameters should match your CSS layout grid. If the section uses color_scheme, confirm the theme defines matching schemes in settings_schema.json. Schema mistakes are expensive because merchants accumulate content against ids you later want to rename. Treat schema review as seriously as code review—Nishad blocks merges when presets are missing because he has seen launch-day Add section confusion too many times on wholesale and beauty stores.
Advanced schema patterns—visible_if, disabled_if, and dynamic options—reduce editor clutter on complex sections. visible_if hides controls until a toggle enables them, which keeps FAQ sections manageable when optional imagery is off by default. Use these sparingly; over-nesting visibility rules confuse merchants who cannot find a field their colleague saw yesterday. When in doubt, split into two simpler sections merchants can stack in JSON templates. The /liquid-schema-generator helps prototype these relationships visually before you embed JSON in section.liquid. Document any visible_if logic in handoff notes because it is invisible in the storefront HTML. Schema is not only JSON syntax; it is product design for non-technical users who still need power without breaking layout constraints you engineered in Liquid and CSS.
When clients ask for every pixel controllable in the editor, push back with grouped settings and sane defaults instead of fifty range sliders. Merchants rarely adjust padding by single pixels—they need headline, image, and CTA control. Excessive settings increase support load and slow the editor sidebar. We group advanced layout under a header labeled Advanced and hide it with visible_if until Show layout options is enabled. That pattern appears in our merchant-friendly schema articles and in converter exports after manual review. Schema that survives three years of merchant edits is boring on purpose: stable ids, clear labels, presets that match marketing language, and blocks for anything repeatable. Exciting schema demos poorly on the Monday after launch when the client needs to swap six FAQ answers before a campaign.
Export schema from /converter as a draft, then walk the theme editor sidebar field by field before merge. If a label confuses you, it will confuse the merchant. Rename, regroup, and delete spurious settings created from decorative HTML nodes. Valid schema JSON is necessary but not sufficient—editor UX is the acceptance test. Dhruv reviews labels; Nishad reviews max_blocks and preset defaults before any client handoff. Keep a schema changelog when you add settings so returning developers know which ids are safe to extend on every merge request review cycle.
When theme check flags your schema
Theme check errors map to fixable patterns. Duplicate setting ids mean two fields share the same key — rename before merge. Invalid JSON usually means a trailing comma or unquoted key in {% schema %}. Missing presets is a warning in some setups and a hard blocker for merchant Add section workflows. When check reports an unknown setting type, compare against Shopify's current schema reference — older themes sometimes copy deprecated types. Fix schema in the section file, redeploy to the duplicate theme, then re-run check before asking merchants to test. Pair each error with a blank-state preview: if check passes but the editor sidebar looks empty, visible_if may be hiding fields behind an unchecked toggle.
- Duplicate id — search schema JSON for repeated "id" values
- Invalid preset block type — preset blocks[].type must match a blocks[].type entry
- Schema parse failure — paste {% schema %} body into a JSON linter
- Setting referenced in visible_if missing — add the parent toggle first

