{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-docs/themes/sidebars.yaml"},"props":{"codeGuideFiles":[],"dynamicMarkdocComponents":[],"metadata":{"type":"markdown"},"seo":{"title":"Blocks and Components","description":"Fluid is the open e-commerce platform built for direct-sales."},"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"blocks-and-components"},"children":["Blocks and Components"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When building a Fluid theme, you'll work with two types of reusable templates: ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["blocks"]}," and ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["components"]},". This guide explains what each is, when to use them, and how they differ."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"table-of-contents"},"children":["Table of Contents"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#components"},"children":["Components"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#blocks"},"children":["Blocks"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#section-blocks-inline"},"children":["Section blocks (inline)"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#theme-blocks-standalone"},"children":["Theme blocks (standalone)"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#private-blocks"},"children":["Private blocks"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#the-theme-wildcard"},"children":["The @theme wildcard"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#named-block-references"},"children":["Named block references"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#rendering-blocks-with-content_for"},"children":["Rendering blocks with content_for"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#nesting-blocks"},"children":["Nesting blocks"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#presets"},"children":["Presets"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#static-blocks"},"children":["Static blocks"]}]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#blocks-vs-components"},"children":["Blocks vs Components"]}]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"components"},"children":["Components"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Components are reusable Liquid partials. They don't have a schema or settings — instead, they accept props when you render them. Think of them like functions you call from your sections or other templates."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"folder-structure"},"children":["Folder structure"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"theme/\n  components/\n    button/\n      index.liquid\n    product_card/\n      index.liquid\n"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"example-button-component"},"children":["Example: Button component"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"text","header":{"controls":{"copy":{}}},"source":"{'%' comment '%'}\n    Props:\n    - tag: string (a or button, default: button)\n    - type: string (button, submit, reset; for button tag)\n    - href: string (for link buttons)\n    - variant: string (primary, secondary, outline, link, white-primary, white-outline)\n    - size: string (sm, md, lg)\n    - text: string (button label)\n    - icon: string (icon name or svg)\n    - icon_position: string (left, right, default: left)\n    - disabled: boolean\n    - attr: string (additional attributes)\n    - class: string\n{'%' endcomment '%'}\n\n{'%' liquid\n  assign tag = tag | default: 'button'\n  if href != blank\n    assign tag = 'a'\n  endif\n  assign variant = variant | default: 'primary'\n  assign size = size | default: 'md'\n  assign icon_position = icon_position | default: 'left'\n  assign type = type | default: 'button'\n\n  case variant\n    when 'primary'\n      assign variant_class = 'btn-bg-primary'\n    when 'secondary'\n      assign variant_class = 'btn-bg-secondary'\n    when 'outline'\n      assign variant_class = 'btn-outline'\n    else\n      assign variant_class = variant\n  endcase\n\n  assign size_class = 'button--medium'\n  case size\n    when 'sm'\n      assign size_class = 'button--small'\n    when 'lg'\n      assign size_class = 'button--large'\n  endcase\n'%'}\n\n<{{ tag }}\n  {'%' if tag == 'a' '%'}href=\"{{ href }}\"{'%' else '%'}type=\"{{ type }}\"{'%' endif '%'}\n  class=\"button {{ variant_class }} {{ size_class }} {{ class }}\"\n  {'%' if disabled '%'}disabled{'%' endif '%'}\n  {'%' if disabled and tag == 'a' '%'}style=\"pointer-events: none; opacity: 0.5;\"{'%' endif '%'}\n  {{ attr }}\n>\n  {'%' if icon and icon_position == 'left' '%'}\n    <span class=\"fluid-btn__icon leading-none flex items-center justify-center\">{{ icon }}</span>\n  {'%' endif '%'}\n  <span class=\"fluid-btn__text\">{{ text }}</span>\n  {'%' if icon and icon_position == 'right' '%'}\n    <span class=\"fluid-btn__icon leading-none flex items-center justify-center\">{{ icon }}</span>\n  {'%' endif '%'}\n</{{ tag }}>\n","lang":"text"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"how-to-use-a-component"},"children":["How to use a component"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Call a component from any section, block, or other component using ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{'%' render '%'}"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"text","header":{"controls":{"copy":{}}},"source":"{'%' render 'button',\n  text: 'Buy Now',\n  href: product.url,\n  variant: 'primary',\n  size: 'md'\n'%'}\n","lang":"text"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"when-to-create-a-component"},"children":["When to create a component"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["You have a piece of UI that shows up in multiple places (buttons, cards, pagination, icons)"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The template doesn't need configurable settings in the visual builder — it just takes props and outputs HTML"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["You want to keep your section templates clean by extracting repeated markup"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"tips"},"children":["Tips"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Document your props in a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{'%' comment '%'}"]}," block at the top of the file"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["| default:"]}," filters to set fallback values for optional props"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Components can render other components — nesting is fine"]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"blocks"},"children":["Blocks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Blocks are dynamic content elements that let users add, remove, and reorder content within a section through the visual builder. There are two kinds of blocks:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Section blocks"]}," — defined inline in a section's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{'%' schema '%'}"]}," tag"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Theme blocks"]}," — standalone ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".liquid"]}," files in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["blocks/"]}," directory, reusable across sections"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"section-blocks-inline"},"children":["Section blocks (inline)"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The traditional approach. Sections define their available block types directly in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"blocks\""]}," array of their schema. The section template renders blocks inline using ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{'%' for block in section.blocks '%'}"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-a-section-with-inline-blocks"},"children":["Example: A section with inline blocks"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"text","header":{"controls":{"copy":{}}},"source":"{'%' for block in section.blocks '%'}\n  {'%' case block.type '%'}\n    {'%' when 'heading' '%'}\n      <h2 class=\"rte\" {{ block.fluid_attributes }}>{{ block.settings.text }}</h2>\n    {'%' when 'text' '%'}\n      <p class=\"rte\" {{ block.fluid_attributes }}>{{ block.settings.content }}</p>\n  {'%' endcase '%'}\n{'%' endfor '%'}\n\n{'%' schema '%'}\n{\n  \"name\": \"Promo Banner\",\n  \"blocks\": [\n    {\n      \"type\": \"heading\",\n      \"name\": \"Heading\",\n      \"limit\": 1,\n      \"settings\": [\n        { \"type\": \"richtext\", \"id\": \"text\", \"label\": \"Text\", \"default\": \"<p>Welcome</p>\" }\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"name\": \"Text\",\n      \"settings\": [\n        { \"type\": \"richtext\", \"id\": \"content\", \"label\": \"Content\" }\n      ]\n    }\n  ],\n  \"presets\": [\n    {\n      \"name\": \"Promo Banner\",\n      \"blocks\": [\n        { \"type\": \"heading\" },\n        { \"type\": \"text\" }\n      ]\n    }\n  ]\n}\n{'%' endschema '%'}\n","lang":"text"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Inline blocks work well when block types are specific to a single section. But if you find yourself repeating the same block definitions across many sections, theme blocks are a better fit."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"theme-blocks-standalone"},"children":["Theme blocks (standalone)"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Theme blocks are standalone ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".liquid"]}," files in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["blocks/"]}," directory. Each file contains its own markup, schema, and settings. Any section can use them without redefining the block's settings."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"folder-structure-1"},"children":["Folder structure"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"theme/\n  blocks/\n    heading/\n      index.liquid\n    description/\n      index.liquid\n    button/\n      index.liquid\n    group/\n      index.liquid\n    _slide/\n      index.liquid       <-- private block (underscore prefix)\n"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-heading-block"},"children":["Example: Heading block"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"text","header":{"controls":{"copy":{}}},"source":"<div class=\"rte\" {{ block.fluid_attributes }}>{{ block.settings.text }}</div>\n\n{'%' schema '%'}\n{\n  \"name\": \"Heading\",\n  \"settings\": [\n    {\n      \"type\": \"richtext\",\n      \"id\": \"text\",\n      \"label\": \"Text\",\n      \"default\": \"<p>Medium length heading goes here</p>\"\n    }\n  ],\n  \"presets\": [\n    { \"name\": \"Heading\" }\n  ]\n}\n{'%' endschema '%'}\n","lang":"text"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-button-block"},"children":["Example: Button block"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"text","header":{"controls":{"copy":{}}},"source":"{'%' assign cr = block.settings.border_radius '%'}\n{'%' assign _btn_attr = block.fluid_attributes '%'}\n{'%' if cr '%'}\n  {'%' capture cr_tl '%'}{{ cr.tl }}{'%' endcapture '%'}\n  {'%' capture cr_tr '%'}{{ cr.tr }}{'%' endcapture '%'}\n  {'%' capture cr_br '%'}{{ cr.br }}{'%' endcapture '%'}\n  {'%' capture cr_bl '%'}{{ cr.bl }}{'%' endcapture '%'}\n  {'%' capture _br_val '%'}{{ cr_tl }}px {{ cr_tr }}px {{ cr_br }}px {{ cr_bl }}px{'%' endcapture '%'}\n  {'%' assign _btn_attr = 'style=\"border-radius: ' | append: _br_val | append: ';\" ' | append: _btn_attr '%'}\n{'%' endif '%'}\n{'%' if block.settings.text != blank '%'}\n  {'%' render 'button',\n    href: block.settings.link | default: '#',\n    text: block.settings.text,\n    variant: block.settings.style | default: 'btn-bg-primary',\n    attr: _btn_attr\n  '%'}\n{'%' endif '%'}\n\n{'%' schema '%'}\n{\n  \"name\": \"Button\",\n  \"settings\": [\n    { \"type\": \"text\", \"id\": \"text\", \"label\": \"Text\", \"default\": \"Button\" },\n    { \"type\": \"url\", \"id\": \"link\", \"label\": \"Link\" },\n    {\n      \"type\": \"select\",\n      \"id\": \"style\",\n      \"label\": \"Style\",\n      \"options\": [\n        { \"value\": \"btn-bg-white\", \"label\": \"White\" },\n        { \"value\": \"btn-bg-primary\", \"label\": \"Primary\" },\n        { \"value\": \"btn-border-primary\", \"label\": \"Primary Border\" }\n      ],\n      \"default\": \"btn-bg-primary\"\n    },\n    { \"type\": \"corner_radius\", \"id\": \"border_radius\", \"label\": \"Border Radius\" }\n  ],\n  \"presets\": [\n    { \"name\": \"Button\" },\n    { \"name\": \"White Button\", \"settings\": { \"style\": \"btn-bg-white\" } }\n  ]\n}\n{'%' endschema '%'}\n","lang":"text"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Key differences from section blocks:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Theme blocks have their own ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".liquid"]}," file with markup — sections don't need to render them manually"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Settings are defined once and reused everywhere"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Multiple presets let a single block file appear as different variants in the block picker"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Theme blocks can contain nested child blocks (see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"#nesting-blocks"},"children":["Nesting blocks"]},")"]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"private-blocks"},"children":["Private blocks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Blocks with names starting with an underscore (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["_"]},") are ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["private blocks"]},". They are excluded from the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@theme"]}," wildcard and only available when a section explicitly references them by name."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use private blocks for section-specific block types that shouldn't appear in the block picker of other sections."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"theme/\n  blocks/\n    heading/\n      index.liquid          <-- public, available via @theme\n    _slide/\n      index.liquid          <-- private, must be explicitly referenced\n    _product_card/\n      index.liquid          <-- private\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A slideshow section can reference the private ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["_slide"]}," block explicitly:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"name\": \"Slideshow\",\n  \"blocks\": [{ \"type\": \"_slide\" }]\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["But a generic section using ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@theme"]}," will NOT see ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["_slide"]}," in its block picker — only public blocks like ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["heading"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["description"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["button"]},", etc."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"the-theme-wildcard"},"children":["The @theme wildcard"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Sections can accept ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["all public theme blocks"]}," by declaring ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{\"type\": \"@theme\"}"]}," in their blocks array. This is the most flexible pattern — users can add any combination of theme blocks to the section."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"text","header":{"controls":{"copy":{}}},"source":"<section class=\"custom-section section-{{ section.id }}\">\n  <div class=\"container\">\n    {'%' content_for 'blocks' '%'}\n  </div>\n</section>\n\n{'%' schema '%'}\n{\n  \"name\": \"Custom Section\",\n  \"blocks\": [{ \"type\": \"@theme\" }],\n  \"settings\": [],\n  \"presets\": [\n    {\n      \"name\": \"Custom Section\",\n      \"blocks\": [\n        { \"type\": \"heading\", \"settings\": { \"text\": \"<h2>Hello World</h2>\" } },\n        { \"type\": \"description\", \"settings\": { \"text\": \"<p>Add any blocks you want.</p>\" } }\n      ]\n    }\n  ]\n}\n{'%' endschema '%'}\n","lang":"text"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@theme"]}," expands to all public (non-underscore) blocks in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["blocks/"]}," directory. The visual builder shows them in the \"Add block\" picker."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can combine ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@theme"]}," with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@app"]}," to also accept extension blocks:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"\"blocks\": [{ \"type\": \"@theme\" }, { \"type\": \"@app\" }]\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can mix all three approaches in the same section — inline definitions, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@theme"]},", and named references:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"\"blocks\": [\n  { \"type\": \"@theme\" },\n  { \"type\": \"_slide\" },\n  { \"type\": \"custom_inline\", \"name\": \"Custom Inline\", \"settings\": [\n    { \"type\": \"text\", \"id\": \"label\", \"label\": \"Label\" }\n  ]}\n]\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In this example:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@theme"]}," makes all public standalone blocks available"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["_slide"]}," explicitly adds the private slide block (excluded from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@theme"]},")"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["custom_inline"]}," defines a section-specific block with inline settings"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When resolving a block, the engine checks inline definitions first, then falls back to standalone block templates via ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@theme"]}," or named references."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"named-block-references"},"children":["Named block references"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Instead of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@theme"]}," (which accepts all blocks), you can reference specific standalone blocks by name:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"name\": \"Slideshow\",\n  \"blocks\": [{ \"type\": \"_slide\" }]\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This restricts the section to only accept the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["_slide"]}," block. The block's settings come from the standalone template file — you don't need to redefine them in the section schema."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can also reference multiple specific blocks:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"\"blocks\": [\n  { \"type\": \"heading\" },\n  { \"type\": \"description\" },\n  { \"type\": \"button\" }\n]\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When a block entry has no ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["settings"]}," key, the engine resolves the settings from the matching standalone block template in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["blocks/"]}," directory."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"rendering-blocks-with-content_for"},"children":["Rendering blocks with content_for"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When using standalone theme blocks, use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{'%' content_for 'blocks' '%'}"]}," to render them. Each block renders using its own ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".liquid"]}," template from the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["blocks/"]}," directory."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"text","header":{"controls":{"copy":{}}},"source":"<div class=\"my-section\">\n  {'%' content_for 'blocks' '%'}\n</div>\n","lang":"text"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This is different from the inline approach where you manually iterate with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{'%' for block in section.blocks '%'}"]},". With ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["content_for"]},", each block's own template handles the rendering — the section doesn't need to know how each block looks."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"rendering-a-single-static-block"},"children":["Rendering a single static block"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can render a specific block by type and ID:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"text","header":{"controls":{"copy":{}}},"source":"{'%' content_for 'block', type: 'heading', id: 'section-header' '%'}\n","lang":"text"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This is useful for pinned/static blocks that always appear in a fixed position (see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"#static-blocks"},"children":["Static blocks"]},")."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"nesting-blocks"},"children":["Nesting blocks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Theme blocks can contain child blocks. This is useful for container blocks like groups, columns, or cards."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-group-block"},"children":["Example: Group block"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A group block that accepts any theme block as children:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"text","header":{"controls":{"copy":{}}},"source":"<div class=\"block-group\" {{ block.fluid_attributes }}\n  style=\"background-color: {{ block.settings.background_color }};\">\n  {'%' content_for 'blocks' '%'}\n</div>\n\n{'%' schema '%'}\n{\n  \"name\": \"Group\",\n  \"blocks\": [{ \"type\": \"@theme\" }],\n  \"settings\": [\n    {\n      \"type\": \"color_background\",\n      \"id\": \"background_color\",\n      \"label\": \"Background Color\"\n    }\n  ],\n  \"presets\": [\n    { \"name\": \"Group\" },\n    {\n      \"name\": \"Card\",\n      \"settings\": { \"background_color\": \"#f8f8f8\" },\n      \"blocks\": [\n        { \"type\": \"heading\", \"settings\": { \"text\": \"<h3>Card Title</h3>\" } },\n        { \"type\": \"description\", \"settings\": { \"text\": \"<p>Card description.</p>\" } }\n      ]\n    }\n  ]\n}\n{'%' endschema '%'}\n","lang":"text"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{'%' content_for 'blocks' '%'}"]}," inside a block template renders that block's children, not the section's blocks."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Nesting depth limit:"]}," Blocks can be nested up to 2 levels deep."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"presets"},"children":["Presets"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Presets define the default blocks and settings when a section is first added to a page. They serve two purposes:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Provide starter content"]}," so the section isn't blank when added"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Offer variants"]}," — multiple presets let the same section appear as different options in the section picker"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"basic-preset"},"children":["Basic preset"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"\"presets\": [\n  {\n    \"name\": \"Hero Banner\",\n    \"blocks\": [\n      { \"type\": \"heading\", \"settings\": { \"text\": \"<h1>Welcome</h1>\" } },\n      { \"type\": \"button\", \"settings\": { \"text\": \"Shop Now\", \"style\": \"btn-bg-white\" } }\n    ]\n  }\n]\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"preset-with-nested-blocks"},"children":["Preset with nested blocks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Presets can include nested blocks for container block types:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"\"presets\": [\n  {\n    \"name\": \"Two Column Cards\",\n    \"blocks\": [\n      {\n        \"type\": \"group\",\n        \"settings\": { \"background_color\": \"#f0f4f8\" },\n        \"blocks\": [\n          { \"type\": \"heading\", \"settings\": { \"text\": \"<h3>Column One</h3>\" } },\n          { \"type\": \"description\", \"settings\": { \"text\": \"<p>First column content.</p>\" } }\n        ]\n      },\n      {\n        \"type\": \"group\",\n        \"settings\": { \"background_color\": \"#f8f0f4\" },\n        \"blocks\": [\n          { \"type\": \"heading\", \"settings\": { \"text\": \"<h3>Column Two</h3>\" } },\n          { \"type\": \"description\", \"settings\": { \"text\": \"<p>Second column content.</p>\" } }\n        ]\n      }\n    ]\n  }\n]\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"block-presets-in-standalone-blocks"},"children":["Block presets (in standalone blocks)"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Standalone block templates can also have presets. These control how the block appears in the block picker and provide pre-configured variants:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"name\": \"Button\",\n  \"settings\": [...],\n  \"presets\": [\n    { \"name\": \"Button\" },\n    { \"name\": \"White Button\", \"settings\": { \"style\": \"btn-bg-white\" } },\n    { \"name\": \"Outline Button\", \"settings\": { \"style\": \"btn-border-primary\" } }\n  ]\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A block without presets will not appear in the block picker."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"static-blocks"},"children":["Static blocks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Static blocks are pinned to a specific location in the section and cannot be removed or reordered by users. They are excluded from the normal block flow rendered by ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{'%' content_for 'blocks' '%'}"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Mark a block as static in the preset:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"\"presets\": [\n  {\n    \"name\": \"Content Columns\",\n    \"blocks\": [\n      {\n        \"type\": \"heading\",\n        \"id\": \"section-header\",\n        \"static\": true,\n        \"settings\": { \"text\": \"<h2>Section Title</h2>\" }\n      },\n      { \"type\": \"group\", \"blocks\": [...] },\n      { \"type\": \"group\", \"blocks\": [...] }\n    ]\n  }\n]\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Render the static block explicitly:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"text","header":{"controls":{"copy":{}}},"source":"{'%' content_for 'block', type: 'heading', id: 'section-header' '%'}\n\n<div class=\"grid\">\n  {'%' content_for 'blocks' '%'}\n</div>\n","lang":"text"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The static heading always appears above the grid. The dynamic blocks (groups) render inside the grid. Users can add, remove, and reorder the dynamic blocks but not the static heading."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"block-schema-properties"},"children":["Block schema properties"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Property"},"children":["Property"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["type"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Unique identifier for the block type. Use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@theme"]}," for all public blocks, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@app"]}," for extension blocks."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["name"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Display name shown in the visual builder. Not needed for ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@theme"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@app"]},", or named references."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["limit"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Maximum number of this block type allowed (optional)."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["settings"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Array of configurable settings. Not needed for named references — resolved from the standalone block template."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["blocks"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Child block definitions for nested blocks (standalone blocks only)."]}]}]}]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"blocks-vs-components"},"children":["Blocks vs Components"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":""},"children":[]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Components"},"children":["Components"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Section Blocks"},"children":["Section Blocks"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Theme Blocks"},"children":["Theme Blocks"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Has schema?"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["No"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes (inline in section)"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes (own file)"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Configurable in visual builder?"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["No"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Can be added/removed/reordered?"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["No"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["How to render"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{'%' render 'name' '%'}"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{'%' for block in section.blocks '%'}"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{'%' content_for 'blocks' '%'}"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Reusable across sections?"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["No (per-section)"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes (via ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@theme"]}," or named ref)"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Supports nesting?"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Via render calls"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["No"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes (up to 2 levels)"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Folder"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["components/"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Inline in section schema"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["blocks/"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Use case"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Simple partials (button, card)"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Section-specific content units"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Reusable, configurable content units"]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"which-should-i-use"},"children":["Which should I use?"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Use a component"]}," when you need a reusable piece of markup that just takes props — no visual builder settings, no user controls."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Use section blocks (inline)"]}," when block types are unique to a single section and you want full control over how they render within that section's template."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Use theme blocks (standalone)"]}," when the same block types appear across many sections. Define once in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["blocks/"]},", reference everywhere with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["@theme"]}," or by name. Use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{'%' content_for 'blocks' '%'}"]}," to let each block render itself."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Components and blocks work together — a standalone button block might call the button component internally to handle the actual HTML rendering."]}]}]},"headings":[{"value":"Blocks and Components","id":"blocks-and-components","depth":1},{"value":"Table of Contents","id":"table-of-contents","depth":2},{"value":"Components","id":"components","depth":2},{"value":"Folder structure","id":"folder-structure","depth":3},{"value":"Example: Button component","id":"example-button-component","depth":3},{"value":"How to use a component","id":"how-to-use-a-component","depth":3},{"value":"When to create a component","id":"when-to-create-a-component","depth":3},{"value":"Tips","id":"tips","depth":3},{"value":"Blocks","id":"blocks","depth":2},{"value":"Section blocks (inline)","id":"section-blocks-inline","depth":3},{"value":"Example: A section with inline blocks","id":"example-a-section-with-inline-blocks","depth":4},{"value":"Theme blocks (standalone)","id":"theme-blocks-standalone","depth":3},{"value":"Folder structure","id":"folder-structure-1","depth":4},{"value":"Example: Heading block","id":"example-heading-block","depth":4},{"value":"Example: Button block","id":"example-button-block","depth":4},{"value":"Private blocks","id":"private-blocks","depth":3},{"value":"The @theme wildcard","id":"the-theme-wildcard","depth":3},{"value":"Named block references","id":"named-block-references","depth":3},{"value":"Rendering blocks with content_for","id":"rendering-blocks-with-content_for","depth":3},{"value":"Rendering a single static block","id":"rendering-a-single-static-block","depth":4},{"value":"Nesting blocks","id":"nesting-blocks","depth":3},{"value":"Example: Group block","id":"example-group-block","depth":4},{"value":"Presets","id":"presets","depth":3},{"value":"Basic preset","id":"basic-preset","depth":4},{"value":"Preset with nested blocks","id":"preset-with-nested-blocks","depth":4},{"value":"Block presets (in standalone blocks)","id":"block-presets-in-standalone-blocks","depth":4},{"value":"Static blocks","id":"static-blocks","depth":3},{"value":"Block schema properties","id":"block-schema-properties","depth":3},{"value":"Blocks vs Components","id":"blocks-vs-components","depth":2},{"value":"Which should I use?","id":"which-should-i-use","depth":3}],"frontmatter":{"seo":{"title":"Blocks and Components"}},"lastModified":"2026-04-02T16:19:48.000Z"},"slug":"/docs/themes/template-types","userData":{"isAuthenticated":false,"teams":["anonymous"]}}