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.

Overview

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
namestringYesUnique identifier across all blocks in the theme
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.
  • Multiple {% schema %} tags in one file: only the first is used; a warning is issued.

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>

Templates can reference a specific layout using {% layout %}. If no layout is specified, default.liquid is used.

Validation rules:

  • Missing layouts/default.liquid produces an error.
  • A {% layout %} referencing a non-existent layout file produces an error.

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 or page.liquid or default.liquid produces an error.
  • 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.json
Images.gif, .ico, .jpg, .jpeg, .png, .svg, .webp
Fonts.eot, .ttf, .woff, .woff2

Files with extensions outside this list are rejected during validation with an error.

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: paginate.pages, current_page: paginate.current_page %}

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

Validation rules:

  • A {% render %} reference to a snippet that doesn't exist in snippets/, components/, or blocks/ 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

{% render %} resolves partials against snippets/, components/, and blocks/, so a call like {% render 'components/global-header' %} works without extra configuration. The split is a convention only; the validator treats both directories the same way.

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.
  • Path segments must be simple and traversal-safe; nested subdirectories under .well-known/ are not allowed.

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
  • Tutorial — apply this structure to a working theme.
  • The theme manifest — how directory contents are transformed during upload.

On this page