Blueprints

Blueprints is the "full site in one click" feature. A user browses a gallery of pre-built site layouts served from a remote API, selects one, steps through a configuration wizard, and ends up with a fully functional site — header, footer, layout templates, pages, categories, sidebars, and theme options all applied in sequence.

Preset PHP files (header, footer, single post, archive) are bundled inside the plugin. The Blueprint JSON only references preset slugs and data — no PHP files are downloaded from the remote server.


Screen Flow

The React app controls which screen is visible via a mode value in the Zustand store. Screens layer on top of the gallery — the gallery stays mounted at all times.

Mode Screen What it does
gallery Gallery Grid of blueprint cards; user picks a blueprint to apply
preflight Pre-flight Modal Runs compatibility checks before the wizard opens
wizard Wizard Multi-step configuration — user makes choices for each layer
progress Progress Screen Applies each layer in sequence, shows real-time status
success Success Screen Install complete summary with quick-action links

Blueprint JSON Structure

The remote API returns this shape for each blueprint. The plugin never modifies it — it is stored as-is in a transient for the duration of the install session.

{
  "name": "The Daily",
  "slug": "the-daily",
  "version": "1.0",
  "requires_plugin_version": "x.x",
  "requires_theme_version": "x.x",
  "category": "news",
  "header_preset": "modern-news",
  "header_settings": {},
  "footer_preset": "news-footer",
  "footer_settings": {},
  "theme_options": {},
  "templates": {
    "single_post": {},
    "category": {},
    "archive": {}
  },
  "pages": [
    { "title": "Home", "slug": "home", "set_as_front": true, "builder_data": [] },
    { "title": "Contact", "slug": "contact", "set_as_front": false, "builder_data": [] }
  ],
  "categories": [
    { "name": "Politics", "slug": "politics" }
  ],
  "sidebars": {}
}

Remote API and Caching

Class: includes/class-sanilwb-blueprints-api.php

Two endpoints on the Sanil server:

  • GET /blueprints — list of blueprints (name, slug, thumbnail URL, category, version requirements)
  • GET /blueprints/{slug} — full blueprint JSON for one blueprint

The list is cached locally as a WordPress transient so the gallery loads even without a live internet connection. The full blueprint JSON is only fetched when the user clicks Apply on a card, and again at the start of the install session.

Method Description
get_list() Returns the cached list, or fetches and caches it if stale
get_blueprint( $slug ) Fetches and returns one full blueprint array, or null on failure
bust_cache() Deletes the cached list so the next get_list() call re-fetches

Pre-flight Checks

Class: includes/class-sanilwb-blueprints-preflight.php

SANILWB_Blueprints_Preflight::run( $blueprint ) runs all checks against a full blueprint array and returns an array of result objects, each with label, passed, and message fields.

Checks run:

Check What it verifies
Plugin version Installed plugin version ≥ requires_plugin_version
Theme version Installed theme version ≥ requires_theme_version
Header preset The header_preset slug folder exists on disk
Footer preset The footer_preset slug folder exists on disk
Content presets Each preset slug referenced in templates exists on disk
Theme options The theme_options key is present (optional data check)

Every check must pass before the wizard opens. The Pre-flight Modal disables its "Proceed to Install" button until all_passed is true.


Snapshot and Rollback

Class: includes/class-sanilwb-blueprints-snapshot.php

A snapshot of all affected data is captured before any layer runs, stored as the sanilwb_blueprint_snapshot WordPress option. If any layer fails, the snapshot is restored immediately and the install stops.

Method Description
capture( $overwrite_page_ids ) Reads and stores current values for all layer targets
restore() Writes all captured values back to the DB; returns true on success
exists() Returns true if a snapshot is stored
clear() Deletes the snapshot option

What the snapshot captures per layer:

Layer What is captured
header sanilwb_header_preset + sanilwb_header_preset_settings
footer sanilwb_footer_preset + sanilwb_footer_preset_settings
theme_options sanilwb_theme_options
content_presets sanilwb_{type}_preset + sanilwb_{type}_preset_settings for each type
db_templates Nothing — orphan template rows are acceptable on failure
pages (action=new) Nothing — orphan pages are acceptable on failure
pages (action=map) sanilwb_data + _wp_page_template for each mapped page ID
categories Nothing — orphan categories are acceptable on failure
sidebars sidebars_widgets + all widget instance options touched

One snapshot at a time — applying a new blueprint overwrites the previous snapshot. A "Restore Previous Blueprint" button is visible in the gallery whenever a snapshot exists.


Install Status Tracking

The sanilwb_blueprint_install_status WordPress option tracks whether the last install completed cleanly:

Value Meaning
in_progress Set when blueprint_start is called
completed Set when finishInstall succeeds, or when a failed install is rolled back

If install_status is in_progress when the Pre-flight screen opens, a warning section appears at the bottom of the modal explaining that the previous install was incomplete, with a "Restore Previous State" button and an "I understand, continue anyway" checkbox.

The "Proceed to Install" button is disabled until all checks pass and (when the warning is shown) the checkbox is ticked.


Installation Layers

Class: includes/class-sanilwb-blueprints-applier.php

Each layer is applied by a static method. The Progress Screen calls them one at a time via the sanilwb_blueprint_apply_layer AJAX action, passing the layer name.

Layer name Applier method What it does
header apply_header() Writes sanilwb_header_preset and sanilwb_header_preset_settings; syncs fonts
footer apply_footer() Writes sanilwb_footer_preset and sanilwb_footer_preset_settings; syncs fonts
theme_options apply_theme_options() Merges blueprint colors and typography into sanilwb_theme_options; syncs Google Fonts
content_presets apply_content_presets() Sets the preset slug + settings for single, category, archive, and any other content types in the blueprint
db_templates apply_db_templates() Inserts layout templates into wp_sanilwb_templates; compiles them; builds a ref map for page data
pages apply_pages() Creates new pages or overwrites existing mapped pages with the blueprint's page builder data
categories apply_categories() Creates any categories that do not already exist
sidebars apply_sidebars() Replaces widget content in each sidebar named in the blueprint

Rules:

  • Never delete existing data — only overwrite or add.
  • Pages are additive — new pages are created; existing pages are only overwritten when the user explicitly mapped them in the wizard and confirmed the overwrite.
  • Stop on error — if any layer throws, the Progress Screen restores the snapshot and halts.

Idempotency Behavior

What happens when the same blueprint is installed more than once, or when data from a previous install already exists.

Per-layer behavior on re-install

Layer Re-install behavior
header / footer / content_presets update_option() overwrites the saved preset slug and settings. Fully idempotent.
theme_options (color preset) The blueprint's color preset is matched against existing presets by id. If a preset with the same id exists it is replaced in-place; otherwise it is appended. The blueprint preset is always made the active preset. No duplicates accumulate.
db_templates Always calls SANILWB_DB::insert(). Every re-install creates new rows. Running the same blueprint twice produces duplicate templates in wp_sanilwb_templates.
pages Depends on the wizard choice. Choosing "Create new page" again calls wp_insert_post() and produces a new page. Choosing "Map to existing" overwrites the existing page's meta — idempotent.
categories wp_insert_term() silently discards the error if the slug already exists. Idempotent.
sidebars Replaces the sidebar's widget list, but always creates new widget instances in widget_block / widget_text options first. Old instances are not cleaned up — they become orphans in the options table after repeated installs.

Color preset name vs. id

The deduplication check compares preset id values, not name values. Two presets that share a display name but have different ids will both appear in the color presets list. To avoid duplicate entries in the UI, blueprint color presets must use a stable, unique id (e.g. the-daily-colors) rather than a human-readable name.

Known accumulation issues

  • Duplicate DB templates — re-running a blueprint is the only way to produce them. They are harmless but invisible; the only cleanup path is a manual database delete.
  • Orphaned widget instanceswidget_block and widget_text options grow by the number of widgets in the blueprint's sidebars block on each re-install. They do not affect the live site but increase option table size over time.

Installation Wizard

The wizard is a single-screen modal (mode === 'wizard') with a step indicator. The user works through configuration choices for each layer before applying. All choices are stored in wizardChoices in the Zustand store and sent to the server as a single JSON object when the install begins.

File: admin/assets/js/src/blueprints/screens/Wizard.jsx

The wizard currently has one configurable step: Pages. For each page in the blueprint, the user chooses one of:

  • Create new page — a fresh page will be created.
  • Map to existing page — pick from a dropdown of current published pages; the existing page's builder data will be overwritten (an inline confirmation message is shown before the user can proceed).

The wizard validates that every page has a choice set before enabling "Proceed to Apply".


AJAX Actions

All blueprint server calls go through SANILWB_Ajax. Each action verifies the sanilwb_templates nonce and requires edit_pages capability.

Action Handler method Description
sanilwb_blueprints_list get_blueprints_list() Returns the cached blueprint list
sanilwb_blueprint_preflight blueprint_preflight() Runs pre-flight checks; returns results + full blueprint data
sanilwb_blueprint_start blueprint_start() Fetches the full blueprint JSON, captures the snapshot, sets status to in_progress, stores blueprint and wizard choices in transients
sanilwb_blueprint_apply_layer blueprint_apply_layer() Applies one named layer using the stored blueprint and choices
sanilwb_blueprint_finish blueprint_finish() Sets status to completed, deletes transients, updates lastBlueprintName
sanilwb_blueprint_restore blueprint_restore() Calls SANILWB_Blueprints_Snapshot::restore()
sanilwb_blueprint_snapshot_exists blueprint_snapshot_exists() Returns whether a snapshot is stored

Edge cases handled in blueprint_start:

  • If the JSON fetch fails before the snapshot is captured, install_status is NOT set to in_progress — nothing has changed yet.
  • The "Apply Blueprint" button is disabled on first click and stays disabled for the duration so a double-click cannot start two concurrent installs.

PHP Infrastructure

File Class Purpose
includes/class-sanilwb-blueprints-api.php SANILWB_Blueprints_API Remote API client with local list caching
includes/class-sanilwb-blueprints-preflight.php SANILWB_Blueprints_Preflight Compatibility checks before install
includes/class-sanilwb-blueprints-snapshot.php SANILWB_Blueprints_Snapshot Capture and restore pre-install site state
includes/class-sanilwb-blueprints-applier.php SANILWB_Blueprints_Applier One static method per layer; called by the AJAX handler
admin/class-sanilwb-admin-blueprints.php SANILWB_Admin_Blueprints Admin page registration, asset enqueue, window.SanilWbBlueprints injection

React App Architecture

Entry point: admin/assets/js/src/blueprints/index.jsx

BlueprintsApp            ← root: fetches blueprint list on mount, renders active screen
├── Gallery              ← blueprint card grid, category filter, "Restore" button
├── PreflightModal       ← runs pre-flight checks, broken-install warning
├── Wizard               ← step-by-step page mapping choices
├── ProgressScreen       ← applies layers in sequence, handles failure + rollback
└── SuccessScreen        ← install complete summary + quick links

State is managed by a single Zustand store (store.js). All API calls go through the thin api.js wrapper which reads ajaxUrl and nonce from window.SanilWbBlueprints.

Gallery is always mounted. Other screens are conditionally rendered on top of it based on mode.


Window Data Object

window.SanilWbBlueprints is injected by SANILWB_Admin_Blueprints::enqueue_blueprints_assets() before the React bundle loads.

Key Type Description
nonce string sanilwb_templates nonce — used for all AJAX calls
ajaxUrl string WordPress admin-ajax.php URL
adminUrl string WordPress admin root URL
pluginVersion string Installed plugin version string
snapshotExists bool Whether a previous blueprint snapshot is stored
installStatus string 'completed' or 'in_progress' — last known install status
lastBlueprintName string Name of the last successfully applied blueprint
existingPages array [{id, title}] — all published pages, used by the wizard page-mapping step

Key Files

File Purpose
admin/class-sanilwb-admin-blueprints.php Admin page, asset enqueue, data injection
admin/assets/js/src/blueprints/BlueprintsApp.jsx React root; screen router
admin/assets/js/src/blueprints/store.js Zustand store; all UI state
admin/assets/js/src/blueprints/api.js AJAX wrapper functions
admin/assets/js/src/blueprints/screens/Gallery.jsx Blueprint card grid
admin/assets/js/src/blueprints/screens/PreflightModal.jsx Pre-flight check modal
admin/assets/js/src/blueprints/screens/Wizard.jsx Page mapping wizard
admin/assets/js/src/blueprints/screens/ProgressScreen.jsx Layer-by-layer install progress
admin/assets/js/src/blueprints/screens/SuccessScreen.jsx Install complete screen
admin/assets/css/blueprints.scss Blueprints admin styles
admin/templates/blueprints/page.php PHP mount point for the React app
includes/class-sanilwb-blueprints-api.php Remote API client
includes/class-sanilwb-blueprints-preflight.php Pre-flight checker
includes/class-sanilwb-blueprints-snapshot.php Snapshot capture and restore
includes/class-sanilwb-blueprints-applier.php Layer applier methods