Packages
Capell packages extend the CMS without adding feature code to Core, Admin, or Frontend. Use a package when a capability can be installed, versioned, tested, and disabled independently.
When To Create A Package
Section titled “When To Create A Package”| Package is right when… | Keep it in the app when… |
|---|---|
| The feature has its own settings, routes, resources, widgets, jobs, or frontend output. | It is one-off project glue with no reuse value. |
| It should be installable through Composer or Marketplace. | It depends heavily on private app models. |
| It needs its own tests and release cadence. | The behavior is just app configuration. |
| It contributes through Capell extension points. | It needs to patch host package classes. |
If you are unsure, use Host, package, or app code.
Required Files
Section titled “Required Files”Every package should have:
composer.jsoncapell.json- at least one service provider
README.md- focused package tests
Packages with admin UI usually also include translations, Filament resources/pages/widgets, settings schemas, an admin bridge, and feature tests.
capell.json
Section titled “capell.json”Keep the manifest boring and explicit. It should identify the package, provider classes, version constraints, contribution metadata, settings ownership, lifecycle commands, and Marketplace metadata when relevant.
Use the current package catalogue as the source of truth for public package names: Approved packages.
Service Providers
Section titled “Service Providers”Package providers should register only what the package owns:
- config and translations
- migrations and settings migrations
- package settings classes
- admin bridges and admin surface contributions
- render hooks, assets, frontend widgets, and cache invalidation rules
- routes, commands, policies, events, and jobs
Do not register optional-package behavior from the host repo. The package that owns the feature should register it.
Use the extension point chooser before adding a new registration path. Use the extension point API reference when you need exact contracts, tags, and test recipes. Use extension troubleshooting when a package is installed but its admin, frontend, settings, cache, or marketplace contribution does not appear.
Actions, Data, And Settings
Section titled “Actions, Data, And Settings”- Put domain behavior in
src/Actions/*Action.php. - Put structured inputs/outputs in
src/Data/*Data.php. - Cast JSON settings/state to Data objects where practical.
- Keep Filament resources, Livewire components, controllers, commands, and jobs thin.
- Use translations for visible strings.
Command, resource, or job tests should fake Actions when the Action already has direct coverage.
Admin Contributions
Section titled “Admin Contributions”Use an AdminBridge when a package contributes more than one admin concern:
final class PackageAdminBridge implements AdminBridge{ public function register(AdminBridgeRegistrar $registrar, AdminBridgeContextData $context): void { $registrar->resource(ExampleResource::class, group: 'content', name: 'examples'); $registrar->widget(ExampleWidget::class); $registrar->settingsClass('examples', ExampleSettings::class); $registrar->settingsSchema('examples', ExampleSettingsSchema::class); }}Small packages can contribute directly with CapellAdmin::contributeToAdminSurface(...), but bridges are easier to audit.
Useful admin surfaces:
| Need | Use |
|---|---|
| Filament page/resource/widget/configurator | AdminSurfaceContributionData through AdminBridgeRegistrar. |
| Page, site, layout, or user form fields | Tagged schema extenders. |
| Dashboard widgets | CapellAdmin::registerDashboardWidget(...). |
| Header tools | AdminToolItem::TAG. |
| User menu items | CapellAdmin::registerUserMenuItem(...). |
| Admin widgets | CapellAdmin::registerWidget(...). |
Frontend Contributions
Section titled “Frontend Contributions”Frontend package code must preserve public HTML safety. Anonymous output must not expose authoring selectors, model IDs, field paths, signed admin URLs, permissions, or package internals.
| Need | Use |
|---|---|
| Small HTML injection | RenderHookRegistry::register(...). |
| Public widget | WidgetRegistry::register(...) with WidgetTarget::FrontendBlade or FrontendLivewire. |
| Package CSS/JS | TailwindAssetsRegistry::registerSource(...) and registerImport(...). |
| Page cache invalidation | CacheInvalidationRegistry::registerDependency(...). |
| Static-site export hook | StaticSiteExtensionRegistry::register(...) when the static export package is installed. |
Database And Migrations
Section titled “Database And Migrations”- Package migrations live in the package.
- Settings migrations live in
database/settings/. - Guard settings migrations with table/column existence checks.
- Writes go through Actions, not model methods.
- If the package introduces public rendering data, make sure controllers/actions load it before Blade renders.
Cover package behavior where it lives:
- Action tests for domain behavior.
- Feature tests for routes, commands, Filament pages/resources, and package install/setup.
- Public rendering tests for frontend output and safety.
- Architecture tests for package boundaries.
- Manifest/provider tests so package discovery fails loudly.
When testing commands or UI surfaces that only orchestrate Actions, fake the Action boundary with Laravel Actions fakes instead of running the Action again. The surface test should prove prompts, options, output, permissions, and Action invocation; the Action test should prove domain behavior.
Use the narrowest package Pest command during development, then broaden before release:
vendor/bin/pest packages/admin/tests --configuration=phpunit.xmlRelease Checklist
Section titled “Release Checklist”Use the package checklist before release.
composer.jsonandcapell.jsonmatch the package name.- Provider registers only package-owned behavior.
- Visible strings use translations.
- Actions and Data objects cover meaningful boundaries.
- Migrations are idempotent for installed apps.
- Public frontend output is safe for anonymous users.
- Package tests pass in isolation.
- README explains install, config, commands, extension points, and troubleshooting.
Read Next
Section titled “Read Next”| Need | Read |
|---|---|
| Build a realistic package from scratch | Build an extension end to end |
| Understand package boot/provider buckets | Package boot lifecycle |
| Pick the right extension point | Extension point chooser |
| Look up exact contracts/tags/tests | Extension point API reference |
| Debug Composer/manifest/provider discovery | Debugging package discovery |
| Debug missing package contributions | Extension troubleshooting |
| Avoid unsafe package patterns | Do not do this |