# Layout Builder — Improvement & Growth Plan

> Package: capell-app/layout-builder · Kind: package · Tier: free · Product group: Capell Foundation · Bundle: foundation · Status: Complete

## 1. Snapshot

Layout Builder is the composition engine for Capell: it persists named layout containers and reusable `Widget` records, and resolves them into a query-free public graph for the frontend. It spans three surfaces (`admin`, `frontend`, `console`) and ships 48 Actions (`src/Actions/`), the bulk of the domain logic — public rendering through `BuildPublicLayoutGraphAction` (`src/Actions/BuildPublicLayoutGraphAction.php`, behind the `PublicLayoutGraphBuilder` contract), a Livewire dual-mode editor (`src/Livewire/Filament/LayoutBuilder.php` + four `Concerns/`), layout health diagnostics (`AnalyzeLayoutHealthAction`), reusable presets (`LayoutPreset` model + `SaveLayoutPresetAction`/`ApplyLayoutPresetAction`), encrypted lazy fragments (`Actions/Fragments/RenderPublicFragmentAction.php`), and a deterministic widget visual-regression command. Tables: `layouts` (JSON `containers`), `widgets`, `widget_assets`, `widget_widgets`, `layout_presets` (`database/migrations/2026_05_10_190841_*`). It is consumed by the Frontend package (via the `PublicLayoutGraphBuilder` / `FrontendRuntimeManifestContributor` / `WidgetResourceUsageContributor` tags), themes (`LayoutAreaRegistry`, e.g. Foundation Theme's `header` area), block-library (`BlockRegistry` for diagnostics), and frontend-authoring (editable-region surface). Marketplace `summary` (verbatim): _"Visual layout composition, content-first editing, and public layout rendering for Capell."_ Manifest currently promotes only the extension card after visual audit showed the committed `docs/screenshots/*` captures are broken by a huge black arc/default shell and do not prove a styled Capell surface.

## 2. Improvements (existing functionality)

Prioritized.

1. **Implement a real package health check** — `compatibleCapellApiVersion()` is the _only_ method on the class; the manifest advertises the check as _"package surfaces, providers, and install health are discoverable by Diagnostics"_ with `severity: critical`, but nothing verifies tables exist, the install action ran, the public graph builder is bound, or the editor Livewire component is registered. A critical-severity check that only echoes `'^4.0'` gives false assurance. — `src/Health/LayoutBuilderHealthCheck.php` — **S**

2. **Delete or wire up `CapellLayoutCacheKeyEnum`** — the enum defines `WidgetByKey` and `WidgetOptions` cache key prefixes, but a full-tree grep finds **zero** references outside the enum file itself (no `remember`/`forget` against these keys anywhere in `src/`, `resources/`, `tests/`). Either dead code or an abandoned caching scheme. The live caching path is `LayoutLoader` via `CapellCore::rememberCache` + a request-scoped `$preloaded` array. — `src/Enums/CapellLayoutCacheKeyEnum.php`, `src/Support/Loader/LayoutLoader.php` — **S**

3. **Align `capell.json` dependencies with `composer.json`** — manifest `dependencies.requires` lists only `core` + `frontend`, but composer requires `admin` and `block-library` too (and the code hard-imports `Capell\BlockLibrary\Support\BlockRegistry`, `Capell\Admin\…`). The package's own `docs/overview.md` "Known Risks" already flags this as a pre-publication blocker. Catalog resolution / install ordering will be wrong without it. — `capell.json` (`dependencies.requires`) — **S**

4. **Done/Shipped: Livewire notifications are translated.** Notification titles/bodies in the editor and related Filament helpers now resolve through translation keys rather than inline English, with duplicate preset/save failures using `capell-layout-builder::message.*` copy. A static guard prevents literal `title()`/`body()` notification strings and raw exception messages from being surfaced to editors. — `src/Livewire/Filament/LayoutBuilder.php`, `src/Livewire/Filament/Support/LayoutBuilderActionFactory.php`, `tests/Unit/LayoutBuilderNotificationTranslationTest.php` — **M**

5. **Partially shipped: recaptured and promoted styled admin/editor marketplace screenshots** — the broken default-shell/admin-dashboard captures were replaced with real runner-backed Capell admin PNGs for the widgets index, create widget form, page editor, and layouts index, with light/dark pairs promoted in `marketplace.screenshots[]`. The frontend render target remains open because the prepared app still renders the oversized black wave/artifact called out in the screenshot-quality audit; keep frontend PNGs as runner evidence only until the public theme capture is visually clean. — `capell.json` (`marketplace.screenshots`), `docs/screenshots.json` — **S**

6. **Split the god-Action `BuildLayoutContentInventoryAction` (554 lines)** — by far the largest Action and the backbone of content-first mode. At this size it is hard to test in isolation and hard to extend. Extract container/asset traversal and the per-widget projection into focused collaborators. — `src/Actions/BuildLayoutContentInventoryAction.php` — **M**

7. **Done/Shipped: orphan/uncovered Actions audited.** The behaviorless `ApplyLayoutPlanAction` was removed. The apparent orphan list is otherwise reachable or covered: `PreviewLayoutPlanAction` is the AI/preset preview seam and has preset-match coverage, `SaveFormComponentRelationshipAction` has relationship save/delete coverage, `PersistLayoutBuilderStateAction` is the editor save path, and `InstallPackageAction` remains a public compatibility installer consumed by Blog/Demo Kit setup helpers with package-local coverage now pinning its widget-type/layout setup behavior. `src/Actions/ApplyLayoutPlanAction.php`, `src/Actions/InstallPackageAction.php`, `tests/Unit/LayoutBuilderScaffoldingAndRelationCoverageTest.php` — **M**

8. **Move undo/redo from in-memory to durable** — `LayoutMutationHistory` and `PushLayoutMutationSnapshotAction` keep history in Livewire component state (`MAX_HISTORY_DEPTH = 20`), so it is lost on navigation/refresh and bloats the wire payload (full state snapshot per step). Consider trimming snapshots to diffs and/or persisting to the layout's `admin` JSON for cross-session undo. — `src/Support/LayoutMutationHistory.php`, `src/Actions/Mutations/PushLayoutMutationSnapshotAction.php` — **M**

## 3. Missing Features (gaps)

Capabilities declared: `layout-builder`, `layout-builder-admin`, `layout-builder-content-first`, `layout-builder-public-rendering`. All four are genuinely reachable in production. Gaps against page-builder norms:

- **Done/Shipped: layout templates / starter layouts (differentiator).** Registered layout presets can now be materialized into a complete builder state through `ApplyStarterLayoutPresetAction`, exposed through a translated Livewire starter-gallery UI in the editor, and applied to replace the full builder state. Package-local Action, registry, render, and Livewire mutation coverage pins the current foundation scope. Page-creation shortcuts and paid Layout Pro packaging remain future product depth above this free engine. — table-stakes-plus.
- **Global / synced blocks (differentiator).** `Widget` records are reusable and `widget_widgets` nests them, but editing one instance does not propagate to all placements (no "edit once, update everywhere"). This is a headline feature in WordPress Gutenberg / Webflow and a strong paid upsell. — differentiator.
- **Revision history / restore (table-stakes).** No layout versioning. `LayoutMutationHistory` is per-session undo only; there is no "restore previous published layout." Page builders are expected to have this. — table-stakes.
- **Responsive controls beyond width.** `LayoutBreakpoint` (Desktop/Tablet/Mobile) drives per-breakpoint `colspan` overrides only (`ResizeLayoutContainerAction`). No per-breakpoint visibility on _containers_ (device visibility exists for widgets via `presentation.manage_advanced`), ordering, or spacing. — table-stakes.
- **Accessibility tooling.** `AnalyzeLayoutHealthAction` checks duplicate anchors, too-many-cards, and unsupported variants — but no a11y diagnostics (heading-order, alt-text presence, contrast hints). `HeroWidgetHasPrimaryHeadingAction` hints the appetite exists; generalize it. — differentiator.
- **Drag-drop nested columns.** Containers are a flat keyed map with `colspan`; there is no true nested column/row tree in the layout model (nesting is only widget-in-widget via `widget_widgets`). Deep section→row→column composition is a common expectation. — table-stakes.
- **Block/widget reuse discovery.** `FindReusableWidgetsAction` exists and is wired into the editor (`ManagesLayoutBuilderState`), but it is a thin (20-line) lookup — no usage counts, no "where used" surfaced to editors at insert time. — incremental.

## 4. Issues / Risks

- **Stub critical health check (false signal).** As §2.1 — `severity: critical` health entry backed by a no-op. `src/Health/LayoutBuilderHealthCheck.php`.
- **Dead cache enum.** As §2.2 — unused `CapellLayoutCacheKeyEnum`; risk of a future dev wiring against an abandoned key scheme. `src/Enums/CapellLayoutCacheKeyEnum.php`.
- **Done/Shipped: public render performance budgets are covered with deterministic suite guards.** `PublicLayoutGraphStressTest` now asserts the manifest-driven 50-query graph budget, a zero-query hydrated Blade render, high-volume query scaling, and public metadata leak guards. The former hard 20ms wall-clock assertion was removed because it was not stable under parallel Pest host load; the package manifest still documents the target budget. Normal Blade widgets also avoid opaque fragment-reference encryption unless a lazy fragment, Livewire widget, or fragment interaction needs it. `tests/Integration/PublicLayoutGraphStressTest.php`, `resources/views/components/layout/widget.blade.php`.
- **Cache invalidation correctness unverifiable here.** `performance.cacheSafety.invalidationSources` is `[]` and `cacheable: false`, yet `queueInvalidation: true` and `cacheTags: ["layout-builder"]` are set, and `LayoutLoader` does cache the `Layout` via `CapellCore::rememberCache`. No `CacheInvalidationRegistry::registerDependency()` call exists in the package — invalidation is delegated entirely to core via `LayoutLoaded`/`AfterRecordSaved` listeners and the empty `invalidationSources` is undocumented. Either register the dependency explicitly or document why core owns it. `src/Listeners/`, `src/Support/Loader/LayoutLoader.php`.
- **Public-output safety is tested but narrow.** `LayoutBuilderPublicRenderingSafetyTest.php` asserts the rendered HTML excludes `layoutDiagnostics`, `LayoutFragmentData`, `pageable_type`, `widget_key`, `responsive`, `colspan`, `signed editor` — good. But `PublicLayoutWidgetData` carries `key` (the widget key) and `?string $html`; the safety net depends on the Blade layer never echoing `data.key`/container meta. Lazy fragments are encrypted+revalidated (per `docs/overview.md`) but there is no test asserting a tampered/replayed `_fragments/{reference}` returns a generic 404. `src/Data/PublicLayoutWidgetData.php`, `src/Actions/Fragments/RenderPublicFragmentAction.php`.
- **Done/Shipped: install/persist paths are covered.** `InstallPackageAction` has compatibility coverage for consuming package setup helpers, and `PersistLayoutBuilderStateAction` now has direct coverage proving container persistence, page layout assignment, widget-asset callback execution, preview invalidation, and transaction rollback when widget-asset persistence fails. `src/Actions/PersistLayoutBuilderStateAction.php`, `src/Actions/InstallPackageAction.php`, `tests/Unit/PersistLayoutBuilderStateActionTest.php`, `tests/Unit/LayoutBuilderScaffoldingAndRelationCoverageTest.php`.
- **Preview-image side effects on read.** `GenerateLayoutPreviewImageAction` writes to `Storage::disk('public')` and `saveQuietly()`s the layout; ensure this is never triggered on a public request path (it is queued via `AsJob`, but `GetLayoutPreviewImageUrlAction` reads `admin` JSON — keep admin-only). `src/Actions/GenerateLayoutPreviewImageAction.php`.
- **i18n debt.** Inline notification strings (§2.4) and `Str::headline()` fallbacks in `AnalyzeLayoutHealthAction::variantLabel()` mean some editor-facing text bypasses translation. `src/Livewire/Filament/LayoutBuilder.php`, `src/Actions/AnalyzeLayoutHealthAction.php`.

## 5. Marketplace & Positioning

This is correctly a **free / foundation** package — it is the composition engine the rest of the platform renders through (Frontend, themes, block-library all depend on it). Standalone pricing makes no sense; its commercial value is as the floor that makes Capell a real page-builder CMS rather than a flat-content CMS.

**Current copy — critique.** Manifest `summary` and composer `description` are identical and feature-listy ("Visual layout composition, content-first editing, and public layout rendering") — three internal capability names, no benefit, no audience. It tells a buyer _what the code does_, not _what they get_.

**Improved `summary` (manifest):**

> "Compose pages visually with reusable widgets and named layout areas — edit content fast in content-first mode, or drag-and-drop the full layout. Renders to clean, query-free public HTML that never leaks editor internals."

**Improved composer `description` (one line):**

> "The visual layout and widget composition engine for Capell CMS — content-first and drag-drop editing, responsive containers, reusable widgets, and safe public rendering."

**Tier / upsell.** Keep the engine free. The credible premium line sits _on top_ of existing primitives: (a) **whole-page templates / starter-layout gallery** (extends `LayoutPreset`), (b) **global synced blocks** (edit-once-update-everywhere over `Widget`/`widget_widgets`), (c) **advanced blocks & layout revision history**. Package these as a paid "Layout Pro" add-on so the foundation stays open and the differentiators monetize. The advanced presentation controls already gated behind `presentation.manage_advanced` show this split is intended.

**Media gaps.** Recapture the 10 screenshot targets with the real Capell runner assets/CSS loaded, then promote the strongest 3–5. The current committed PNGs stay as broken-runner evidence only and should not be buyer-facing marketplace media. Add a short animated capture of content-first editing and responsive-breakpoint switching — the two demos `docs/overview.md` explicitly says should be captured separately. A GIF of the editor is worth more than any static card for a layout product.

**Pitch contribution.** Strengthen the Capell pitch by leading with this package: it is the proof that Capell is a _composable_ CMS. Position it as "the engine themes and the public site render through," then point buyers to the Pro add-on for templates/global blocks.

**Keywords / tags (8–12):** `page-builder`, `visual-editor`, `drag-and-drop`, `layout`, `widgets`, `content-first`, `reusable-blocks`, `responsive-layout`, `filament`, `livewire`, `cms`, `block-composition`.

## 6. Prioritized Roadmap

| Item                                                                                                                                                                                                                                                                                                                      | Bucket | Effort | Impact | Section ref                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ------ | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Align `capell.json` deps with composer (add admin, block-library)                                                                                                                                                                                                                                                         | Done   | S      | High   | §2.3 / §4 — closed 2026-06-05: manifest requirements now include core, admin, block-library, and frontend.                                                                                                                                                                                                                                                                                                                                               |
| Implement real package health check (tables, install, bindings)                                                                                                                                                                                                                                                           | Done   | S      | High   | §2.1 / §4 — closed 2026-06-05: `LayoutBuilderHealthCheck` now probes storage tables, public graph builder binding, and editor Livewire registration.                                                                                                                                                                                                                                                                                                     |
| Remove dead `CapellLayoutCacheKeyEnum` (or wire it)                                                                                                                                                                                                                                                                       | Done   | S      | Med    | §2.2 / §4 — closed 2026-06-05: the unused cache enum was removed instead of preserving an abandoned key scheme.                                                                                                                                                                                                                                                                                                                                          |
| Recapture and promote 3–5 styled screenshots into manifest marketplace block                                                                                                                                                                                                                                              | Later  | S      | High   | §2.5 / §5 — current implementation scope is closed: the persistent prepared app recaptured and promoted real light/dark Capell admin/editor PNGs for widgets index, create widget form, page editor, and layouts index. Keep the frontend render target unpromoted until the public theme capture no longer shows the oversized black wave/artifact.                                                                                                     |
| Rewrite manifest `summary` + composer `description`                                                                                                                                                                                                                                                                       | Done   | S      | High   | §5 — closed 2026-06-05: manifest/composer copy now explains visual composition, content-first editing, and safe query-free public HTML.                                                                                                                                                                                                                                                                                                                  |
| Done/Shipped: Add public render performance-budget test coverage. Evidence: `PublicLayoutGraphStressTest` covers manifest-driven query budgets, zero-query hydrated Blade rendering, high-volume query scaling, and leak guards; wall-clock budget remains manifest documentation rather than a parallel-suite assertion. | Done   | M      | High   | §4                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| Add fragment tamper/replay → 404 safety test                                                                                                                                                                                                                                                                              | Done   | M      | High   | §4 — closed 2026-06-05: `PublicFragmentRenderingTest` covers invalid encrypted references, replayed references for another site/page, route 404s, and unsafe authoring HTML rejection.                                                                                                                                                                                                                                                                   |
| Done/Shipped: Audit & remove/cover orphan Actions (ApplyLayoutPlan, PreviewLayoutPlan, SaveFormComponentRelationship, InstallPackage)                                                                                                                                                                                     | Done   | M      | Med    | §2.7 / §4 — removed no-op `ApplyLayoutPlanAction`; confirmed/covered the reachable preview, relationship, persist, and compatibility install paths.                                                                                                                                                                                                                                                                                                      |
| Cover PersistLayoutBuilderStateAction + install path                                                                                                                                                                                                                                                                      | Done   | M      | High   | §4                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| Translate inline Livewire notifications                                                                                                                                                                                                                                                                                   | Done   | M      | Med    | §2.4 / §4                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| Split BuildLayoutContentInventoryAction (554 lines)                                                                                                                                                                                                                                                                       | Done   | M      | Med    | §2.6 — closed 2026-06-07: the Action is now a coordinator, with item projection/labels in `LayoutContentInventoryItemFactory` and group assembly in `LayoutContentInventoryGrouper`; package-local inventory tests preserve behavior.                                                                                                                                                                                                                    |
| Whole-page templates / starter-layout gallery (Pro)                                                                                                                                                                                                                                                                       | Done   | L      | High   | §3 / §5 — closed 2026-06-08: registered starter presets can replace the full builder state via `ApplyStarterLayoutPresetAction` and `LayoutBuilder::applyStarterLayoutPreset()`, and the editor now renders a translated starter-gallery UI backed by `ListLayoutPresetsAction`. Package-local Action, registry, render, and Livewire mutation tests pass. Future page-creation shortcuts and paid Layout Pro packaging remain Later product-depth work. |
| Durable / diff-based undo-redo history                                                                                                                                                                                                                                                                                    | Later  | M      | Med    | §2.8 / §3                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| Global synced blocks (edit-once-update-everywhere) (Pro)                                                                                                                                                                                                                                                                  | Later  | L      | High   | §3 / §5                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| Layout revision history + restore                                                                                                                                                                                                                                                                                         | Later  | L      | High   | §3                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| Accessibility diagnostics in AnalyzeLayoutHealthAction                                                                                                                                                                                                                                                                    | Later  | M      | Med    | §3                                                                                                                                                                                                                                                                                                                                                                                                                                                       |