create-template

File: bin/create-template.php

Inserts a new template row into the database from a JSON definition file. This is the CLI equivalent of creating a template in Page Builder's template context (see Page Builder) and clicking Save.

Usage

Run from the WordPress root directory:

wp eval-file wp-content/plugins/sanil-website-builder/bin/create-template.php path/to/definition.json

The only argument is the path to your JSON definition file. The path can be relative (resolved from the current working directory) or absolute.

Definition File Format

The definition file is a JSON object with the following fields:

Field Type Required Default Description
name string Yes Display name shown in the templates list page
schema array Yes Page Builder kind: 'div'|'widget' tree — same shape as sanilwb_data
category string No "default" Category slug for grouping templates
supports string No "" Comma-separated post type slugs this template supports

There is no builder_type field anymore — every template row is "template", and the script no longer reads or validates a builder_type key even if one is present in the JSON.

Minimal example

{
  "name": "Simple Heading Card",
  "schema": [
    {
      "kind": "div",
      "options": {
        "sanilwb_flex_direction": "column",
        "sanilwb_gap": "8",
        "sanilwb_padding_vertical": "12",
        "sanilwb_show_desktop": "1",
        "sanilwb_show_tablet": "1",
        "sanilwb_show_mobile": "1"
      },
      "children": [
        {
          "kind": "widget",
          "widget_uid": "pb-heading1",
          "widget_type": "heading",
          "widget_values": "{\"sanilwb_tag\":\"h2\",\"sanilwb_text\":\"Heading\",\"sanilwb_font_size\":\"18\",\"sanilwb_font_weight\":\"600\",\"sanilwb_show_desktop\":\"1\",\"sanilwb_show_tablet\":\"1\",\"sanilwb_show_mobile\":\"1\"}",
          "widget_title": "",
          "show_desktop": "1",
          "show_tablet": "1",
          "show_mobile": "1"
        }
      ]
    }
  ]
}

Full example with all fields

{
  "name": "News Horizontal Card",
  "category": "news",
  "supports": "post",
  "schema": [
    {
      "kind": "div",
      "options": {
        "sanilwb_flex_direction": "row",
        "sanilwb_align_items": "flex-start",
        "sanilwb_gap": "12",
        "sanilwb_border_style": "solid",
        "sanilwb_border_color": "#e8e8e8",
        "sanilwb_border_width_bottom": "1",
        "sanilwb_padding_vertical": "12",
        "sanilwb_show_desktop": "1",
        "sanilwb_show_tablet": "1",
        "sanilwb_show_mobile": "1"
      },
      "children": [
        {
          "kind": "widget",
          "widget_uid": "pb-image1",
          "widget_type": "image",
          "widget_values": "{\"sanilwb_size\":\"medium\",\"sanilwb_img_width\":\"130\",\"sanilwb_show_desktop\":\"1\",\"sanilwb_show_tablet\":\"1\",\"sanilwb_show_mobile\":\"0\"}",
          "widget_title": "",
          "show_desktop": "1",
          "show_tablet": "1",
          "show_mobile": "0"
        },
        {
          "kind": "div",
          "options": {
            "sanilwb_flex_direction": "column",
            "sanilwb_gap": "6",
            "sanilwb_show_desktop": "1",
            "sanilwb_show_tablet": "1",
            "sanilwb_show_mobile": "1"
          },
          "children": [
            {
              "kind": "widget",
              "widget_uid": "pb-heading2",
              "widget_type": "heading",
              "widget_values": "{\"sanilwb_tag\":\"h3\",\"sanilwb_text\":\"News headline\",\"sanilwb_font_size\":\"16\",\"sanilwb_font_weight\":\"600\",\"sanilwb_color\":\"var(--color-text)\",\"sanilwb_hover_color\":\"var(--color-primary)\",\"sanilwb_link_url\":\"1\",\"sanilwb_show_desktop\":\"1\",\"sanilwb_show_tablet\":\"1\",\"sanilwb_show_mobile\":\"1\"}",
              "widget_title": "",
              "show_desktop": "1",
              "show_tablet": "1",
              "show_mobile": "1"
            },
            {
              "kind": "widget",
              "widget_uid": "pb-date1",
              "widget_type": "date",
              "widget_values": "{\"sanilwb_format\":\"time_ago\",\"sanilwb_custom_format\":\"Y-m-d\",\"sanilwb_date_source\":\"post_date\",\"sanilwb_language\":\"english\",\"sanilwb_show_desktop\":\"1\",\"sanilwb_show_tablet\":\"1\",\"sanilwb_show_mobile\":\"1\"}",
              "widget_title": "",
              "show_desktop": "1",
              "show_tablet": "1",
              "show_mobile": "1"
            }
          ]
        }
      ]
    }
  ]
}

Schema Node Reference

A schema is an array of root nodes — same shape Page Builder itself saves (see Page Builder → Data Structure). Each node has kind: "div" or kind: "widget". A div's own layout/appearance fields live in its options object; a widget's fields are a JSON-encoded string in widget_values.

div node fields

Field Description
options Object holding layout (sanilwb_flex_direction, sanilwb_gap, sanilwb_align_items, sanilwb_justify_content), appearance (background, border, spacing), and visibility (sanilwb_show_desktop/tablet/mobile) fields
children Array of further div or widget nodes

widget node fields

Field Description
widget_type Registered widget type — see admin/assets/js/src/page-builder/config/widgets/index.js for the full list
widget_uid Unique string ID for this widget instance (e.g. "pb-abc123")
widget_values JSON-encoded string of the widget's own field values (sanilwb_* keys — each widget file's defaultValues shows the full set)
widget_title Optional admin label
show_desktop/show_tablet/show_mobile Duplicated from widget_values.sanilwb_show_* so PHP can read visibility without decoding JSON first

Only widgets whose contexts array includes "template" may be used in a template schema — data-fetching widgets (post_content, shortcodes, template_reference) are page-only. See Page Builder → Template Editing.

Responsive field overrides use double-underscore suffixes: fieldName__tablet, fieldName__mobile.

For the complete field reference, review the relevant widget's file in admin/assets/js/src/page-builder/config/widgets/.

What the Script Does

  1. Reads and parses the JSON definition file.
  2. Validates that name and schema are present.
  3. Calls SANILWB_DB::insert() to write the row to {prefix}sanilwb_templates, with builder_type hardcoded to "template".
  4. Prints the new template ID on success.

There is no compile step — a template's schema_json renders live wherever it's referenced (see Dynamic Template Widget), so the row is immediately usable as soon as it's inserted, with nothing else to generate. The result is identical to saving a template through the UI — the template is immediately available for use in the Page Builder widget picker.

Example Output

Template inserted. ID: 7

Done. Template 'News Horizontal Card' created with ID 7.

Error Cases

Error Cause
No definition file specified First argument was omitted
File not found The path does not exist or is misspelled
Invalid JSON The file contains a JSON syntax error — check with jq . file.json
must include a 'name' field The name key is missing or empty
must include a 'schema' field The schema key is missing or is not an array
SANILWB_DB class not found Plugin is not active — activate it first
Failed to insert template Database error — check $wpdb->last_error via wp db query

Typical Workflow

Use this script to seed templates for a blueprint definition, or bootstrap a development environment without clicking through the UI.

# 1. Reset everything first
wp eval-file wp-content/plugins/sanil-website-builder/bin/reset-plugin-data.php

# 2. Create templates from definition files
wp eval-file wp-content/plugins/sanil-website-builder/bin/create-template.php definitions/news-card.json
wp eval-file wp-content/plugins/sanil-website-builder/bin/create-template.php definitions/news-headline.json

# 3. Verify the templates were created
wp db query "SELECT id, name, category, builder_type FROM wp_sanilwb_templates;"