QUANTM7 Docs

Blocks

Add repeatable, sortable content items inside sections.

Blocks are repeatable, sortable content items inside a section. A slideshow section contains slide blocks. A testimonials section contains individual testimonial blocks. The visual editor lets merchants add, remove, and rearrange these blocks without writing any template code.

Defining blocks

Add a blocks array to your section schema. Each entry describes one type of block:

{% schema %}
{
  "name": "Slideshow",
  "blocks": [
    {
      "type": "slide",
      "name": "Slide",
      "settings": [
        { "type": "image_picker", "id": "image", "label": "Image" },
        { "type": "text", "id": "heading", "label": "Heading" },
        { "type": "text", "id": "subheading", "label": "Subheading" },
        { "type": "url", "id": "link", "label": "Link" }
      ]
    }
  ]
}
{% endschema %}

The type is a unique identifier you choose for this block variety. The name is the human-readable label that the merchant sees when adding blocks in the editor sidebar. The settings array follows the exact same structure as section-level settings.

Rendering blocks

Loop over section.blocks in your template. Each block has an id, type, and settings object:

<div class="slideshow">
  {% for block in section.blocks %}
    <div class="slide" data-block-id="{{ block.id }}">
      {% if block.settings.image %}
        {{ block.settings.image | image_tag }}
      {% endif %}
      <h2>{{ block.settings.heading }}</h2>
      <p>{{ block.settings.subheading }}</p>
    </div>
  {% endfor %}
</div>

Always include the data-block-id attribute on each block's outermost element. The visual editor relies on this attribute to highlight the corresponding block when the merchant selects it in the sidebar.

Multiple block types

A section can have more than one type of block. Use block.type to tell them apart:

{% schema %}
{
  "name": "Content Grid",
  "blocks": [
    {
      "type": "text_block",
      "name": "Text",
      "settings": [
        { "type": "richtext", "id": "content", "label": "Content" }
      ]
    },
    {
      "type": "image_block",
      "name": "Image",
      "settings": [
        { "type": "image_picker", "id": "image", "label": "Image" },
        { "type": "text", "id": "caption", "label": "Caption" }
      ]
    },
    {
      "type": "video_block",
      "name": "Video",
      "settings": [
        { "type": "video_url", "id": "url", "label": "Video URL" }
      ]
    }
  ]
}
{% endschema %}

In the template, check the type for each block:

{% for block in section.blocks %}
  <div class="grid-item" data-block-id="{{ block.id }}">
    {% case block.type %}
      {% when 'text_block' %}
        <div class="text-content">{{ block.settings.content }}</div>
      {% when 'image_block' %}
        {{ block.settings.image | image_tag }}
        {% if block.settings.caption != blank %}
          <p class="caption">{{ block.settings.caption }}</p>
        {% endif %}
      {% when 'video_block' %}
        <iframe src="{{ block.settings.url }}" allowfullscreen></iframe>
    {% endcase %}
  </div>
{% endfor %}

Limiting blocks

Set max_blocks at the top level of your schema to cap how many blocks the merchant can add:

{% schema %}
{
  "name": "Testimonials",
  "max_blocks": 6,
  "blocks": [
    {
      "type": "testimonial",
      "name": "Testimonial",
      "settings": [
        { "type": "text", "id": "quote", "label": "Quote" },
        { "type": "text", "id": "author", "label": "Author" }
      ]
    }
  ]
}
{% endschema %}

Empty state

Always handle the case where no blocks have been added yet:

{% if section.blocks.size == 0 %}
  <p>No slides added yet. Open the editor to add one.</p>
{% else %}
  {% for block in section.blocks %}
    {% render 'slide' with block %}
  {% endfor %}
{% endif %}

Block properties

Each block in the loop gives you these values:

PropertyDescription
block.idA unique ID for DOM targeting
block.typeThe type string from the schema
block.settingsThe values the merchant set for this block

Tips

  • Keep block schemas small. A block with more than five or six settings becomes hard for merchants to manage.
  • Give blocks clear names. The merchant sees the name in the editor sidebar when adding new blocks.
  • Use case/when for multiple block types. It is cleaner than a chain of if/elsif checks.
  • Include default values for settings that should never be empty. This makes the section look good before the merchant makes any changes.

On this page