Basker Docs

Theme directory structure

Required and optional directories, file naming conventions, and asset size limits for Basker themes

Themes are packaged as ZIP files and processed during upload. The directory structure decides how blocks, templates, layouts, settings, and assets are extracted into the theme manifest.

DirectoryRequiredPurpose
blocks/YesReusable content blocks with schema definitions
layouts/YesHTML shell templates that wrap page content
templates/YesCollection-specific page templates
assets/NoStatic files: CSS, JavaScript, images, fonts
snippets/NoReusable Liquid partials included via {% render %}
components/NoLarger Liquid partials for page-level UI like headers, footers, or card components, also resolved by {% render %}
config/NoTheme-level configuration files
.well-known/NoFiles served at /.well-known/* for domain verification, security disclosure, and similar use cases

Required directories

blocks/

.liquid files defining reusable content blocks. Each must include a {% schema %} tag with a JSON object containing at minimum name (string) and settings (array).

Blocks are available to editors in the admin. The schema defines the fields editors fill in when adding a block to a page.

blocks/
  hero-banner.liquid
  text-section.liquid
  image-gallery.liquid
  call-to-action.liquid

Schema requirements:

PropertyTypeRequiredDescription
namestringYesMust match the block's filename without the .liquid extension
settingsarrayYesField definitions for editor inputs
labelstringNoDisplay name in the editor; defaults to name
singularstringNoSingular label; defaults to name
pluralstringNoPlural label; defaults to name

Example block file:

<section class="hero-banner">
  <h1>{{ block.heading }}</h1>
  <p>{{ block.subheading }}</p>
</section>

{% schema %}
{
  "name": "hero-banner",
  "label": "Hero Banner",
  "singular": "Hero Banner",
  "plural": "Hero Banners",
  "settings": [
    {
      "name": "heading",
      "label": "Heading",
      "type": "text"
    },
    {
      "name": "subheading",
      "label": "Subheading",
      "type": "textArea"
    }
  ]
}
{% endschema %}

Validation rules:

  • Missing {% schema %} produces an error during upload validation. The local theme checker reports it as a warning so you can keep iterating.
  • Missing name produces an error.
  • settings must be an array; a non-array value produces an error.
  • Duplicate name values across block files produce a warning.
  • Put exactly one {% schema %} tag in each block. Multiple schema tags produce a validation warning and do not have a stable merge order.

See Block schema reference for the full field type list.

layouts/

.liquid files defining the outer HTML shell. Every theme must include layouts/default.liquid.

layouts/
  default.liquid
  checkout.liquid
  blank.liquid

Required placeholders:

PlaceholderPurposePlacement
{{ content_for_header }}Basker injects scripts, meta tags, JSON-LD, and preview bannersInside <head>
{{ content_for_layout }}Basker outputs the rendered template body captured by the templateInside <body>

Every template must declare its layout explicitly with {% layout 'layouts/default.liquid' %}. There is no implicit default: a template without a {% layout %} tag renders on its own, and since template bodies are wrapped in {% capture content_for_layout %}, an omitted layout tag produces an empty page.

Validation rules:

  • Missing layouts/default.liquid produces a validation error. It is one of the structural errors that prevents upload.
  • A {% layout %} referencing a non-existent layout file produces a validation error, but is reported as a theme-health issue rather than a structural upload blocker.

templates/

.liquid files controlling how content is rendered for specific collections. Filenames follow a strict naming convention.

templates/
  page.liquid
  page.landing.liquid
  event.default.liquid
  post.default.liquid
  blog.default.liquid
  index.liquid

File naming convention:

[collection].liquid or [collection].[name].liquid
SegmentDescriptionExamples
collectionThe Basker content collection this template servespage, event, post, blog, organization, person, venue, work, season, series
nameThe template variant identifierdefault, landing, sidebar, full-width

A template with only one segment before .liquid (like index.liquid or page.liquid) is treated as a base template where collection is the filename and name defaults to "default".

Schema structure (optional but recommended):

{% schema %}
{
  "settings": [
    {
      "name": "show_sidebar",
      "label": "Show sidebar",
      "type": "switch"
    }
  ],
  "blocks": ["hero-banner", "text-section"]
}
{% endschema %}
PropertyTypeRequiredDescription
settingsarrayNoTemplate-level field definitions
blocksarrayNoNames of blocks permitted on pages using this template

blocks array entries must match name values defined in blocks/. A reference to a non-existent block name produces a warning.

Validation rules:

  • Missing {% schema %} produces a warning.
  • No index.liquid, page.liquid, or default.liquid produces a structural error that prevents upload.
  • Invalid JSON in {% schema %} produces an error.
  • settings as a non-array value produces a warning.
  • blocks entries referencing undefined block names produce a warning.

Optional directories

assets/

Static files served via the Basker CDN. Reference assets in Liquid using asset_url.

assets/
  css/
    main.css
    typography.css
  js/
    navigation.js
  images/
    logo.svg
    hero-bg.jpg
  fonts/
    custom-font.woff2

Referencing assets:

<link rel="stylesheet" href="{{ 'css/main.css' | asset_url }}">
<script src="{{ 'js/navigation.js' | asset_url }}"></script>
<img src="{{ 'images/logo.svg' | asset_url }}" alt="Logo">

Allowed file extensions:

CategoryExtensions
Stylesheets.css
Scripts.js
Data and metadata.json, .map, .txt, .xml, .webmanifest
Images.gif, .ico, .jpg, .jpeg, .png, .svg, .webp
Fonts.eot, .ttf, .woff, .woff2
Other supported source.vue

Files with extensions outside this list produce a validation error. This is reported in theme health, but it is not one of the structural errors that prevents upload.

Size limits:

File typeMaximum size
Images (gif, ico, jpg, jpeg, png, svg, webp)1.5 MB
All other assets2.5 MB

Exceeding either limit produces a warning.

Validation rules:

  • Disallowed file extensions produce an error.
  • Assets referenced in Liquid but missing from assets/ produce an error.
  • Assets present in assets/ but not referenced in any Liquid file produce a warning (orphaned assets).

snippets/

Reusable Liquid partials, included in layouts/templates/blocks via {% render %}.

snippets/
  social-links.liquid
  breadcrumbs.liquid
  pagination.liquid

Usage:

{% render 'social-links' %}
{% render 'pagination', total_pages: total_pages, current_page: current_page %}

The {% include %} tag is deprecated. Use {% render %} instead. Files using {% include %} produce a deprecation warning during validation.

Validation rules:

  • A {% render %} reference is resolved against snippets/, components/, and blocks/ for a bare name, or from the theme root when the reference contains a path separator. Anything that resolves to neither produces a warning.
  • Snippets present in snippets/ but never referenced produce a warning (unused snippets).

components/

A second home for Liquid partials, conventionally used for larger page-level UI (global headers, footers, navigation menus, card components) while snippets/ holds smaller reusable bits like icons or formatters.

components/
  global-header.liquid
  global-footer.liquid
  event-card.liquid

components/ is a naming convention rather than a separate Liquid root. Render a component with its path from the theme root, such as {% render 'components/global-header' %}. Files in snippets/ can be rendered without the directory prefix, such as {% render 'social-links' %}.

config/

Theme-level configuration files.

config/
  settings_schema.json

settings_schema.json

Defines theme-wide settings that appear in the admin under the theme's settings panel. The file must be a JSON array of setting groups.

[
  {
    "name": "theme_settings",
    "settings": [
      {
        "name": "primary_colour",
        "label": "Primary colour",
        "type": "color"
      },
      {
        "name": "font_family",
        "label": "Font family",
        "type": "select",
        "options": [
          { "label": "Sans-serif", "value": "sans-serif" },
          { "label": "Serif", "value": "serif" }
        ]
      }
    ]
  }
]

Each entry is a setting group. Each must have a name property.

Validation rules:

  • File must parse as valid JSON.
  • Top-level value must be an array.
  • Non-object entries produce a warning.
  • Entries missing name produce a warning.

Tenant locking: A setting group with "name": "theme_settings" may include a "tenant" property. Setting it locks the theme to that tenant's slug; uploading the theme to any other site produces an error.

.well-known/

Files in .well-known/ are served verbatim at /.well-known/<filename> on the live site. Common uses include apple-app-site-association, assetlinks.json, and security.txt.

.well-known/
  apple-app-site-association
  assetlinks.json
  security.txt

.well-known/ files are validated more strictly than regular assets.

Allowed extensions:

ExtensionNotes
.jsonJSON manifest files
.pemPEM-encoded certificates
.txtPlain text
.xmlXML documents
(no extension)Permitted: many .well-known standards use extensionless filenames

Size limit: 100 KB per file.

Validation rules:

  • Disallowed extensions produce an error.
  • Files larger than 100 KB produce a warning.
  • Keep files directly inside .well-known/ so their public URL is predictable. Paths are normalised and checked before files are served.

Ignored directories

DirectoryReason
__MACOSX/Skipped when the theme ZIP is unpacked
examples/Excluded from manifest generation

Allowed field types

Field types used in settings arrays across blocks, templates, and settings_schema.json.

TypeDescription
textSingle-line text input
textAreaMulti-line text input
richTextRich text editor with formatting
numberNumeric input
checkboxBoolean checkbox
switchBoolean toggle switch
selectDropdown selection
radioRadio button group
colorColour picker
dateDate picker
dateTimeDate and time picker
emailEmail address input
urlURL input
uploadFile or image upload
relationshipReference to another document
codeCode editor
jsonJSON editor
hiddenHidden field: not shown to editors
groupGroups nested fields together
arrayRepeatable set of fields

Type aliases: richtext is normalised to richText, textarea to textArea, datetime to dateTime. Unsupported type values produce a warning.

Nesting: group and array types support a fields sub-array for nested field definitions. Nesting deeper than four levels produces a best-practice warning.

Complete example

my-theme/
  assets/
    css/
      main.css
      variables.css
    js/
      navigation.js
      gallery.js
    images/
      logo.svg
      default-hero.jpg
    fonts/
      brand-regular.woff2
      brand-bold.woff2
  blocks/
    hero-banner.liquid
    text-section.liquid
    image-gallery.liquid
    call-to-action.liquid
    feature-grid.liquid
  config/
    settings_schema.json
  layouts/
    default.liquid
    checkout.liquid
  snippets/
    social-links.liquid
    breadcrumbs.liquid
    pagination.liquid
    seo-meta.liquid
  templates/
    index.liquid
    page.liquid
    page.landing.liquid
    event.default.liquid
    post.default.liquid
    blog.default.liquid

On this page