Actions, Data, And Settings
Capell packages use Actions for behavior and Data objects for typed boundaries.
Actions
Section titled “Actions”Put package behavior in src/Actions.
<?php
declare(strict_types=1);
namespace Capell\Example\Actions;
use Lorisleiva\Actions\Concerns\AsObject;
final class BuildExampleReportAction{ use AsObject;
public function handle(): mixed { return ExampleModel::query(); }}Filament pages, commands, listeners, and controllers call ::run() or ::dispatch(). They should not contain domain logic.
Data Objects
Section titled “Data Objects”Use src/Data for structured input and output:
<?php
declare(strict_types=1);
namespace Capell\Example\Data;
use Spatie\LaravelData\Data;
final class ExampleHealthData extends Data{ public function __construct( public string $status, public int $issueCount, ) {}}Use Data objects across HTTP, Filament, Livewire, JSON casts, and package boundaries.
Settings
Section titled “Settings”Settings need a Spatie settings class, a settings migration, a Filament schema, and a package-owned extension settings page. The global Capell Settings page is reserved for core settings only.
final class ExampleSettings extends Settings{ public bool $enabled = true;
public static function group(): string { return 'example'; }}Register settings from a provider:
use Capell\Core\Support\Settings\SettingsGroupMetadata;use Capell\Core\Support\Settings\SettingsSchemaRegistry;use Filament\Support\Icons\Heroicon;
$registry = resolve(SettingsSchemaRegistry::class);$registry->registerSettingsClass('example', ExampleSettings::class);$registry->registerMetadata(new SettingsGroupMetadata( group: 'example', label: 'example::settings.title', icon: Heroicon::OutlinedCog6Tooth, navigationGroup: 'capell-admin::navigation.group_system', packageName: 'capell-app/example',));$registry->register('example', ExampleSettingsSchema::class);Expose package settings through a Filament page that extends Capell\Admin\Filament\Pages\AbstractPackageSettingsPage and register it with CapellAdmin::registerExtensionPage($packageName, YourPackageSettingsPage::class). This adds the page to Filament, lists the package on the Extensions management page with a direct Edit action, and adds accessible registered pages to the grouped Filament sub-navigation on the Extensions page. Packages with multiple registered pages use the first page as the primary edit target and show the others as direct secondary links.