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
```
- `{{ }}` 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; `