From 3db11a40d0eedff8a85f0abf96101818f711f136 Mon Sep 17 00:00:00 2001 From: Olivier Gorzalka Date: Mon, 28 Sep 2026 16:04:41 +0200 Subject: [PATCH] docs(skill): teach in Blade block templates The framework (after v13.32.0-beta.8) lets a render.blade.php write : the inner blocks are edited in place in the editor and printed in the tag's wrapper on the page. Generated dynamic blocks use the editor runtime window.pollora.blocks (bladeEdit, save) instead of ServerSideRender and () => null. The skill said to use ServerSideRender. --- resources/boost/guidelines/core.blade.php | 2 +- .../boost/skills/pollora-blocks/SKILL.md | 61 ++++++++++++------- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/resources/boost/guidelines/core.blade.php b/resources/boost/guidelines/core.blade.php index b288700..15af43a 100644 --- a/resources/boost/guidelines/core.blade.php +++ b/resources/boost/guidelines/core.blade.php @@ -104,7 +104,7 @@ class InternalHelper {} - **WordPress objects** (`WP_Post`, `WP_Query`, `WP_User`) are auto-injected via type hints in controller methods - **Facades**: `Action`, `Filter`, `Ajax`, `Asset`, `Theme`, `PostType`, `Taxonomy`, `Option`, `Ability`, `PostQuery`, `MetaQuery`, `TaxQuery`, `Mail`, `Constant`. There is no `Loop` or `Query` facade: use Sage Directives in Blade, WordPress functions in PHP - **Translations**: `__('Text', 'my-domain')` goes to WordPress's catalogues; `__('key', ['name' => $x])` goes to Laravel; `__('Text')` tries Laravel, then WordPress's `default` domain -- **Blocks**: live in `resources/views/blocks/{slug}`, render with `render.blade.php` by default, and are registered by Pollora — never write a `BlocksServiceProvider` +- **Blocks**: live in `resources/views/blocks/{slug}`, render with `render.blade.php` by default, and are registered by Pollora — never write a `BlocksServiceProvider`; `` in `render.blade.php` marks where inner blocks go, edited in place in the editor (see the `pollora-blocks` skill) - **Which template answered?** With `WP_DEBUG` on, every page carries `` (hierarchy responses only, not `Route::wp()` or Laravel routes) - **CSRF**: WordPress endpoints are excluded from Laravel CSRF — WordPress uses its own nonce system - **Modules**: Use `nwidart/laravel-modules` for large projects — discovery works inside modules automatically diff --git a/resources/boost/skills/pollora-blocks/SKILL.md b/resources/boost/skills/pollora-blocks/SKILL.md index b7b45b6..e49c795 100644 --- a/resources/boost/skills/pollora-blocks/SKILL.md +++ b/resources/boost/skills/pollora-blocks/SKILL.md @@ -18,7 +18,7 @@ Options: - `--theme[=NAME]` — Create in a theme (default: the active theme) - `--plugin=NAME` — Create in a plugin - `--static` — A static block saved in `post_content` (`save.jsx`, no `render.blade.php`) -- `--inner-blocks` — Add InnerBlocks support +- `--inner-blocks` — Add inner blocks: `` in `render.blade.php` (Gutenberg's `InnerBlocks` in `edit.jsx`/`save.jsx` with `--static`) - `--namespace=NS`, `--title=TITLE`, `--category=CAT`, `--icon=ICON`, `--no-view-script`, `--force` - `--dynamic` is deprecated: blocks are dynamic by default @@ -69,30 +69,28 @@ Blocks are **dynamic by default**: `render.blade.php` renders them on each reque } ``` -## Editor Component (edit.jsx) +## Editor Component (edit.jsx) and save -For a dynamic block, the editor should show what the page shows: render the same markup (or use `ServerSideRender`). +A generated dynamic block is edited through the framework's editor runtime, `window.pollora.blocks`, which Pollora loads with every block that has a `render` template (handle `pollora-block-editor`). Nothing to install or import: ```jsx -import { useBlockProps, RichText } from '@wordpress/block-editor'; - -export default function Edit({ attributes, setAttributes }) { - return ( -
- setAttributes({ heading })} - placeholder="Enter heading..." - /> -
- ); -} +// edit.jsx +import metadata from './block.json'; + +export default window.pollora.blocks.bladeEdit(metadata); + +// index.jsx +registerBlockType(metadata.name, { + edit: Edit, + save: window.pollora.blocks.save, // stores the inner blocks, nothing else +}); ``` +`bladeEdit` previews `render.blade.php` through the core block-renderer REST route (again 200 ms after an attribute change) and makes its `` editable in place. Framework v13.32.0-beta.8 and earlier generate `ServerSideRender` and `save: () => null` instead — check `edit.jsx` before assuming. + ## Rendering with Blade (render.blade.php) -The template receives `$attributes` (array), `$content` (inner blocks HTML) and `$block` (`WP_Block`). Blade components work as in any view. +The template receives `$attributes` (array), `$content` (inner blocks HTML), `$block` (`WP_Block`) and `$isPreview` (true while it renders for the editor's preview). Blade components work as in any view. ```blade
'py-16']) !!}> @@ -100,14 +98,35 @@ The template receives `$attributes` (array), `$content` (inner blocks HTML) and {{ $attributes['ctaText'] ?? '' }} - {!! $content !!}
``` - `{{ }}` escapes; use `{!! !!}` only for `get_block_wrapper_attributes()` and `$content`. - For URLs use `esc_url_raw()` inside `{{ }}` — `esc_url()` would be encoded twice. - The render file must stay inside the block directory, or the block renders nothing and a warning is logged. -- A plain `render.php` still works. +- A plain `render.php` still works, with the same variables. + +## Inner Blocks: `` + +Write `` in the template where the inner blocks go (ACF-style). In the editor they are edited right there; on the page they replace the tag, inside a `div` with the tag's `class` (default `pollora-inner-blocks`) — the same `div` the editor renders. + +```blade +
'card']) !!}> +

{{ $attributes['title'] ?? '' }}

+ +
+``` + +- Options are Gutenberg's inner blocks options as attributes: `allowedBlocks`, `template`, `templateLock`, `orientation`, `defaultBlock`, `directInsert`… JSON for arrays/objects (write it with `{{ json_encode(...) }}`, which escapes quotes and `>`), `"true"`/`"false"` for booleans. +- One list per block: only the first tag gets the inner blocks; further tags are dropped. +- The inner blocks are saved in `post_content`; the rest of the block is not, so template changes reach existing blocks. +- In the preview, `$content` is empty and the tag stays for the editor; `