Theme structure

A theme is a folder (or a zip of one) with this layout. Only the files marked required must exist; any template, section or snippet you leave out falls back to the Counsel theme's. Templates and sections explains what each template renders.

layout/
  theme.liquid          required: the page frame
  member.liquid         optional: the frame around the client portal's account pages
templates/
  index.json            required (or index.liquid): the homepage's starting layout
  page.json             a site page's starting layout
  page.contact.json     optional alternative page layouts (page.{name}.json)
  practice_areas.json   the practice areas list
  practice_area.json    one practice group's page
  blog.json             the blog and its category and tag archives
  article.json          one article
  404.json
  customers/
    login.json
    forgot_password.json
    reset_password.json
    verify_email.json
    activate_account.json
sections/
  *.liquid              sections, each with a {% schema %}
  header-group.json  
  footer-group.json
snippets/
  *.liquid              partials for {% render %}
assets/
  *.css 
  *.js 
  *.svg 
  *.png 
  *.jpg 
  *.gif 
  *.webp 
  *.avif 
  *.ico 
  *.woff 
  *.woff2 
  *.ttf 
  *.otf
config/
  settings_schema.json  required: the theme-wide settings
  settings_data.json    their values
locales/
  en.default.json       text for the `t` filter (other languages: fr.json, pt-BR.json…)
screenshots/
  desktop.png           required: at least 1600×1000 (.png, .jpg or .webp)
  mobile.png            optional
theme.json
README.md  
CHANGELOG.md  
LICENSE   (optional, at the root)

File rules

  • Names use lowercase letters, digits, - and _ (assets may also use capitals, . and @).
  • assets/ has no subfolders.
  • Any other file makes the upload fail, with one exception: development files are skipped, so you can zip your project folder as it is. Skipped: anything in src/, dist/, docs/ or node_modules/, dotfiles and dot-folders (.gitignore, .git/, .vscode/), package.json, lock files, tailwind.config.* and *.map files.
  • layout/theme.liquid must output {{ content_for_header }} inside <head> and {{ content_for_layout }} inside <body>.

theme.json

JSON
{
    "name": "Aurora",
    "version": "1.2.0",
    "author": "Your studio",
    "description": "A calm, editorial theme for language firms.",
    "documentation_url": "https://example.com/aurora/docs",
    "screenshots": {
        "desktop": "screenshots/desktop.png",
        "mobile": "screenshots/mobile.png"
    }
}

name and version show in the theme library. documentation_url (https only) adds a Theme documentation link there.

Limits

Limit Value
Zip size 20 MB
Unpacked size 40 MB
Theme files (development files not counted) 500
One file 5 MB
Screenshot 1600×1000 minimum, 5 MB maximum
Sections per template, blocks per section 50
One JSON document 512 KB
Rendered page 2 MB of HTML

What happens on upload

  1. The zip is read in memory. Unsafe paths, symlinks and zip bombs are refused.
  2. The package is validated: required files, allowed names, valid JSON, valid schemas, every Liquid file parses, every template only uses sections that exist, the screenshot is a real image of the right size. All problems are listed at once.
  3. The theme is added to the library unpublished, with its JSON documents as its starting content.

Upload new version (or mattersimple-theme push --theme <id>) replaces the theme's code but keeps its content, unless you tick Also replace pages and settings. Replaced content is kept in the theme editor's history.

Still need help?

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

Sign in to contact support