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

Filament Package Template Laravel Package

mortalkiller/filament-package-template

A Laravel package template for building Filament plugins and extensions, offering a ready-made scaffold with sensible structure and conventions to help you start, organize, and ship reusable Filament components faster. Ideal for developers seeking a clean starting point for custom Filament packages.

View on GitHub
Deep Wiki
Context7

Getting Started

mortalkiller/filament-package-template is a scaffolding template, not a runtime dependency — you consume it once to generate a new package repository, then you never require it at runtime. Treat the version constraint as "the version of the generator I used", not something Composer will upgrade for you.

Start by creating a project from the template (or using the repo as a GitHub template), then let the interactive installer ask which profile you want:

composer create-project mortalkiller/filament-package-template:^2.0.1 my-plugin --stability=stable
cd my-plugin
composer install

Pin ^2.0.1 explicitly. v2.0.0 was tagged from the pre-v2 source and is not a valid starting point — it will give you the old template with none of the profile/opt-in machinery described in these notes.

Where to look first, in order:

  1. composer.json — the generated scripts (test, analyse, format, rector, etc.) are the real table of contents for the template's tooling.
  2. The generated src/*ServiceProvider.php — this is where Laravel Package Tools wiring lives and where you will spend most of your scaffolding time.
  3. workbench/ — a miniature Laravel app with a Filament panel that mounts your plugin.
  4. tests/ — the strict PHPUnit config and the browser-test setup tell you exactly what CI expects.

First use case: pick the plugin profile, run composer test, then boot the Workbench panel to see your (empty) plugin rendered inside a real Filament panel before you write a line of feature code. That loop — edit provider/resource, run tests, refresh workbench — is the day-to-day rhythm.

Implementation Patterns

Choose the profile deliberately — it is close to a one-way door. The five profiles map to genuinely different skeletons:

  • plugin — a Filament plugin (panel extension via the Plugin contract), the default for most packages.
  • theme — a Filament theme package with asset/CSS pipeline emphasis.
  • forms / tables — focused packages extending Filament form or table behaviour, typically without a panel.
  • library — no Filament panel dependency; the Laravel Package Tools skeleton with the Filament-specific bits stripped out.

Switching afterwards means copying directories by hand, so decide before create-project.

Opt-in features are additive, not retroactive. Config, migrations, views, translations, stubs, assets, Workbench, browser tests, and Rector are all selected at scaffold time. Each one has two halves that must both be present:

  1. The files themselves (config/, database/migrations/, resources/views/, resources/lang/, resources/dist/, stubs/).
  2. The corresponding configurePackage() flag in your service provider.

If you skipped a feature and want it later, the cleanest path is to scaffold a throwaway package with that feature enabled and copy both the files and the provider lines across.

Lean on Laravel Package Tools for the runtime wiring. Most of your provider is declarative:

public function configurePackage(Package $package): void
{
    $package
        ->name('filament-package-standard-example')
        ->hasConfigFile()
        ->hasViews()
        ->hasTranslations()
        ->hasMigrations(['create_examples_table'])
        ->hasAssets()
        ->hasInstallCommand(fn (InstallCommand $command) => $command->publishesMigrations()->publishesAssets());
}

Resist the urge to hand-roll loadViewsFrom / mergeConfigFrom calls — the template's tests and the install command both assume the Package Tools conventions.

Filament plugin registration pattern. For plugin-profile packages, implement the Plugin contract and keep register(Panel $panel) a thin list of resources/pages/widgets. Register the plugin in the Workbench panel provider so tests and the browser suite exercise the real panel:

public function panel(Panel $panel): Panel
{
    return $panel
        ->id('admin')
        ->plugin(ExamplePlugin::make());
}

Use the generated scripts as your gate, not ad-hoc commands. Run composer test (strict PHPUnit), composer analyse (Larastan 6+), composer rector (if opted in), and the browser suite in that order before pushing. The CI matrix (PHP 8.2–8.5 × Laravel 12/13, plus a Windows job) is expensive to iterate on remotely, so reproduce its lowest boundary locally — PHP 8.2 + Laravel 12 + Filament 5.8 — before opening a PR.

Gotchas and Tips

  • v2.0.0 is a poisoned tag. It was cut from pre-v2 source. Never scaffold from it and never let a lockfile resolve to it. ^2.0.1 is correct.
  • Template updates do not reach you. Composer will not "upgrade" a scaffolded package. If you want a v2.0.2 template fix (CI workflow, Rector config, PHP 8.5 matrix entry), diff your repo against a fresh scaffold of the new version and cherry-pick. Budget for this periodically rather than expecting automatic maintenance.
  • PHP 8.2 is the floor. The matrix tests down to 8.2, so avoid 8.4-only syntax (property hooks, asymmetric visibility) in src/ even though the top of the matrix allows it. The Windows job exists for template tooling compatibility — it does not guarantee your package's browser tests pass on Windows.
  • Strict PHPUnit is strict about things you don't think about: risky tests, warnings, deprecations, output during tests, and coverage annotation mismatches all fail the build. A passing test suite locally under a permissive config can still fail in the template's config. Read phpunit.xml.dist before adding tests.
  • Larastan level 6 + Filament generics is the most common friction point. Expect to add @extends, @property, and @method docblocks to Resources, Pages, and Table/Form schemas. Do it as you go — bolting docblocks on at level 6 later is miserable.
  • Workbench is a test harness, not shippable code. Its migrations, seeders, and panel provider should never be published or referenced from src/. Keep the boundary explicit; the library profile exists precisely for cases where the Workbench/panel coupling is unwanted.
  • Opt-in assets means a build step. If you enabled assets, the publish pipeline expects compiled output in resources/dist/. Forgetting to build before tagging ships a broken style to consumers, and browser tests won't catch it if they run against source.
  • Zizmor requires SHA-pinned actions. Any uses: you add must use a full commit SHA, not a tag, or the audit job fails. Fork PRs also won't have access to repository secrets — keep workflows secret-free or guard on pull_request_target carefully.
  • Extension points worth knowing: the stubs/ directory (if opted in) lets you customise what your own package publishes via hasInstallCommand; configurePackage() is the single lever for feature toggling; the profile prompts themselves live in the template tooling, so if you need a new profile, fork the template rather than fighting the generated output.
  • Upgrade command from the release notes, for anyone unlucky enough to have scaffolded from v2.0.0: composer require mortalkiller/filament-package-standard:^2.0 and re-scaffold — the ^2.0.1 constraint applies to the template at creation time.
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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource