Quickstart
Install TAW Theme, start the Vite dev server, scaffold your first MetaBlock, and render it on a page — in under 10 minutes.
Before you start
Make sure your environment meets these requirements:
- WordPress 6.0+
- PHP 8.1+
- Composer 2.0+
- Node.js 20.19+
- npm 8+
TAW does not use Gutenberg blocks or ACF. Blocks are plain PHP classes and templates — no block editor registration needed.
Step 1 — Install the theme
Scaffold a new TAW Theme project
Run this from your WordPress wp-content/themes directory. Replace my-theme with your desired folder name.
cd wp-content/themes
composer create-project taw/theme my-theme \
--repository='{"type":"vcs","url":"https://github.com/Relmaur/taw-theme"}'
This creates the theme folder with the correct structure and pulls in the taw/core framework package.
Install PHP and JS dependencies
cd my-theme
composer install # PHP deps — pulls taw/core
npm install # Frontend dependencies
Start the Vite dev server
npm run dev
Vite starts on port 5173 with hot module reloading. Leave this running while you develop — CSS and JS changes reflect instantly in the browser without a full reload.
Activate the theme in WordPress
- Log in to your WordPress admin.
- Go to Appearance → Themes.
- Find your new theme and click Activate.
Visit the frontend — you should see the TAW Theme layout rendered with Vite-powered assets.
Step 2 — Create your first block
TAW has two block types. For this quickstart we'll build a MetaBlock — a page section backed by metabox fields in the WordPress admin.
Scaffold the block with the CLI
Run the block generator from your theme root:
php bin/taw make:block Hero --type=meta --with-style
composer dump-autoload
This creates Blocks/Hero/ with three files:
Blocks/Hero/
├── Hero.php ← the block class
├── index.php ← the template
└── style.scss ← per-block styles (auto-enqueued)
composer dump-autoload is required after adding any new block class so Composer's PSR-4 classmap picks it up.
Define your metabox fields
Open Blocks/Hero/Hero.php. The CLI generates a skeleton — fill in your fields inside registerMetaboxes() and return the data you need in getData().
<?php
// Blocks/Hero/Hero.php
namespace TAW\Blocks\Hero;
use TAW\Core\Block\MetaBlock;
use TAW\Core\Metabox\Metabox;
class Hero extends MetaBlock
{
protected string $id = 'hero';
protected function registerMetaboxes(): void
{
new Metabox([
'id' => 'taw_hero',
'title' => 'Hero Section',
'screens' => ['page'],
'fields' => [
['id' => 'hero_heading', 'label' => 'Heading', 'type' => 'text', 'required' => true],
['id' => 'hero_subtext', 'label' => 'Subtext', 'type' => 'textarea'],
['id' => 'hero_image', 'label' => 'Image', 'type' => 'image'],
],
]);
}
protected function getData(int|false $postId): array
{
return [
'heading' => $this->getMeta($postId, 'hero_heading'),
'subtext' => $this->getMeta($postId, 'hero_subtext'),
'image_url' => $this->getImageUrl($postId, 'hero_image', 'large'),
];
}
}
TAW discovers the metabox automatically — it appears in the WordPress page editor as soon as the class is loaded.
Write the template
Open Blocks/Hero/index.php. The variables returned by getData() are extracted into the template scope automatically.
<?php
// Blocks/Hero/index.php
if (empty($heading)) return;
?>
<section class="hero">
<h1><?php echo esc_html($heading); ?></h1>
<?php if ($subtext): ?>
<p><?php echo esc_html($subtext); ?></p>
<?php endif; ?>
<?php if ($image_url): ?>
<img src="<?php echo esc_url($image_url); ?>" alt="">
<?php endif; ?>
</section>
Step 3 — Render the block on a page
TAW blocks are not Gutenberg blocks. You queue and render them from your PHP templates.
Queue and render in a WordPress template
Open (or create) front-page.php in your theme root. Queue the block's assets before get_header(), then render it where it should appear in the page.
<?php
// front-page.php
use TAW\Core\Block\BlockRegistry;
BlockRegistry::queue('hero'); // schedules CSS/JS for <head>
get_header();
?>
<?php BlockRegistry::render('hero'); ?>
<?php get_footer(); ?>
TAW automatically passes the current post ID to getData() and extracts the result into the template.
Fill in content in the WordPress admin
- Open a page in the WordPress editor.
- Scroll down — your Hero Section metabox appears below the editor.
- Fill in the Heading, Subtext, and Image fields.
- Publish and visit the page.
You should see your Hero block rendered with the content you entered.
What you just built
BlockLoader::loadAll()(called byTheme::boot()) discoveredBlocks/Hero/Hero.phpautomatically — no registration required.Metaboxrendered the admin UI and saved field values topost_meta.BlockRegistry::queue('hero')scheduledstyle.scssfor<head>— only on pages that use this block.BlockRegistry::render('hero')calledgetData(), extracted the result, and loadedindex.php.
Add a second block type: UI Block
UI Blocks are stateless components that receive props at render time — no metaboxes, no post_meta.
php bin/taw make:block Button --type=ui --with-style
composer dump-autoload
// Blocks/Button/Button.php
namespace TAW\Blocks\Button;
use TAW\Core\Block\Block;
class Button extends Block
{
protected string $id = 'button';
protected function defaultData(): array
{
return [
'text' => '',
'url' => '#',
'style' => 'primary',
];
}
}
Use it inside any template or MetaBlock template:
<?php (new \TAW\Blocks\Button\Button())->render([
'text' => 'Get Started',
'url' => '/contact',
]); ?>
Props are merged over the defaults() array — missing props always have safe fallbacks.
Multi-block pages
Queue multiple blocks at once, then render each where it belongs:
<?php
// front-page.php
use TAW\Core\Block\BlockRegistry;
BlockRegistry::queue('hero', 'features', 'stats', 'testimonials', 'cta');
get_header();
?>
<?php BlockRegistry::render('hero'); ?>
<?php BlockRegistry::render('features'); ?>
<?php BlockRegistry::render('stats'); ?>
<?php BlockRegistry::render('testimonials'); ?>
<?php BlockRegistry::render('cta'); ?>
<?php get_footer(); ?>
Production build
When you're ready to deploy:
npm run build
Vite outputs content-hashed CSS and JS to public/build/. WordPress loads these automatically when the dev server is not running.
Useful CLI commands
| Command | What it does |
|---|---|
php bin/taw make:block Name --type=meta | Scaffold a MetaBlock |
php bin/taw make:block Name --type=ui | Scaffold a UI Block |
php bin/taw make:block Name --group=sections | Scaffold inside Blocks/sections/Name/ |
php bin/taw make:block Name --with-style --with-script | Include style.scss and script.js |
php bin/taw export:block Hero | Export a block as a portable ZIP |
php bin/taw import:block path/to/Hero.zip | Import a block from a ZIP |
composer dump-autoload | Rebuild classmap after adding new block classes |