# 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

| 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](../development/package-boundaries.md).

## Required Files

Every package should have:

- `composer.json`
- `capell.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`

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](catalog.md).

## 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](extension-point-chooser.md) before adding a new registration path. Use the [extension point API reference](extension-point-api-reference.md) when you need exact contracts, tags, and test recipes. Use [extension troubleshooting](extension-troubleshooting.md) when a package is installed but its admin, frontend, settings, cache, or marketplace contribution does not appear.

## 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

Use an `AdminBridge` when a package contributes more than one admin concern:

```php
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

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

- 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.

## Tests

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:

```bash
vendor/bin/pest packages/admin/tests --configuration=phpunit.xml
```

## Release Checklist

Use the [package checklist](package-checklist.md) before release.

- `composer.json` and `capell.json` match 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

| Need                                       | Read                                                              |
| ------------------------------------------ | ----------------------------------------------------------------- |
| Build a realistic package from scratch     | [Build an extension end to end](build-extension-end-to-end.md)    |
| Understand package boot/provider buckets   | [Package boot lifecycle](package-boot-lifecycle.md)               |
| Pick the right extension point             | [Extension point chooser](extension-point-chooser.md)             |
| Look up exact contracts/tags/tests         | [Extension point API reference](extension-point-api-reference.md) |
| Debug Composer/manifest/provider discovery | [Debugging package discovery](debugging-package-discovery.md)     |
| Debug missing package contributions        | [Extension troubleshooting](extension-troubleshooting.md)         |
| Avoid unsafe package patterns              | [Do not do this](../development/do-not-do-this.md)                |