Skip to content

Frontend Authoring — Improvement & Growth Plan

Package: capell-app/frontend-authoring · Kind: package · Tier: free · Product group: Capell Foundation · Bundle: foundation · Status: Draft

  • 2026-06-04: Defined the advertised frontend-authoring.edit Gate as a package-owned deny-by-default ability that host apps can override, while preserving existing editContent / update pageable policy fallbacks. Focused coverage proves the ability is registered, denies by default, can be overridden, and does not suppress fallback authorization.
  • 2026-06-04: Guarded the optional Publishing Studio approval workspace branch behind the package install state and removed the catch-all fallback that converted approval failures into in_review saves. Focused coverage proves unavailable Publishing Studio returns a 409 without creating a workspace, installed approval still creates an in-review workspace, and approval submission failures now surface.

Frontend Authoring is the foundation in-page editing bridge: it adds an admin-only beacon (POST /beacon, BeaconController) that, after a public page has loaded, returns a bootstrap script decorating registered regions (page title, meta description, page content) with edit controls, plus a signed iframe editor route (GET authoring/regions/{payload}, EditRegionControllerEditRegionField Livewire) that saves a single Filament field through UpdateEditableRegionAction and clears affected HTML caches. Gating is layered and genuinely defensive: the beacon short-circuits to a bare CSRF token for anonymous users, non-admins, cross-origin requests, and posted-URL/origin mismatches before any DB work (src/Http/Controllers/BeaconController.php); the editor route is auth+signed, payloads are HMAC-signed (EditableRegionSigner) and re-validated against the live manifest on every load and save (ValidateEditableRegionPayloadAction). Surfaces: frontend, console. Deps: capell-app/admin, capell-app/core, capell-app/frontend, capell-app/html-cache, spatie/laravel-package-tools. Capabilities: authoring-surface, preview-only, beacon, cache-blocking; manifest declares it non-cacheable (cacheSafety.cacheable: false) with a 20ms frontend render budget. Marketplace summary now leads with the live-site editing outcome while emphasizing visitor/cache safety, and Composer description is aligned. Screenshots: marketplace.screenshots[] now declares the extension card plus real desktop and mobile authoring captures from runner-backed docs/screenshots/; docs/screenshots.json still defines the wider browser/config proof contract for the screenshot runner.

  • Make the health check actually check somethingFrontendAuthoringHealthCheck only implements compatibleCapellApiVersion(): '^4.0'; the manifest advertises it as severity: critical with label “surfaces, providers, and install health are discoverable by Diagnostics.” It verifies none of that. Add real probes: beacon route registered, EditableRegionRegistry/EditorSurfaceRegistry/EditableRegionSigner resolvable, capell-frontend-authoring.enabled readable, app.key present (signer depends on it). src/Health/FrontendAuthoringHealthCheck.php — S.
  • Shipped 2026-06-04: Define the frontend-authoring.edit Gate. FrontendAuthoringServiceProvider now registers the advertised ability as deny-by-default when the host has not defined it. Host apps can override it with Gate::define() / Gate::before(), and AuthorizeEditableRegionAction still falls back to pageable editContent / update policies when the package ability denies. src/Providers/FrontendAuthoringServiceProvider.php, tests/Feature/AuthorizeEditableRegionActionTest.php — S/M.
  • Done/Shipped: beacon admin-manifest assembly now lives in an Action. BeaconController delegates to BuildBeaconResponseAction, which owns anonymous/non-origin short-circuits, site/page resolution, admin user response shape, banner context, editable-region manifest assembly, and bootstrap script rendering. This keeps public no-leak behavior intact while moving domain response assembly out of the controller. src/Actions/BuildBeaconResponseAction.php, src/Http/Controllers/BeaconController.php — M.
  • Done/Shipped: editable-region field/type/surface/status logic is enum-backed. EditableRegionInputType, EditableRegionSurface, EditableRegionSaveStatus, and EditableRegionField now back internal comparisons while EditableRegionPayloadData::toArray() and EditableRegionData::toArray() keep the same string values for signed editor URLs and beacon manifests. Custom meta paths such as meta.summary remain preserved while being classified as meta fields. src/Enums/, src/Data/EditableRegionPayloadData.php, src/Livewire/EditRegionField.php, src/Actions/UpdateEditableRegionAction.php — M.
  • Shipped 2026-06-04: Harden UpdateEditableRegionAction approval branch against duck-typing. The approval workspace branch now aborts with 409 unless capell-app/publishing-studio is installed, and submitForApproval() failures bubble instead of being caught and forced into in_review. src/Actions/UpdateEditableRegionAction.php, tests/Feature/EditableRegionEditingTest.php — M.
  • Cache BuildAuthoringBannerContextAction table check — it calls Schema::hasTable(...) on every admin beacon hit before querying cached_model_urls. Since html-cache is a hard dependency the table is always present; drop the probe or memoise it to respect the 20ms budget. src/Actions/BuildAuthoringBannerContextAction.php — S.
  • Closed 2026-06-05: Refresh the CHANGELOG. The changelog now records real health probes, signed-payload editor flow, beacon origin hardening, optional approval-workspace save flow, marketplace/composer copy sharpening, promoted desktop/mobile screenshots, signer tamper coverage, and orphan screenshot cleanup. CHANGELOG.md — S.

Tie-back to capabilities: [authoring-surface, preview-only, beacon, cache-blocking].

  • Done/Shipped: Click-to-edit beyond text fields has a second built-in surface. Frontend Authoring now ships a registered media editor surface beside field, and package-supplied editable-region extenders can emit EditableRegionSurface::Media regions with target/context metadata that round-trip through the manifest and signed edit controller. The first built-in media shell still uses the shared value editor, so richer asset-picker UX remains future Pro depth. src/Enums/EditableRegionSurface.php, src/Support/EditorSurfaces/MediaEditorSurface.php, src/Providers/FrontendAuthoringServiceProvider.php, tests/Unit/Actions/BuildEditableRegionManifestActionTest.php, tests/Feature/EditableRegionEditingTest.php — L.
  • Section reorder / block management on the frontend (differentiator). capabilities implies an authoring surface but there is no drag-reorder or add/remove-block affordance; editing is strictly per-field, per-region. This is the single biggest differentiator vs table-stakes “edit text in place.” — L.
  • Draft/preview from the frontend is half-built (table-stakes). preview-only is advertised and UpdateEditableRegionAction has an approval-workspace path returning a redirect_url, but it is opt-in (workflow.require_approval, default false), entirely dependent on publishing-studio internals, and has no first-class “edit as draft / preview / publish” toggle in the editor UI. Promote this to a visible, supported control. — M/L.
  • Done/Shipped: role-aware region controls are available to extenders. EditableRegionPayloadData now accepts a permissions list, AuthorizeEditableRegionAction requires those Gate abilities before coarse frontend-authoring.edit / pageable policy checks pass, and BuildEditableRegionManifestAction filters denied regions before returning the admin-only manifest. The manifest now declares frontend-authoring.edit, while package extenders can supply their own per-region abilities. src/Data/EditableRegionPayloadData.php, src/Actions/AuthorizeEditableRegionAction.php, src/Actions/BuildEditableRegionManifestAction.php, tests/Feature/AuthorizeEditableRegionActionTest.php, tests/Unit/Actions/BuildEditableRegionManifestActionTest.php — M.
  • No edit toolbar persistence / discoverability surface. The bootstrap script injects a banner + per-region controls, but there is no documented public JS API or CapellFrontendAuthoring global for themes to hook (the anonymous browser-test asserts no such global, which is correct — but admins get none either). A namespaced admin-only API would let themes register custom regions client-side. — M.
  • Done/Shipped: locale coverage extends beyond English. Frontend Authoring now bundles resources/lang/es/authoring.php, mirroring the banner, editor, health, enum-label, and surface strings from English. LocaleCoverageTest asserts Spanish and English key parity so future authoring strings cannot drift silently. resources/lang/es/authoring.php, tests/Unit/LocaleCoverageTest.php — S.

Public-output safety (the #1 rule) — currently strong, keep it that way.

  • Anonymous/non-admin no-leak coverage exists and is solid: tests/Feature/BeaconControllerTest.php covers guest (returns only csrf token for guest), authenticated non-admin (does not return authoring scripts or metadata for non-admin authenticated user), admin-without-permission, cross-origin admin (does not return authoring scripts for cross-origin admin beacons), posted-URL/origin mismatch, and cached-HTML leakage (page data does not render authoring metadata into cached html, line 383). tests/Unit/ManifestRequirementsTest.php:54 enforces a declared browser test anonymous-users-receive-no-authoring-surface, and docs/screenshots.json codifies the assertions (“no CapellFrontendAuthoring global, no capell-authoring DOM, no edit_url/recordKey/model/field path/selector/label/signed URL”). This is the model other packages should copy.
  • html-cache interaction is correct by construction: editor HTML is injected client-side by the beacon after load, never rendered into Blade, so cached pages stay clean. The manifest correctly sets cacheSafety.cacheable: false. The risk is regression — any future change that moves a region marker, selector, or signed URL into server-rendered Blade (resources/views/components/page-data.blade.php is the only public-injected view and it emits only the generic beacon fetch, no authoring data) would break this. Keep the line-383 cached-HTML test and the arch/browser contract as guardrails.

Bugs / tech debt.

  • Stub health check misrepresents severity: critical coverage (see §2). src/Health/FrontendAuthoringHealthCheck.php — risk: Diagnostics reports green while the surface is broken.
  • Undefined frontend-authoring.edit ability (see §2/§3) — advertised gate is inert in production; real gating silently delegates to pageable policies. src/Actions/AuthorizeEditableRegionAction.php:24.
  • Shipped 2026-06-04: approval path now respects optional publishing-studio availability. UpdateEditableRegionAction checks CapellCore::isPackageInstalled('capell-app/publishing-studio') before creating an approval workspace and surfaces submission failures instead of masking them. src/Actions/UpdateEditableRegionAction.php.
  • Closed 2026-06-05: Orphan duplicate asset cleanup. The nested stray packages/frontend-authoring/... screenshot copy is gone; committed documentation image assets still live under docs/images/screenshots/, while marketplace and runner contract captures now use the release-gate-friendly docs/screenshots/ location.
  • PassThroughActivityMiddleware is a literal no-op aliased only when frontend.activity is unregistered. Fine as a fallback shim, but undocumented; a reader can’t tell it’s intentional. Add a class docblock. src/Http/Middleware/PassThroughActivityMiddleware.php.

Test gaps.

  • No direct unit test for EditableRegionSigner tamper/format edge cases at the decode() boundary (malformed base64, missing keys, truncated signature) — these abort(403) paths are only hit indirectly via EditableRegionEditingTest (“encodes signed region payloads and rejects tampered payloads”). Add a focused signer unit test.
  • Done/Shipped: content HTML policy is explicit and covered. Frontend Authoring keeps content HTML as trusted_admin_raw: signed editor routes are admin-only, and the package stores admin-authored content exactly as submitted so Capell’s normal rendering/theme layer remains the owner of output policy. A focused test covers script-bearing HTML round-tripping unchanged under that policy. config/capell-frontend-authoring.php, src/Actions/UpdateEditableRegionAction.php, tests/Feature/EditableRegionEditingTest.php.
  • No assertion that the beacon stays within the frontendRenderBudgetMs: 20 budget; the budget is declared in capell.json but unverified.

Performance budgets (cited). performance.frontendRenderBudgetMs: 20, adminQueryBudget: 0. The anonymous beacon path is O(1) (returns before any query) — good. The admin path runs several queries (LoadSiteDomainFromUrlAction, PageUrl lookup with eager loads, registry translation load, cached_model_urls lookup, Schema::hasTable); adminQueryBudget: 0 is therefore aspirational/irrelevant for the admin branch but should be documented as “anonymous only.”

i18n. English-only (see §3). variesBy: ["site","locale"] declared but no non-en bundle.

This is a foundation/bundled package (tier: free, bundle: foundation, proposedLicense: free, requestedCertification: first-party) — it is plumbing that the frontend stack depends on, not a standalone purchase.

  • Closed 2026-06-05 — manifest summary and composer description. Manifest and Composer copy now lead with live-site editing for admins, then the public/cache safety guarantee. This is outcome-led and avoids the previous plumbing-first “beacon/manifest/routes” phrasing.
  • Screenshot/media status. marketplace.screenshots[] now lists the card plus real desktop and mobile authoring captures from docs/screenshots/. docs/screenshots.json tracks the broader three product captures plus two config-proof captures; the before/after “authoring enabled vs disabled / no leak” proof images remain strong trust assets for future gallery expansion.
  • free/bundle vs premium. Frontend inline editing is the strongest visible differentiator in the whole catalogue and a classic paid-pro hook. The current split is defensible: keep the core single-field text/meta/content editor free (it’s foundation, other packages assume the beacon exists), but a “Frontend Authoring Pro” could layer the high-value capabilities from §3 — media/block surfaces, frontend section reorder, draft→preview→publish UI, granular per-role region permissions — as a premium tier. The beacon + signer + registry already provide the extension seams (EditorSurfaceRegistry, capell-frontend-authoring:editable-regions tag) to do this without forking.
  • Platform-pitch contribution. This package is the “edit your site like Webflow/Framer, but it’s just Laravel + Filament” headline. It demonstrably proves the platform’s hardest promise — WYSIWYG-style editing with aggressive HTML caching and zero public leakage. Lead marketing with it; back the claim with the existing no-leak browser test as evidence.
  • Keywords/tags (8–12): inline editing, in-page editing, frontend authoring, live editing, WYSIWYG, click to edit, Filament, Livewire, html cache safe, signed urls, cms editing, content editing.
ItemBucketEffortImpactSection ref
Shipped 2026-06-04: implement real probes in FrontendAuthoringHealthCheck; evidence: route, service-binding, config, app-key probes plus healthy/broken critical manifest testsDoneSHigh§2, §4
Shipped 2026-06-04: define/deny-by-default the frontend-authoring.edit abilityDoneS/MHigh§2, §3, §4
Shipped 2026-06-04: guard publishing-studio approval branch behind isPackageInstalled + stop swallowing errorsDoneMHigh§2, §4
Done/Shipped: Promote real desktop+mobile captures into marketplace.screenshots[]; delete orphan nested assetDoneSMed§4, §5
Done/Shipped: Sharpen composer description + marketplace summary to outcome-led copyDoneSMed§5
Shipped 2026-06-04: add EditableRegionSigner tamper/format unit test + beacon render-budget assertionDoneSMed§4
Done/Shipped: Refresh CHANGELOG with signer/beacon-origin/approval historyDoneSLow§2
Done/Shipped: Extract beacon admin-manifest assembly into a BuildBeaconResponse ActionDoneMMed§2 — BeaconController now delegates response assembly to BuildBeaconResponseAction.
Done/Shipped: Replace field/type/surface/status string literals with backed enums (HasLabels)DoneMMed§2 — typed enums now back editor input type, surface, save status, and field-kind comparisons without changing public payload values.
Done/Shipped: Decide + test HTML sanitization policy for the content regionDoneS/MMed§4 — admin-authored content HTML is explicitly trusted_admin_raw and covered by focused round-trip coverage.
Done/Shipped: add a second built-in editor surface (image/media) to exercise the contractDoneLHigh§3 — registered media surface plus manifest/controller coverage for package-supplied media regions.
Done/Shipped: Add granular per-region/per-role permissions, filtered in the manifest builderDoneMHigh§3 — optional region permissions are enforced by AuthorizeEditableRegionAction before manifest inclusion or editor validation.
Done/Shipped: Translate authoring.php into the supported locale set (variesBy: locale)DoneS/localeMed§3, §4 — bundled Spanish locale plus key-parity coverage against English.
First-class draft→preview→publish toggle in the editor UILaterM/LHigh§3
Frontend section reorder / block add-remove (“Pro” differentiator)LaterLHigh§3, §5
Namespaced admin-only client API so themes can register regions in JSLaterMMed§3