Basker Docs

The theme manifest

How Basker generates a structured manifest from your theme files during upload, and what drives the editor experience

The theme manifest is the structured representation that Basker generates during upload. It combines block schemas, template schemas, and config/settings_schema.json so the editor can:

  • Present the correct fields for each block and template.
  • Determine which blocks are available on which templates.
  • Apply theme-wide settings to the live site renderer.
  • Detect changes between theme versions for deployment tracking.

What the manifest is

The manifest is a JSON object with three top-level properties. It is not a file you create. Basker generates it from your theme files during upload.

type ThemeManifest = {
  blocks: ThemeBlockSchema[];
  settings: JsonObject[] | null;
  templates: ThemeTemplateManifestEntry[];
};

Key characteristics:

  • Auto-generated. You never write or edit the manifest directly. Basker produces it during upload.
  • Deterministic. Given the same theme files, Basker always produces the same manifest.
  • Versioned. Each upload sets a manifestRevision timestamp.
  • Diffable. On every upload, Basker computes a diff between the previous and new manifest. Basker records added, removed, and changed blocks, templates, and settings on the theme's upload log.

How the manifest is built

The upload process follows a fixed sequence.

1. ZIP extraction

Basker extracts the uploaded ZIP in memory. It discards __MACOSX/ and examples/ directories. It categorizes every remaining file by its path prefix: blocks/, layouts/, templates/, assets/, snippets/, or config/.

2. Schema extraction from Liquid files

Basker parses every .liquid file through a Liquid engine configured for schema extraction. The engine registers passthrough implementations for tags like {% render %}, {% layout %}, and {% stageblocks %} so it can parse without resolving external references. When it encounters {% schema %}, it captures the raw text inside.

If the Liquid syntax is invalid, Basker records a compatibility error. If the schema JSON is malformed, Basker records a schema validation error. A template can still receive a manifest entry with empty settings and allowed_blocks. A block without a usable schema cannot become a block entry.

Use exactly one {% schema %} tag in each block or template. Multiple schema tags produce a validation warning and do not have a stable merge order.

3. Block manifest entries

For each .liquid file inside blocks/, Basker parses the extracted schema JSON into a block manifest entry:

type ThemeBlockSchema = {
  name: string;
  settings: ThemeField[];
  label?: string;
  singular?: string;
  plural?: string;
  fileHash?: string;
};

name is required. It is the unique identifier for the block across the entire theme. If label, singular, or plural are missing, they default to name.

Basker normalizes field types within settings during extraction. richtext becomes richText, textarea becomes textArea, datetime becomes dateTime. Unrecognized types stay in the manifest, but they produce a validation warning.

Basker computes a SHA-256 hash of the entire file content and stores it as fileHash. This enables change detection. When you re-upload a theme, Basker compares hashes to determine which blocks have actually changed.

4. Template manifest entries

For each .liquid file inside templates/, Basker parses the extracted schema into a template manifest entry:

type ThemeTemplateManifestEntry = {
  template: string;
  collection: string;
  name: string;
  settings: ThemeField[];
  allowed_blocks: JsonValue[];
  fileHash?: string;
};

Basker derives template, collection, and name from the filename, not from the schema JSON.

Filename parsing:

Filenamecollectionnametemplate
page.liquidpagedefaultpage.liquid
page.landing.liquidpagelandingpage.landing.liquid
event.sidebar.liquideventsidebarevent.sidebar.liquid
index.liquidindexdefaultindex.liquid
page.liquidpagedefaultpage.liquid

settings comes from the schema JSON. allowed_blocks comes from the blocks key. Each entry in allowed_blocks should match the name of a block defined in blocks/. A referenced block name that does not exist in the theme produces a validation warning.

5. Settings extraction

If config/settings_schema.json exists, Basker parses its contents as a JSON array. Entries can be individual fields or groups of fields. Groups use a fields array. You set starting values with default or the field-specific default property documented in the settings guide.

[
  {
    "name": "colours",
    "type": "group",
    "fields": [
      {
        "type": "color",
        "name": "primary_colour",
        "label": "Primary colour",
        "default": "#1a1a2e"
      }
    ]
  },
  {
    "name": "typography",
    "type": "group",
    "fields": [
      {
        "type": "select",
        "name": "heading_font",
        "label": "Heading font",
        "options": [
          { "label": "Sans-serif", "value": "sans-serif" },
          { "label": "Serif", "value": "serif" }
        ],
        "default": "sans-serif"
      }
    ]
  }
]

If the file is absent, settings is null. If the file is present but contains invalid JSON or a non-array value, Basker cannot extract the settings, and validation reports the problem.

File hashing for change detection

Basker hashes every block and template file using SHA-256 from the full file content (HTML, Liquid tags, schema) and stores the hash in fileHash.

When you re-upload a theme, Basker compares hashes between the previous and new manifests to determine:

  • Added entries: present in the new manifest, absent from the previous.
  • Removed entries: present in the previous, absent from the new.
  • Changed entries: present in both with different content (detected via hash or deep comparison of the schema object).

This comparison powers the manifest diff recorded on the theme's upload log entry (see Versioning and rollback) on every upload, not only when the currently active theme is re-uploaded.

Manifest revision tracking

Each upload sets a manifestRevision property on the theme document: an ISO 8601 timestamp marking when Basker generated the manifest:

"2025-03-15T14:22:08.421Z"

It is not a version number. It is a point-in-time marker. It changes with every upload, regardless of whether the manifest content actually changed. Use the manifest diff to determine real changes.

How the manifest drives the editor

After Basker generates and stores the manifest, the editor synchronizes it with the underlying admin schema. For each entry in manifest.blocks, the editor creates or updates a corresponding admin field group. It transforms the block's settings array into editor controls: what site editors see when adding the block to a page.

The same applies to templates. Each entry in manifest.templates becomes a set of editable fields in the page editor when a site editor selects that template.

If a block or template existed in the previous manifest but is absent from the new one, the editor removes it from its available definitions. Check existing content that used a removed definition before deployment.

Recommendation: Use config/settings_schema.json for global theme settings (colors, fonts, layout preferences) and template-level {% schema %} settings for options specific to a single template.

In practice

You maintain a theme with 8 blocks, 5 templates, and a settings_schema.json. You rename a block from hero_banner to hero_section in its schema, update the blocks array in two templates that reference it, and add a new color setting to settings_schema.json.

After uploading, the manifest diff records:

  • Blocks: hero_banner removed, hero_section added (Basker treats the rename as a new block because name changed).
  • Templates: Two templates changed: their allowed_blocks arrays differ.
  • Settings: Changed (new color field detected).

The editor deletes the old hero_banner block definition and creates the new hero_section. Pages that had the old block will no longer render it. This is why you must coordinate block name changes with content migration.

Common misconceptions

MisconceptionReality
The manifest is a file I create in my themeThe manifest is auto-generated during upload. You define schemas in .liquid files and settings_schema.json. Basker consolidates them.
Changing the HTML in a block file does not affect the manifestThe fileHash changes whenever any part of the file changes. The editor only re-syncs fields when the schema content differs.
manifestRevision tracks the number of uploadsIt is an ISO 8601 timestamp, not a counter.
Re-uploading an unchanged theme has no effectBasker sets a new manifestRevision and processes the upload. With matching hashes, the manifest diff shows no meaningful changes.
You can change block names freelyBasker treats renaming as removing the old block and adding a new one. Existing page content referencing the old name loses its association.
  • Theme validation: The upload process validates all files before generating the manifest. Basker records validation errors and warnings in a validation log alongside the manifest. See Validation errors.
  • Manifest diffs: On every upload, Basker stores a diff between the old and new manifests on the theme's upload log. See Versioning and rollback.

On this page