ChangelogChangelog

Changelog

Release history for TAW Theme and the taw/core framework package.

2026-06-16Docs update
docs

Docs — June 2026 (2)

New: Framework and Dump helpers

  • TAW\Helpers\Framework — documented the path/URL resolver helpers (path(), url(), themePath(), themeUrl()) that were present in the taw/core README but missing from the docs.
  • TAW\Helpers\Dump — documented the debug utility helpers (Dump::dd(), Dump::log()), also missing from the docs.

Blocks

  • getData(int|false) 404 note — added explanation that getData() receives int|false because get_the_ID() returns false on 404 pages, and that all MetaBlock convenience helpers handle false safely.
2026-06-11Docs update
docs

Docs — June 2026

Options page

  • OptionsPage field types expanded — per the authoritative taw/core README, OptionsPage now supports the same field types as Metabox (all types, including files, group, post_select, repeater, and datepicker). The previous explicit subset list has been replaced with the correct statement.
2026-06-10Docs update
docs

Docs — June 2026

Visual Editor

  • Visual Editor documented — the Visual Editor (TAW\Core\Editor\VisualEditor) is now opt-in and production-ready. Enable it by calling VisualEditor::enable() before Theme::boot() in functions.php. The new Visual Editor section covers automatic behaviour, template annotations (Editor::field(), Editor::attrs()), and the save endpoint.
  • Updated theme boot callout — removed the "not ready for production" warning from the Theme boot page; replaced with a note pointing to the Visual Editor API.

REST API

  • Visual editor endpoints documentedPOST /taw/v1/visual-editor/save and GET /taw/v1/visual-editor/fields are now listed in the REST API endpoint table.

Options page

  • Removed files from supported field typesfiles is not supported in OptionsPage (only in Metabox). Corrected the supported-types list to match the authoritative README.
2026-06-05taw/core v1.15.52
stable

taw/core v1.15.52 — June 2026

Block system

  • MetaBlock::variations() static method — block variations are now declared by overriding public static function variations(): array and returning an array of string suffixes ('' = default variation). The previous constructor-based parent::__construct(['variations' => [...]]) approach is replaced.

Asset pipeline

  • ViteLoader::inlineCriticalCss(string $path) — inline critical CSS directly into <head> from any path relative to the Vite asset root. Use this to manage critical CSS loading from code rather than relying solely on the automatic critical.scss detection.
  • ViteLoader::preloadAssets(array $paths) — add modulepreload hints for JS chunks to improve first-load parse performance.

Theme boot

  • Theme::boot() accepts optional config array — pass ['performance' => [...]] directly to Theme::boot() as a shorthand for calling Theme::performance([...]) as a separate step. Both patterns remain supported.
2026-06-05taw/core v1.15 · TAW Theme update
stable

taw/core v1.15 · TAW Theme — June 2026

Asset pipeline

  • ViteLoader OOP APITAW\Support\ViteLoader is now the authoritative way to interact with Vite assets. New static methods: ViteLoader::assetUrl(), ViteLoader::isDevServerRunning(), ViteLoader::enqueueAsset(), and ViteLoader::init().
  • Legacy procedural helpers removed from autoloadvite_asset_url() and vite_is_dev() are no longer in the Composer files autoload and are not available globally. Use ViteLoader instead.
  • SCSS block asset priority — when a block has both style.scss and style.css, SCSS now takes priority.

Form system

  • Form::register() + Form::display() — forms are now registered statically via Form::register() inside boot() and displayed in templates with Form::display('id'). The old new Form() + $form->render() pattern has been replaced.
  • New input field types: radio (with options and layout), checkbox_group (stored as comma-separated string), date (with min_date and max_date).
  • Structural field types: heading, divider, and html — cosmetic fields for layout and copy inside a form with no submission data.
  • AND / OR conditional logicconditions now supports 'relation' => 'any' for OR logic. The old flat-array AND format is still fully supported.
  • Multi-step forms — replace the top-level fields key with steps. Each step has a title and its own fields array. Includes a numbered step indicator, per-step client-side validation, and automatic navigation to the failing step on server error.
  • SubmissionsHandler auto-wiredTheme::boot() now registers SubmissionsHandler automatically; manual instantiation is no longer needed.

Metabox engine

  • datepicker field type — jQuery UI date picker; stored as a date string (YYYY-MM-DD default). Supports date_format, min_date, and max_date options.
  • Repeater layout option — repeater rows can now render as tabbed_horizontal or tabbed_vertical in addition to the default accordion.
  • screens key (plural) — the Metabox config option is now screens (accepts an array of post types, page slugs, or page template filenames). The singular screen is no longer used.

Transactional email

  • Template path updated — pre-compiled HTML templates now live at mails/html/{name}.html. MJML source files remain at mails/{name}.mjml for dev-time compilation.
  • MailTester registration — register manually with (new \TAW\Core\Mail\MailTester())->register() in functions.php.

Block system

  • defaultData() method — UI Blocks now use defaultData() instead of defaults() to define prop fallbacks.
  • getData(int|false $postId)MetaBlock::getData() now accepts int|false so blocks return safe empty values on 404 pages.
  • boot() for all blocksBlockLoader now calls boot() on every block type (not just UI Blocks) during discovery.
  • MenuItem::target() — new method returning '_self' or '_blank'.
  • MenuItem::isActiveAncestor() — new method; isInActiveTrail() now means any of active/activeParent/activeAncestor is true.
  • MenuItem::wpPost() — new method returning the raw WP_Post menu item object.

TAW Theme

  • ThemeUpdater re-introduced via taw/coreTAW\Core\ThemeUpdater is available again for GitHub Releases-based auto-updates. Instantiate it in functions.php.
  • CSS Studio toggle — CSS Studio is now activated via WP Admin → TAW Settings → Developer Tools → Enable CSS Studio (previously auto-activated when the Vite dev server was running).
  • Image::render() signature — the $alt parameter has been removed. Pass options (including class, sizes, above_fold, attr) as the third argument directly.
  • Image::preloadTag() — renamed from preload_tag() to camelCase preloadTag().
2026-04-14taw/core v1.14 · TAW Theme update
stable

taw/core v1.14 · TAW Theme — April 2026

Metabox engine

  • files field type — new multi-file picker with drag-to-reorder. Stores an array of attachment IDs. Accepts limit to cap the number of selectable files.
  • Nested repeaters — repeater fields now fully support nesting: place a repeater inside another repeater's fields array for hierarchical data structures up to three levels deep. Serialization is pre-submit and handles re-entrant calls safely.
  • JSON encoding — all repeater data is now serialized with full Unicode support.
  • postMatchesTemplate — new method on Metabox for template matching; screen now accepts multiple post types (comma-separated or array).
  • Repeater template tag — internally switched from <script> to <template> for repeater row prototypes (better browser compatibility).
  • jQuery selector optimization — repeater element selectors are scoped for improved performance on pages with multiple repeaters.

Block system

  • Block variationsMetaBlock now accepts a variations array in its constructor to declare WordPress block variations. Asset handles are automatically namespaced per variation.
  • BlockLoader::boot() for plain blocks — when BlockLoader loads a UI Block (extending Block), it now calls the block's boot() method if one exists. Use it for one-time setup such as registering hooks.

REST API

  • post_select page handlingSearchEndpoints now properly validates the page post type and handles the WordPress special case automatically.

TAW Theme

  • ThemeUpdater removed — the ThemeUpdater class has been removed from TAW Theme. Use composer update taw/core to update the framework.
  • SearchEndpoints cleaned up — removed the theme-level override; the endpoint is now served exclusively by taw/core.
  • Hero block — added content (wysiwyg) field. Added a three-level nested_repeater field as a reference implementation for hierarchical repeater data.
  • CSS Studio — added as a dev-only dependency. Activated automatically when vite_is_dev() is true; never shipped to production.
  • PerformanceTheme::performance() now schedules its work on after_setup_theme for better WordPress filter compatibility.
2026-03-19Initial release
stable

v1.0.0 — Initial release

TAW Theme and taw/core v1.0.0 are the first stable release of the framework. Everything below ships out of the box when you run composer create-project taw/theme.

Block system

  • Auto-discovery — drop a class and a template inside Blocks/ and TAW finds it automatically. No registration step, no functions.php edits required.
  • MetaBlock — page sections backed by metabox data. Extend TAW\Core\MetaBlock, define fields in registerMetaboxes(), return template vars from getData().
  • Block (UI Block) — stateless components that receive props at render time. Extend TAW\Core\Block and define a defaults() array. Missing props always fall back safely.
  • Block nesting — UI Blocks compose naturally inside MetaBlock templates via (new Button())->render([...]).
  • Subgroup organisation — blocks can live in nested folders (Blocks/sections/Hero/) for large projects.
  • BlockRegistry::queue() / ::render() — queue a block's assets before get_header(), render it anywhere in the template.

CLI scaffolding (bin/taw)

Powered by Symfony Console, shipped inside taw/core.

  • make:block Name --type=meta|ui — scaffold a MetaBlock or UI Block with the correct class stub and template.
  • --with-style — include a style.scss wired into the Vite pipeline.
  • --with-script — include a script.js loaded as an ES module in the footer.
  • --group=sections — place the block inside a subgroup folder.
  • --force — overwrite an existing block.
  • export:block Name — export any block as a portable ZIP file.
  • import:block path.zip — import a block from a ZIP into the Blocks/ directory.

Metabox engine

Config-driven metaboxes with no plugin dependencies. All field types render, validate, sanitize, and save through TAW\Core\Metabox\Metabox.

Supported field types: text, textarea, wysiwyg, url, number, range, select, checkbox, color, image, files, group, repeater, post_select

  • Conditional logic — show or hide fields based on other field values. Evaluated live in the admin with Alpine.js and server-side on save. Operators: ==, !=, contains, empty, !empty.
  • Tabbed layouts — group fields into tabs using the tabs key; each tab references field IDs from the fields array.
  • Responsive grid — control field width with the width option (e.g. '50' for two-column).
  • show_on callable — conditionally hide an entire metabox per post.
  • Retrieval helpersMetabox::get(), ::get_bool(), ::get_image_url(), ::get_color(), ::get_posts(), ::get_repeater() cover every field type.

Options page

  • TAW\Core\OptionsPage — site-wide settings stored in wp_options using the same field config as metaboxes.
  • Supports tabbed layouts, validation, and all field types except repeater and group.
  • Retrieval via OptionsPage::get() and OptionsPage::get_image_url().

Forms

  • TAW\Core\Form\Form — config-driven frontend forms with CSRF (nonces), honeypot spam protection, field validation, and PRG redirect after success.
  • Supports text, email, textarea, select, and any standard HTML input type.
  • Sends dual emails (to-self and to-client) via Mailer when templates are configured; falls back to plain-text wp_mail() otherwise.
  • TAW\Core\Form\SubmissionsHandler — stores successful submissions as a taw_submission CPT in WP Admin.
  • Optional webhook forwarding (n8n, Zapier, Make, etc.) with HMAC-signed payloads. Configure endpoint and secret under Settings → Form Webhook.

Transactional email

  • TAW\Core\Mail\Mailer — fluent wrapper around wp_mail() with a to(), subject(), template(), setVariables(), send() chain.
  • TAW\Core\Mail\MailTemplate — resolves templates from mails/html/{name}.html (production) or mails/{name}.mjml (dev, compiled via spatie/mjml-php). Uses {{variable}} placeholder syntax.
  • TAW\Core\Mail\MailTester — admin page under Tools → Test Emails for sending test emails against any compiled template without a real form submission.
  • TAW\Core\Menu\Menu — typed wrapper around WordPress nav menus. Load by location slug with Menu::get('primary').
  • TAW\Core\Menu\MenuItem — exposes title(), url(), openInNewTab(), hasChildren(), children(), isActive(), isInActiveTrail(), classes(), and more. WP auto-classes are filtered out by default.

Asset pipeline

  • Per-block assetsstyle.scss (or style.css) and script.js inside any block folder are auto-detected and auto-enqueued only on pages that use that block.
  • Critical CSSresources/scss/critical.scss is compiled and inlined in <head> to eliminate a render-blocking network round-trip for above-fold styles.
  • Async CSSapp.css / app.scss are loaded non-render-blocking via media="print" + onload swap.
  • ES module JS — block scripts and the main app.js are loaded as type="module".
  • Content-hashed filenames — all production assets are cache-busted automatically.
  • vite_asset_url($path) / vite_is_dev() — global helpers available anywhere in your templates.
  • Tailwind CSS v4 via @tailwindcss/vite. Alpine.js v3 for interactivity.

Performance

Theme::performance([...]) (forwarded to TAW\Core\Support\Performance) supports:

  • remove_bloat — strips unnecessary WordPress front-end scripts, styles, and features.
  • remove_emoji — disables WordPress emoji detection scripts.
  • remove_meta_tags — removes default WordPress generator and discovery meta tags.
  • remove_oembed — disables oEmbed support and associated scripts.
  • preconnect_origins — emits <link rel="preconnect"> hints for external origins.
  • preload_fonts — preloads self-hosted WOFF2 font files resolved via ViteLoader.
  • preload_images — emits <link rel="preload"> for above-fold images by attachment ID and size.

Image helper

  • TAW\Helpers\Image::render($id, $size, $alt, $options) — generates <img> with correct loading, fetchpriority, decoding, srcset, and sizes attributes. Pass ['above_fold' => true] for hero images.
  • TAW\Helpers\Image::preload_tag($id, $size) — generates a <link rel="preload"> tag for your single most important image.

SVG support

  • TAW\Helpers\Svg::register() — enables sanitized SVG uploads in WordPress (called automatically by Theme::boot()).
  • Svg::render($id, $alt, $options) — renders a sanitized <img> tag.
  • Svg::inline($id, $options) — outputs inline SVG markup for CSS/animation targeting.
  • Svg::url($id) — returns the URL for a stored SVG attachment.

REST API

  • GET /wp-json/taw/v1/search-posts — powers the post_select metabox field. Supports s, post_type, per_page, and exclude parameters. Requires edit_posts capability.

Theme updater

  • TAW\Core\Theme\ThemeUpdaterremoved in a later release hooked into the WordPress update system to check a GitHub Releases URL for new versions. Shows the standard Update Available notice in admin. Updates are cached for 6 hours. Deprecated — see the v1.14 entry below.

Boot process

  • TAW\Core\Theme::boot() — single entrypoint that wires block loading, Vite assets, REST endpoints, and SVG support into WordPress hooks.
  • TAW\Core\Theme::performance([...]) — configures performance behavior after boot.