> ## Documentation Index
> Fetch the complete documentation index at: https://flex-fields.bjanczak.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Examples target Filament 5. Verify optional dependencies before configuring integrations.
> Upload transfer completion, permanent storage and record acceptance are separate milestones. Native and Spatie image conversions retain the original.

# Your first extension

> Build and install a reusable Summary field, column and infolist entry step by step.

This walkthrough creates `acme/summary` inside an application that already has FLEX
and a Filament panel. Run the first command from the application directory containing
`artisan` and `composer.json`. Replace `acme` with your vendor name before distributing it.

For a private application extension, keep using your applicable FLEX grant. Before
distributing a package or reusable kit, confirm its [licensing scope](https://flex-fields.bjanczak.com/docs/licensing.md).
Generating a starter does not grant rights to redistribute FLEX itself.

> [!TIP]
>
> **Watch this in the workshop:** [29:56 — generate the reusable family](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=1796s) · [1:03:07 — install it through Composer and enable it in Filament](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=3787s).

**1. Generate the family**

The parent directory must exist. The destination must be new.

```shell theme={"theme":{"light":"github-light","dark":"github-dark"}}
mkdir -p packages
php artisan make:flex-component-package acme/summary ./packages/summary \
  --prefix=acme-summary \
  --namespace='Acme\Summary' \
  --class=Summary
```

You now have a field, column, entry, provider, views, shared CSS and build script.
The command does not install dependencies or change your application's Composer configuration.
To inspect the plan first, append `--dry-run --json`.

**2. Build the package**

Use the FLEX installation already present in the application. This avoids requiring
a second Composer installation merely to run the starter's build.

```shell theme={"theme":{"light":"github-light","dark":"github-dark"}}
cd packages/summary
npm install
FLEX_FIELDS_ROOT="../../vendor/janczakb/filament-flex-fields" npm run build
cd ../..
```

If your Composer vendor directory is different, set `FLEX_FIELDS_ROOT` to the installed
FLEX package directory. Build before Composer discovery boots your new provider.
The resulting manifest references the complete `resources/dist/<release>` directory.

**3. Install the local Composer package**

Add a path repository in the application's Composer configuration, then require the package.

```shell theme={"theme":{"light":"github-light","dark":"github-dark"}}
composer config repositories.acme-summary \
  '{"type":"path","url":"packages/summary","options":{"symlink":true}}'
composer require 'acme/summary:@dev'
php artisan filament:assets
php artisan fff:assets:doctor
php artisan fff:assets:explain acme-summary-field
```

Composer discovers `SummaryServiceProvider`. Keep your application's existing FLEX
package repository and license access configuration. The local development constraint
is not a release version for a distributed package.

Keep the main FLEX plugin enabled in the panel that will use your extension. If it is
already enabled, no panel change is needed. Otherwise, add it to the panel's existing
plugins in `AdminPanelProvider`:

```php theme={"theme":{"light":"github-light","dark":"github-dark"}}
use Bjanczak\FilamentFlexFields\FilamentFlexFieldsPlugin;

// Inside your existing panel configuration:
->plugins([
    FilamentFlexFieldsPlugin::make(),
    // Keep your other panel plugins here.
])
```

The generated Summary family does not need its own `->plugin()` call. Its Laravel
service provider registers its definitions with FLEX. For an application-local
provider that is not installed through Composer, register that provider in
`bootstrap/providers.php` instead; do not register the same provider twice.

**4. Add the field**

Add this component to the form schema of your resource or Livewire form:

```php theme={"theme":{"light":"github-light","dark":"github-dark"}}
use Acme\Summary\Forms\SummaryField;
use Bjanczak\FilamentFlexFields\Filament\Forms\Components\FlexTextInput;

SummaryField::make('summary')
    ->schema([
        FlexTextInput::make('text')
            ->label('Summary')
            ->required()
            ->maxLength(80),
    ]);
```

This is the real FLEX input inside your field. Its state, validation and assets remain
owned by the child. You can change its supported fluent options without copying its view.

**5. Store the value and show it elsewhere**

The generated field stores `['text' => 'Example']`. Add a JSON attribute and an Eloquent
array cast to the model used by your form:

```php theme={"theme":{"light":"github-light","dark":"github-dark"}}
// In your application migration:
Schema::table('posts', function (Blueprint $table): void {
    $table->json('summary')->nullable();
});
```

Import `Illuminate\Support\Facades\Schema` and `Illuminate\Database\Schema\Blueprint`
in that migration, and run your normal migration workflow.

```php theme={"theme":{"light":"github-light","dark":"github-dark"}}
// In your model:
protected function casts(): array
{
    return ['summary' => 'array'];
}
```

Use the matching surface in a table or infolist:

```php theme={"theme":{"light":"github-light","dark":"github-dark"}}
use Acme\Summary\Tables\SummaryColumn;
use Acme\Summary\Infolists\SummaryEntry;

// Table columns:
SummaryColumn::make('summary');

// Infolist schema:
SummaryEntry::make('summary');
```

## Confirm the result

Enter a summary, submit the form and reopen the record. The same value should appear
in the field, table and infolist. The column and entry use shared display CSS without
loading the field's interactive JavaScript. Two fields on the same page must keep
independent values and consumer identities.

> **[Understand the package](https://flex-fields.bjanczak.com/docs/extensions/package-structure.md)**
>
> Learn which generated files to change and which build outputs to distribute.

> **[Configure an existing child](https://flex-fields.bjanczak.com/docs/extensions/child-php-api.md)**
>
> Add relationships, queries and callback configuration through trusted PHP.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.