Templates and sections

Templates

Each kind of page has a template. A JSON template lists the sections the page is made of, in order. The firm can add, remove, reorder and configure them in the theme editor.

Template Page Page objects
index The homepage's starting layout page
page A site page's starting layout page
page.{name} Alternative page layouts, e.g. page.contact, page.about page
practice_areas The list of practice areas, at /practice-areas
practice_area One practice area's page, at /practice-areas/{handle} practice_area
blog The blog, at /blog, and its category and tag archives at /blog/category/{handle} and /blog/tag/{handle} blog
article One article's page, at /blog/{handle} article
intake The firm's intake form, at /intake, while the firm has it on
404 Page not found
customers/login Sign in
customers/forgot_password Forgot password
customers/reset_password Reset password reset_password
customers/verify_email Verify email
customers/activate_account Accepting a client portal invitation: the client chooses a password invitation

Site pages

The firm creates its own pages under Pages (any number, each at its own address, /{slug}) and marks one as the homepage. Pages don't nest: dropdowns and grouping come from the menus the firm builds in Navigation. Each page picks one of your page templates: page, or any page.{name} your theme ships (the editor lists page.about as "About"). A missing page.{name} falls back to page.

Firms manage pages in the theme editor: they pick a page, switch its layout between your page templates, and change its sections. Once they change a page's sections, that page keeps its own layout (stored as pages/{id} on the theme, never in your package); switching layout again replaces it with the chosen template's sections.

The page's text is stored on the page, not in a layout, so it survives layout and theme changes. Show it with {{ page.content }} in a section whose schema has "page_content": true (Counsel's is main-page): selecting that section in the editor shows the text editor for the page. Put such a section in every page template.

JSON
{% schema %}
{ "name": "Page content", "page_content": true, "settings": [] }
{% endschema %}
JSON
{
    "layout": "theme",
    "sections": {
        "hero": {
            "type": "hero",
            "settings": { "heading": "Clear advice when it matters most" },
            "blocks": {
                "cta": { "type": "button", "settings": { "label": "Book a consultation" } }
            },
            "block_order": ["cta"]
        },
        "faq": { "type": "faq", "settings": {}, "disabled": false }
    },
    "order": ["hero", "faq"]
}
  • layout picks layout/<name>.liquid (default theme), or false for no layout.
  • type is a file in sections/. Section and block ids are yours: letters, digits, - and _, up to 64 characters.
  • disabled: true keeps a section configured but hidden.
  • A template can also be a .liquid file, which then isn't editable in the theme editor.

Practice areas

Firms publish their practice areas under Firm settings → Practice areas, and the platform serves /practice-areas with your practice_areas template and each area's page with practice_area. If you don't ship them, Counsel's are used. A site page the firm publishes at the same path takes its place. The practice_areas and team objects are available on every page, so any section can list them.

Blog

Firms on a plan with the blog write articles under Website → Blog. The platform serves /blog and the category and tag archives with your blog template (check blog.category and blog.tag to title an archive) and each article with article. Archives show 12 articles a page: link blog.pagination.previous_url and next_url. If you don't ship the templates, Counsel's are used. A site page the firm publishes at /blog takes the blog's first page's place; articles and archives always come from the blog. The blog object is available on every page, so a home page section can show blog.latest_articles or blog.featured_articles.

The client portal's account pages are rendered by the platform. They're shown inside layout/member.liquid (or theme.liquid if you don't ship one), with your header and footer around them.

There is no public sign-up: clients join by invitation, on your customers/activate_account page. Any customers/* template you don't ship falls back to Counsel's.

Give a signed-in customer a way to sign out from your header (see the customer example). Don't hide it behind a setting: the bundled themes always show it, and their "Show sign in link" setting only controls the link guests see.

Section groups

sections/header-group.json and sections/footer-group.json are the header and footer, shared by every page. Render them in your layout:

Liquid
{% sections 'header-group' %}
<main id="main-content">{{ content_for_layout }}</main>
{% sections 'footer-group' %}

They use the same format as templates, plus "type": "header" or "type": "footer" and a name.

Sections

A section is a Liquid file in sections/ with a {% schema %}:

Liquid
<div class="page-width section-y">
  <h2 class="h2">{{ section.settings.heading | escape }}</h2>
  <div class="grid gap-6 md:grid-cols-3">
    {%- for block in section.blocks -%}
      <div {{ block.theme_attributes }}>
        <h3>{{ block.settings.title | escape }}</h3>
        <div class="rte">{{ block.settings.text }}</div>
      </div>
    {%- endfor -%}
  </div>
</div>

{% schema %}
{
  "name": "Features",
  "tag": "section",
  "class": "section",
  "settings": [
    { "type": "text", "id": "heading", "label": "Heading", "default": "Why learn with us" }
  ],
  "blocks": [
    {
      "type": "feature",
      "name": "Feature",
      "settings": [
        { "type": "text", "id": "title", "label": "Title", "default": "Live classes" },
        { "type": "richtext", "id": "text", "label": "Text" }
      ]
    }
  ],
  "max_blocks": 6,
  "presets": [
    { "name": "Features", "blocks": [{ "type": "feature" }, { "type": "feature" }, { "type": "feature" }] }
  ],
  "enabled_on": { "templates": ["index", "page.contact"] }
}
{% endschema %}
Schema key Meaning
name Shown in the theme editor.
tag The wrapper element: section, div (default), header, footer, aside, nav, main or article.
class Classes on the wrapper. The wrapper also gets id="theme-section-…", data-section-type and, when the firm animates the section, data-animate or data-animate-stagger.
settings The section's settings (see Settings).
blocks Block types: type, name, settings, and optionally limit (how many of that type).
max_blocks How many blocks in total (up to 50).
presets Makes the section available under Add section, with starting settings and blocks. Without a preset, a section can only be placed by a template file.
enabled_on / disabled_on Limit where the section can be added: { "templates": [...], "groups": ["header", "footer"] }.
animations false to leave out the platform's animation settings for this section and its blocks (see Platform settings). A block's schema can also say "animations": false. Defaults to true.

Output {{ block.theme_attributes }} on each block's outermost element. The theme editor uses it to highlight and select blocks, and it carries the block's animation (data-animate="…"), so a block without it can't animate.

For repeated items that aren't blocks, such as the cards of a list, put data-animate-item on each item's outer element. When the firm turns on Stagger blocks, those items are revealed one after another too. See Motion and animations.

{% section 'name' %} renders a section with its schema defaults, outside any template. It isn't editable.

Snippets

{% render 'card', title: block.settings.title, compact: true %} renders snippets/card.liquid. A snippet only sees the variables you pass it, plus the global objects.

Still need help?

Send a request to the Mattersimple team and we'll reply by email.

Sign in to contact support