Skip to content

WordPress Reference Architecture

cpx May 25, 2026 9 min read PHP

A practical, layered view of WordPress as a platform, focused on Blocksy child themes as the customization vector. Written for engineers who need to make non-trivial changes to a Blocksy-based site without forking the parent, without breaking updates, and without painting themselves into a corner.


1. Overview

WordPress is a PHP/MySQL CMS organised around three coarse layers — core, plugins, theme — orchestrated by a request lifecycle that fires hundreds of action and filter hooks along the way. Blocksy is a popular Gutenberg-first theme with a deep configuration surface: a Customizer-driven header/footer builder, content-area modules, a custom-properties-based design system, the Blocksy Companion plugin that ships extensions, and an extensive hook API.

A child theme is the WordPress-blessed customization vector — a tiny package that declares Blocksy as its parent and selectively overrides theme.json, templates, assets, and hook callbacks without ever editing the parent. Parent updates ship cleanly, customizations live in version control, and the surface you maintain stays small.


2. Design Principles

PrincipleWhat it means in practice
Hooks over template overridesHooks survive parent updates; template copies need re-syncing on major releases
Configuration over codeUse the Customizer and theme.json before reaching for PHP
Composition over forkingAdd to Blocksy; don’t replace it. If you need to replace large chunks, pick a different parent
One source of truth per tokenA design token (colour, font) lives in either Customizer or theme.json — never both
Version-controlled child, untouched parentParent and plugins are deployable artefacts; only the child theme carries your code
Conditional everythingEnqueue assets, run hooks, register CPTs only where needed
Escape on output, sanitize on inputThe two non-negotiable rules of WordPress PHP

3. The Stack

WordPress sits on a conventional LEMP (or LAMP) stack. The child theme operates at the application layer but its decisions reach down (database queries, asset bytes) and up (caching, edge).

LayerComponentWhat lives here
EdgeCloudflare / CDN / WAFTLS termination, DDoS, edge caching
Web serverNginx or ApacheStatic assets, reverse proxy to PHP-FPM
App serverPHP-FPMWordPress execution
WP Corewp-includes, wp-adminLoader, query engine, rewrite, options API, hooks
MU-pluginswp-content/mu-pluginsAlways-on, can’t be disabled from the dashboard
Pluginswp-content/pluginsIncluding Blocksy Companion
Parent themewp-content/themes/blocksyTemplates, hooks, design system, Customizer panels
Child themewp-content/themes/blocksy-childYour overrides
Object cacheRedis / MemcachedPersistent options, transients, query cache
DatabaseMySQL / MariaDBPosts, options, terms, meta
StorageLocal FS or S3-compatibleuploads/, media

4. Request Lifecycle — Where the Child Theme Intercepts

A typical page render flows through:

  1. Web server routes to PHP-FPM
  2. index.phpwp-blog-header.phpwp-load.phpwp-config.phpwp-settings.php
  3. MU-plugins load, then active plugins load
  4. Parent theme functions.php loads, then child theme functions.php loads
  5. after_setup_themeinitwp_loaded
  6. Request parsing — parse_requestparse_querypre_get_posts → main query
  7. template_redirecttemplate_include — template resolution
  8. Render — wp_head, header, content (blocks/templates), footer, wp_footer
  9. Shutdown, response sent

The child theme can attach behaviour at any of these stages. The key intercept points:

StageHookUse for
Theme setupafter_setup_themeadd_theme_support, image sizes, nav menus
Asset registrationwp_enqueue_scriptsStylesheets and scripts (front-end)
Editor assetsenqueue_block_editor_assetsEditor-side styling and scripts
Query shapingpre_get_postsModify main query before it runs
Template choicetemplate_includeForce a template for a given request
Render hooksblocksy:*, wp_head, wp_footer, content filtersInject markup, modify output
ShutdownshutdownLogging, cache warming

5. Blocksy at a Glance

What the parent gives you out of the box:

CapabilityWhere it lives
Header builderCustomizer → Header
Footer builderCustomizer → Footer
Content area design controlsCustomizer → per content type (single, archive, page, WooCommerce)
Design tokensInline <style> from Customizer + theme.json
Blocksy Companion pluginExtensions (Sticky Header, Trending, Cookies Consent, Demo Install, etc.)
Hook APIblocksy:* action and filter prefix
WooCommerce integrationDedicated templates and Customizer panels
Pro featuresMega Menu, Local Google Fonts, Conditional Headers, Advanced Hooks, White Label

Worth knowing: Blocksy is hybrid — not full-site-editing in the strict sense. Header, footer, and loops are Blocksy PHP renderers driven by Customizer settings; post content uses the block editor. Block templates work as overrides but are not the primary configuration surface. If you want a strictly FSE workflow, pick a strictly FSE parent.


6. Child Theme Anatomy

6.1 Minimum Viable Child

blocksy-child/
├── style.css        ← required, with Template: blocksy header
└── functions.php    ← enqueue parent + child styles

style.css header:

css

/*
Theme Name: My Blocksy Child
Template: blocksy
Version: 1.0.0
Text Domain: blocksy-child
*/

functions.php minimum:

php

<?php
defined('ABSPATH') || exit;

add_action('wp_enqueue_scripts', function () {
    wp_enqueue_style(
        'blocksy-parent',
        get_template_directory_uri() . '/style.css'
    );
    wp_enqueue_style(
        'blocksy-child',
        get_stylesheet_uri(),
        ['blocksy-parent'],
        wp_get_theme()->get('Version')
    );
});
blocksy-child/
├── style.css              ← theme header + a couple of resets
├── functions.php          ← bootstraps include files only
├── theme.json             ← design token overrides
├── screenshot.png         ← 1200×900, for the Themes screen
├── inc/
│   ├── enqueue.php        ← asset registration
│   ├── hooks.php          ← action/filter callbacks
│   ├── shortcodes.php
│   ├── cpt.php            ← custom post types & taxonomies
│   └── customizer.php     ← child-specific Customizer additions
├── templates/             ← FSE block template overrides
│   └── single.html
├── parts/                 ← block template parts
├── patterns/              ← reusable block patterns
├── woocommerce/           ← WooCommerce template overrides
└── assets/
    ├── css/
    ├── js/
    ├── fonts/
    └── images/

functions.php loader pattern:

php

<?php
defined('ABSPATH') || exit;

foreach (['enqueue', 'hooks', 'shortcodes', 'cpt', 'customizer'] as $f) {
    require_once get_stylesheet_directory() . "/inc/{$f}.php";
}

7. Customization Vectors — Decision Matrix

The single most useful table in this document. When you want to change something, this is the lookup.

GoalBest vectorNotes
Change a colour or font tokentheme.json or Customizer → Colors/Typographytheme.json wins for block editor parity
Set defaults on a block (e.g. all Buttons rounded)theme.json styles.blocks.core/buttonSurvives editor edits as defaults
Add a section after the headeradd_action('blocksy:header:after', ...)Blocksy hook
Add a section before the post titleadd_action('blocksy:single:title:before', ...)
Change archive card layoutCustomizer → Archive → Card TypeOften no code needed
Override a single templatetemplates/single.html (block) or PHP copyTry the hook first
Override WooCommerce single productwoocommerce/single-product.phpStandard WC override path
Register a custom post typeinc/cpt.php with register_post_type
Add a custom blockblock.json + register_block_typeHeavier; consider ACF Blocks for content-team UX
Add a block patternpatterns/my-pattern.phpAuto-discovered
Modify rendered HTMLFilter (the_content, blocksy:*)Don’t break nested structure
Conditional logic per pageis_singular(), is_archive(), etc. inside hooks
Brand the adminCompanion → White Label (Pro)

8. The Hook System

WordPress’s plugin API splits into actions (do something at a point) and filters (modify a value passing through a point). Blocksy adds its own prefix-namespaced hooks; combined with core hooks, they cover most customization without template overrides.

8.1 Notable Blocksy Action Hooks

HookFires
blocksy:header:before / :afterAround the header
blocksy:footer:before / :afterAround the footer
blocksy:content:top / :bottomAround the main content area
blocksy:single:before / :afterAround single post/page content
blocksy:single:title:before / :afterAround the post title
blocksy:single:content:top / :bottomInside the content wrapper
blocksy:loop:posts:before / :afterAround the loop on archives
blocksy:archive:cards:title:before / :afterAround archive card titles
blocksy:woocommerce:product-single:beforeWooCommerce hooks

8.2 Pattern — Adding a Pre-Header Notice

php

// inc/hooks.php
add_action('blocksy:header:before', function () {
    if (!is_front_page()) {
        return;
    }
    echo '<div class="pre-header-notice">'
       . esc_html__('Free shipping over €50', 'blocksy-child')
       . '</div>';
});

8.3 Pro Advanced Hooks

Blocksy’s Pro Advanced Hooks extension lets non-developers attach content (HTML, shortcodes, blocks) to hooks via the admin. Useful for content teams; for engineering work prefer code in inc/hooks.php under version control so it ships through CI.


9. theme.json — The Design System

theme.json is the modern declarative way to configure the block editor’s design system. Resolution hierarchy:

LayerWins overSource
User Global StylesAll belowSaved via Site Editor
Child theme.jsonParent + coreYour repo
Parent theme.jsonCore defaultsBlocksy’s theme.json
WordPress coreNothingwp-includes/theme.json

Minimal child override:

json

{
  "$schema": "https://schemas.wp.org/trunk/theme.json",
  "version": 2,
  "settings": {
    "color": {
      "palette": [
        { "slug": "primary", "name": "Primary", "color": "#003594" },
        { "slug": "accent",  "name": "Accent",  "color": "#E4002B" }
      ]
    }
  },
  "styles": {
    "blocks": {
      "core/button": {
        "border": { "radius": "4px" }
      }
    }
  }
}

Caveat about Blocksy specifically. Blocksy also exposes design tokens via its Customizer and emits inline CSS custom properties (--theme-palette-color-1, --theme-font-family, etc.). For Blocksy-controlled regions (header, footer, loops) Customizer settings often win; for block content theme.json wins. Choose one source per token and stick to it — mixing leads to spec-by-debugger.


10. Template Hierarchy and Overrides

Simplified resolution for a single post:

single-{post-type}-{slug}.php
  → single-{post-type}.php
    → single.php
      → singular.php
        → index.php

With block templates, parallel templates/*.html resolution runs first.

Override discipline:

  1. Copy the parent template into the child
  2. Comment the parent version you copied from
  3. Diff and re-copy on major Blocksy releases
  4. Prefer hooks where a hook gives the same surface

WooCommerce overrides follow the same path: copy from wp-content/plugins/woocommerce/templates/ into your child’s woocommerce/ directory.


11. Asset Pipeline

AssetMechanism
Front-end stylesheetwp_enqueue_style in wp_enqueue_scripts
Front-end scriptwp_enqueue_script with dependencies, in_footer => true
Editor styleenqueue_block_editor_assets
Per-block stylewp_enqueue_block_style (WP 6.1+)
Fonttheme.json settings.typography.fontFamilies (preferred) or wp_enqueue_style

Versioning for cache busting:

php

wp_enqueue_style(
    'blocksy-child-main',
    get_stylesheet_directory_uri() . '/assets/css/main.css',
    [],
    filemtime(get_stylesheet_directory() . '/assets/css/main.css')
);

Build toolchain. For non-trivial themes use @wordpress/scripts — it’s the official path, aligns with block.json toolchains, and ships sensible defaults for Webpack, Babel, ESLint, Stylelint, and Jest. Vite is workable but requires more glue.


12. Performance

ConcernMitigation
Render-blocking CSSInline critical CSS, defer the rest
Unused Blocksy modulesCustomizer → Performance → disable what you don’t use
Heavy fontsHost locally via theme.json fontFace; use font-display: swap
Plugin CSS bloatConditional dequeue on routes that don’t need it
Image weightwp_get_attachment_image with srcset, WebP/AVIF, lazy-loading (default in modern WP)
Object cache missRedis via Object Cache Pro or Redis Object Cache
Page cacheServer-side (Nginx fastcgi_cache) or plugin (LiteSpeed, WP Rocket, Cache Enabler)
Query bloatpre_get_posts to limit fields, disable un-needed queries on the front page
HTTP/2 push or 103 Early HintsEdge or origin headers; preload critical assets

13. Security

ConcernMitigation in the child theme
Output XSSesc_html(), esc_attr(), esc_url(), wp_kses_post()
Input sanitizationsanitize_text_field, sanitize_email, sanitize_textarea_field, etc.
Formswp_nonce_field and check_admin_referer
Capability checkscurrent_user_can('edit_posts') before sensitive operations
Direct file access`defined(‘ABSPATH’)
SecretsNever in style.css or theme.json — use wp-config.php constants or environment variables
Dashboard file editingdefine('DISALLOW_FILE_EDIT', true); in wp-config.php
Auto-updatesAuto-update WP minor; plugins/themes on a schedule with a staging gate
HeadersCSP, X-Frame-Options, X-Content-Type-Options at the web-server layer
User enumerationBlock ?author=N redirects, disable XML-RPC if not used

14. Development and Deployment

ConcernPractice
Local devLocalWP, DDEV, or docker-compose
Version controlGit on the child theme; Bedrock / Composer for managing core and plugins
MigrationsWP-CLI for db/options moves; All-in-One WP Migration for ad-hoc
StagingA separate host with prod-data refresh on schedule
CIPHPCS (WordPress-Extra), Stylelint, ESLint, optional Playwright for visual regression
DeploymentGit pull / rsync / CI to prod; never edit theme files through the dashboard editor
Secretswp-config.php constants from env vars; never in the theme
BackupDatabase + uploads/ + child theme repo — the other directories are reproducible

15. Where to Draw Lines

Don’tBecause
Edit the parent theme directlyLost on update; ditto for plugins
Put functions in style.cssIt’s a stylesheet, not a loader
Add hundreds of options to Customizer in the childCustomizer is for site config, not per-page content — use ACF or CPTs
Re-implement what Blocksy already gives youHeader builder, footer builder, archive layouts — use them
Override a template when a hook will doHooks survive parent updates; template copies need re-syncing
Bundle every page’s CSS into one fileConditional enqueue per route is faster
Use <?php ?> in theme.jsonIt’s static JSON; for dynamic values use the wp_theme_json_data_theme filter
Inline JavaScript with <script> tags in PHP templatesRegister and enqueue properly so caching, async, and CSP work

16. Architectural Diagram

Wordpress Blocksy Reference Architecture
WordPress Blocksy Reference Architecture


17. Further Reading

  • WordPress Developer Resources — Theme Handbook and Block Editor Handbook
  • Blocksy documentation — creativethemes.com/blocksy/docs
  • theme.json reference — Block Editor Handbook → Reference Guides
  • WP-CLI handbook — wp-cli.org/
  • Plugin API reference — developer.wordpress.org/plugins/hooks/

Reference architecture, May 2026. Verify version-specific behaviour against the WordPress core, Blocksy, and Blocksy Companion versions in your environment.

0 0 votes
Article Rating
guest

0 Comments
Oldest
Newest Most Voted
0
Would love your thoughts, please comment.x
()
x