Introduction to Block-Based Architectures
Zero CMS features an extremely powerful, high-contrast, zero-dependency Page Builder Block System. Pages are stored in the database as serialized JSON blocks (under the content field). To build an active, beautiful block inside the CMS, you need to configure its Frontend View Template (to render the block beautifully on the public website) and register it in the Core Block Registry (which automatically generates admin edit fields, handles inserting drawers, and serializes inputs generically!).
Step 1: Create the Frontend View Template
Frontend blocks are resolved dynamically by the theme template renderer. To add a block template named accordion, create a new PHP file at src/Views/themes/default/blocks/accordion.php. This template receives a local $block array data context populated with fields:
<?php
// src/Views/themes/default/blocks/accordion.php
$items = $block['items'] ?? [];
?>
<div class="block-accordion">
<?php if (!empty($block['title'])): ?>
<h3><?php echo htmlspecialchars($block['title']); ?></h3>
<?php endif; ?>
<div class="accordion-list">
<?php foreach ($items as $item): ?>
<div class="accordion-item">
<div class="accordion-trigger"><?php echo htmlspecialchars($item['title'] ?? ''); ?></div>
<div class="accordion-panel"><?php echo htmlspecialchars($item['content'] ?? ''); ?></div>
</div>
<?php endforeach; ?>
</div>
</div>Step 2: Create the Admin Edit Fields View Template
Create a self-contained PHP file representing the administrative edit fields for the block at src/Modules/Admin/Views/blocks/accordion.php. This template is automatically included and pre-rendered inside the admin page builder blocks list. Use convention-based input classes to enable automatic serialization:
<div class="field-group">
<label>Block Title</label>
<input type="text" class="block-title-input" value="<?php echo htmlspecialchars($blockTitle); ?>">
</div>
<div class="field-group">
<label>Accordion Items</label>
<div class="accordion-items-list">
<!-- Dynamic items rows -->
</div>
<button type="button" class="btn-add-accordion-item">+ Add Accordion Item</button>
</div>Step 3: Register the Block in the Core App
Register your block dynamically inside the core App::bootstrap() method (or inside any bootstrapper/module initialization) by calling App::registerBlock():
// Inside src/Core/App.php
self::registerBlock('accordion', [
'label' => 'Accordion FAQ List',
'description' => 'A sleek list of expandable/collapsible questions and answers.',
'icon' => 'file'
]);This single registration completely takes care of generating card options in the Block Inserter modal drawer, injecting templates inside the builder container, and serializing complex input arrays into the database payload dynamically on the fly!