capell-app/filament-peek
Adds a Peek action to Filament resource edit pages so editors can preview a record's front-end page in a modal or new tab without leaving the panel, including unsaved changes and device presets. Handy for content-heavy sites where layouts need checking before publishing.
capell-app/filament-peek is a fork of pboivin/filament-peek — a Filament plugin that adds a Preview button to resource pages so editors can see a record's front-end page (or their unsaved form state) in a modal before publishing. The 1.0.x line is the "stable, no surprises" branch; v1.0.49 is a patch release, so nothing in your setup should need to change.
Minimal setup:
composer require capell-app/filament-peekphp artisan vendor:publish --tag=filament-peek-config (add --tag=filament-peek-views only if you intend to restyle the modal).config/filament-peek.php first — it's the whole surface area of the package: modal sizing, internal page patterns, front-end asset/theme handling.Page, Post, LandingPage model), implement the package's preview contract and return the public URL for a record. This is the one piece of glue code you own.protected function getHeaderActions(): array
{
return [
PreviewAction::make(),
];
}
First use case to validate end-to-end: open a draft record, hit Preview, and confirm the iframe renders the front-end page for an unpublished record. That single flow exercises the URL resolution, the auth/session handoff, and the iframe headers — the three things that break.
Put URL resolution on the model, not the resource. Resources get copied, renamed and split; a previewUrl() method (or a small PreviewUrlResolver) on the model keeps getPreviewUrl() a one-liner and gives you somewhere sane to add locale/tenant/domain logic.
Unsaved-changes preview is the real feature. Peek serialises the current Livewire form state and renders the front-end view with it, so editors see typography and layout changes without saving. Use it for content types where the visual result matters (marketing pages, block builders, long-form articles). For structured data where the front-end barely changes (a category, a settings row), the plain record preview is enough — don't add buttons that show the same page every time.
Side-by-side editing (preview stays open while the form stays editable) is the workflow pattern worth adopting for a CMS: editors tweak copy in the left pane, watch the iframe on the right, save once. It pairs badly with heavy modals-in-modals, so keep the resource form flat.
Table-row previews for read-only triage: put the action in ->actions([...]) so reviewers can eyeball a record without entering the edit page and risking an accidental save.
Multi-panel / multi-guard apps: register the plugin per panel and make sure your admin path is listed under the internal page patterns in config, otherwise the package will happily try to iframe your own admin screens.
Test it like a route. A feature test that hits the preview URL for a draft record and asserts 200 + a fragment of expected content catches 90% of regressions (guard changes, middleware changes, policy changes) before an editor does.
X-Frame-Options / CSP frame-ancestors is the #1 cause of a blank modal. Laravel sends SAMEORIGIN by default; if the front-end lives on a different subdomain or port than the admin, the iframe is silently refused. Check the browser console first, not your logs.admin.example.com and front-end on www.example.com means SameSite=Lax session cookies may not be sent, and you get a redirect to the login page rendered inside the modal. Fix at the cookie/domain config level, or proxy through a preview route on the front-end domain.getPreviewUrl() against a null record and return a sensible placeholder route, or hide the action until the form has been saved once.no-store.storage/logs/laravel.log before touching config.composer.json Filament constraint in the tag (forks commonly widen Filament major support inside patch releases) and re-run your preview smoke test on draft, published, and create-page flows.How can I help you explore Laravel packages today?