Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Shortcodes Filament Laravel Package

webwizo/laravel-shortcodes-filament

Filament panel integration for webwizo/laravel-shortcodes. Adds admin resources and pages to create, edit, and organize shortcodes from your Filament dashboard, letting editors manage dynamic content snippets, attributes, and previews without touching code.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and migrate

composer require webwizo/shortcodes-filament
php artisan vendor:publish --tag=shortcodes-filament-migrations
php artisan vendor:publish --tag=shortcodes-filament-config   # optional
php artisan migrate

Upgrading an existing install to v1.0.1 requires re-publishing the migration with --force (the shortcodes table gains a type column), then running migrate:

php artisan vendor:publish --tag=shortcodes-filament-migrations --force
php artisan migrate

Register the plugin on the Filament panel you want editors to manage shortcodes from, then clear caches (php artisan filament:cache-components, config:clear) so the new type field and Dynamic Data Source section appear.

Where to look first

  1. The generated config/shortcodes-filament.php — data source / model configuration lives here.
  2. The Filament ShortcodeResource — this is where content editors create and preview shortcodes.
  3. The facade Webwizo\ShortcodesFilament\Facades\Shortcode — the whole runtime API is compile(), strip(), register().

First use case — a static presentational block. Create a shortcode in the admin with type Static, body something like:

<div class="callout callout--{{variant}}">{{text}}</div>

Then in a Blade view:

{!! Shortcode::compile($page->body) !!}

Everything after that is the same pattern — the only decision per shortcode is whether it needs a live record (Dynamic) or is just markup (Static).

Implementation Patterns

Compile at render time, not at save time. Store raw shortcode markup in your content column and run Shortcode::compile() in the view (or a model accessor / presenter). Saving compiled HTML freezes dynamic shortcodes against stale data and makes edits in the admin invisible until you re-save content. If compile cost becomes an issue, cache the rendered string per shortcode + lookup id, and bust it on the underlying model's saved/deleted events.

Static shortcodes — treat {{attr}} as optional-by-default. Since v1.0.1, attributes with no value are omitted from output entirely. Design templates so a missing attribute degrades gracefully rather than leaving class="callout--" or an empty <a href="">. Either give every attribute a sane default in the template, or guard with a CSS class that only matters when present.

Dynamic shortcodes — the lookup attribute is part of the public contract. A dynamic shortcode's usage example now includes the required attribute:

[staff_card id="5"]

The value in id="" is what the Dynamic Data Source uses to fetch the record; {{db.name}}, {{db.role}} etc. then resolve against it. Document the required attribute name next to the shortcode (the generated usage example on the resource is the natural place) — authors who type [staff_card] or [staff_card slug="x"] get nothing, silently.

strip() for every non-HTML sink. Use Shortcode::strip($content) for meta descriptions, search indexes, RSS, notification emails, and PDF-ish exports. Running compile() into a plain-text field will dump markup into your SEO metadata; running the raw string will leak [staff_card id="5"] into excerpts.

register() for code-defined shortcodes. Anything that must exist across environments — a CTA banner owned by the dev team, an embed defined in a service provider — should be registered in a ServiceProvider::boot() (or a seeder for local-only fixtures) rather than hand-created in production. That way a fresh migrate:fresh on staging reproduces it. Keep editor-owned marketing shortcodes in the database and code-owned structural ones in register(); mixing both in the admin UI leads to "who deleted this?" incidents.

Filament integration pattern. Use a RichEditor for body content and render the stored value with compile() in your front-end Blade. Filament's editor round-trips the raw [tag ...] text fine; just don't enable a preview/render step inside the editor unless you're also compiling there, otherwise editors see raw tags and assume it's broken.

Empty output is the safe default. Missing, invalid, or soft-deleted lookup values render nothing (v1.0.1). Lean into it: a card for a deleted employee disappears instead of shipping a half-broken div. But it also means you can't rely on a visible failure to catch bad data — pair dynamic shortcodes with a lint/report step (see below).

Gotchas and Tips

The --force publish overwrites the published migration file. It's a one-time upgrade step, not something to re-run casually — re-running it after you've customised the published migration wipes those edits. After migrating, php artisan migrate:status and confirm the type column exists before debugging anything else; a panel still rendering the old form almost always means the migration didn't run.

Silent rendering is the top debugging trap. If a dynamic shortcode outputs nothing, check in this order: (1) is the shortcode's type actually Dynamic — Static shortcodes ignore the data source entirely; (2) is the lookup attribute present in the content and spelled exactly as the resource's usage example shows; (3) does the record exist and is it not soft-deleted (withTrashed() in tinker); (4) is the configured data source model correct in config. Nothing in the output will hint at which of these failed.

Raw {{db.*}} placeholders in production HTML means you're behind. That was the v1.0.0 lookup bug (wrong attribute-reading method → every query returned empty) plus unhandled lookups. Upgrade to 1.0.1 and re-check; do not "fix" it by editing templates.

Escape deliberately. compile() returns HTML, so it needs {!! !!}. That's fine for trusted editor content, but shortcode bodies are authored HTML — restrict the ShortcodeResource to trusted roles, and never compile() content submitted by end users (comments, support tickets, profile bios) without sanitising the rendered result. The attribute interpolation path is likewise not a user-input sanitiser.

Import the facade class, don't alias-hope. v1.0.1 ships Webwizo\ShortcodesFilament\Facades\Shortcode with proper docblocks for compile(), strip(), and register(). Adding the use statement gives you autocompletion and static analysis; skipping it and calling a global/string alias hides typos until runtime.

Empty attributes and CSS. Because valueless attributes are dropped, class="x {{modifier}}" renders class="x " when modifier is unset — harmless — but style="background:{{color}}" becomes a broken inline style. Prefer template-level conditionals for anything where an empty value is semantically wrong.

Cache invalidation for dynamic shortcodes. If you cache compiled output, key it on the lookup id and the shortcode's updated_at, and flush on the source model's save/delete/restore. Soft-deletes are especially easy to miss: a restored record should start rendering again, but a naive cache keyed only on id will keep serving empty.

Add a smoke test. A cheap test that asserts compile() of a known dynamic shortcode with a real factory record contains the expected field value, and that compile() of the same shortcode with a deleted record returns '', catches both the regressions v1.0.1 fixed and future template typos.

Extension points to prefer over editing the package. Register custom shortcodes in a service provider via Shortcode::register(); wrap compile() in your own Blade component or directive (e.g. <x-shortcode :content="$body" />) so you have one place to add caching, sanitising, or environment gating without touching vendor code.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc