PHPackages                             lunarphp/filament - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Admin Panels](/categories/admin)
4. /
5. lunarphp/filament

ActiveLibrary[Admin Panels](/categories/admin)

lunarphp/filament
=================

Filament components, widgets, and schemas for Lunar — composable building blocks for any Filament v5 panel.

2.x-dev(today)00MITPHP ^8.4

Since Jul 1Pushed todayCompare

[ Source](https://github.com/lunarphp/filament)[ Packagist](https://packagist.org/packages/lunarphp/filament)[ RSS](/packages/lunarphp-filament/feed)WikiDiscussions 2.x Synced today

READMEChangelogDependencies (5)Versions (2)Used By (0)

Lunar Filament Bridge
=====================

[](#lunar-filament-bridge)

Filament v5 components, widgets, schemas, and tables for Lunar — the e-commerce primitives behind the Lunar admin panel, packaged so you can drop them into any Filament v5 panel.

This package ships the reusable building blocks: a product picker that knows about Lunar's translated names and Scout-aware search, a translated-text input that round-trips your locale data, dashboard chart widgets pre-wired against the order schema, a complete set of resource forms and tables for every commerce model, and the attribute system that powers Lunar's flexible product data.

If you want Lunar's complete turnkey admin panel — navigation, branding, auth, dashboard — install [`lunarphp/admin`](https://packagist.org/packages/lunarphp/admin) instead. It depends on this package.

Requirements
------------

[](#requirements)

- PHP 8.3+
- Laravel 11+ (Lunar v2 supports Laravel 13)
- Filament v5
- `lunarphp/core` (installed automatically)

Installation
------------

[](#installation)

```
composer require lunarphp/core lunarphp/filament
```

The service provider auto-registers via Laravel's package discovery. No further wiring is required to start using the form components, table columns, infolist entries, or selectors.

To run Lunar's database migrations against your app:

```
php artisan migrate
```

What's in the box
-----------------

[](#whats-in-the-box)

SurfaceNamespaceExamplesEntity selectors`Lunar\Filament\Forms\Components\*Select``ProductSelect`, `CollectionSelect`, `CurrencySelect`Generic form components`Lunar\Filament\Forms\Components\*``Attributes`, `TranslatedText`, `MediaSelect`, `Tags`, `Vimeo`, `YouTube`Table columns`Lunar\Filament\Tables\Columns\*``TranslatedTextColumn`, `ThumbnailImageColumn`Infolist entries`Lunar\Filament\Infolists\Components\*``Timeline`, `Tags`, `Transaction`Resource schemas`Lunar\Filament\Schemas\{Model}\{Model}Form``ProductForm`, `OrderForm`, `BrandForm`, `LocationForm`, `RegionForm`, … (22 models)Resource tables`Lunar\Filament\Tables\{Model}\{Model}Table``ProductTable`, `OrderTable`, …Relation managers`Lunar\Filament\RelationManagers\{Model}\*`Customer addresses, Discount conditions, ProductOption values, …Actions`Lunar\Filament\Actions\{Subject}\*Action``RefundOrderAction`, `CaptureOrderAction`, `DuplicateProductAction`, `PublishProductsBulkAction`Global-search descriptors`Lunar\Filament\GlobalSearch\*GlobalSearch``OrderGlobalSearch`, `ProductGlobalSearch`, `CustomerGlobalSearch`Dashboard widgets`Lunar\Filament\Widgets\*``OrderStatsOverview`, `OrdersSalesChart`, `LatestOrdersTable`Attribute system`Lunar\Filament\FieldTypes\*``TextField`, `TranslatedText`, `Dropdown`, `Toggle`, `ListField`, …---

Entity selectors
----------------

[](#entity-selectors)

Sixteen first-class `Select` (and one `MorphToSelect`) subclasses for picking Lunar records by relationship. They all share one Scout-aware search backend, default to translated names where applicable, and ship with sensible Lunar-flavoured defaults.

SelectorPicksNotable extras`ProductSelect`Product`->showSku()`, `->scopeStatus('published')`, `->withinChannel($channel)`, `->excludeAttached()``ProductVariantSelect`ProductVariant`->forProduct($product)`, `->searchViaProduct()`, label is `"Product — SKU"``CollectionSelect`Collectionbreadcrumb path label, `->excludeDescendantsOf($collection)`, `->excludeSelf($collection)`, `->withinGroup($group)``BrandSelect`Brandrelationship-bound to `brand`, inline create form`ProductTypeSelect`ProductTypepreloaded, relationship-bound`TagSelect`Tagmulti-select by default`CustomerSelect`Customermulti-field search across `first_name`, `last_name`, `company_name``CustomerGroupSelect`CustomerGrouppreloaded, relationship-bound to `customerGroup``DiscountTargetSelect`Polymorphic Product/Variant/Collection/Brand`->targets([Product::class, Collection::class])` per call-site`CurrencySelect`Currencydefaults to `Currency::getDefault()`, preloaded`ChannelSelect`Channelpreloaded`LanguageSelect`Languagepreloaded`TaxClassSelect`TaxClassdefaults to `TaxClass::getDefault()`, preloaded`TaxZoneSelect`TaxZonepreloaded`CountrySelect`Countryemoji + native-name label, `->iso3()` mode`StateSelect`Statedatalist-backed, `->dependsOn('country_id')`### Basic usage

[](#basic-usage)

Drop a selector into any Filament form, schema, or action — it works exactly like a `Select`:

```
use Lunar\Filament\Forms\Components\ProductSelect;

ProductSelect::make('product_id')
    ->required();
```

### Searching, filtering, and de-duplication

[](#searching-filtering-and-de-duplication)

```
use Lunar\Core\Models\Channel;
use Lunar\Filament\Forms\Components\ProductSelect;

ProductSelect::make('product_id')
    ->showSku()                                  // append " — {sku}" to each result
    ->scopeStatus('published')                   // only published products
    ->withinChannel(Channel::getDefault())       // only products attached to this channel
    ->excludeAttached()                          // hide records already on the surrounding relation
    ->multiple();                                // multi-select is supported on every selector
```

`->excludeAttached()` is a no-op outside a `RelationManager` context, and inside one it dedupes against the `getRelationship()->get()` ids automatically — including for `AttachAction`-driven attach modals.

### Variants

[](#variants)

```
use Lunar\Filament\Forms\Components\ProductVariantSelect;

// Direct variant search (SKU + product name)
ProductVariantSelect::make('variant_id');

// Search products first, then list every variant of the matched product
ProductVariantSelect::make('variant_id')->searchViaProduct();

// Restrict to one product (e.g. a row already chose the parent)
ProductVariantSelect::make('variant_id')->forProduct($product);
```

### Collections

[](#collections)

```
use Lunar\Filament\Forms\Components\CollectionSelect;

CollectionSelect::make('collection_id')
    ->excludeDescendantsOf($currentCollection)   // safe re-parent target picker
    ->excludeSelf($currentCollection);
```

The default label format is the breadcrumb path: `"Men > Outerwear > Jackets"`.

### Country &amp; State (dependent datalist)

[](#country--state-dependent-datalist)

```
use Lunar\Filament\Forms\Components\CountrySelect;
use Lunar\Filament\Forms\Components\StateSelect;

CountrySelect::make('country_id')->live();
StateSelect::make('state')->dependsOn('country_id');
```

`CountrySelect::iso3()` switches the field to store ISO3 codes instead of foreign keys — useful for `TaxZone` countries and other ISO-keyed columns.

### Polymorphic discount targets

[](#polymorphic-discount-targets)

```
use Lunar\Core\Models\Brand;
use Lunar\Core\Models\Collection;
use Lunar\Core\Models\Product;
use Lunar\Core\Models\ProductVariant;
use Lunar\Filament\Forms\Components\DiscountTargetSelect;

DiscountTargetSelect::make('discountable')
    ->targets([Product::class, ProductVariant::class, Collection::class, Brand::class]);
```

### Using a selector inside `AttachAction`

[](#using-a-selector-inside-attachaction)

Filament's `AttachAction::recordSelect(fn ($select) => …)` callback hands you the existing `Select` rather than letting you swap in a subclass. Lunar selectors expose a static `applyTo($select)` helper for exactly this case:

```
use Filament\Actions\AttachAction;
use Filament\Forms\Components\Select;
use Lunar\Filament\Forms\Components\CollectionSelect;

AttachAction::make()
    ->recordSelect(fn (Select $select) => CollectionSelect::applyTo($select));
```

### Picking your own search backend

[](#picking-your-own-search-backend)

If you need to bend the search query for one call-site, the `modifyOptionsQueryUsing()` hook is stackable:

```
ProductSelect::make('product_id')
    ->modifyOptionsQueryUsing(fn ($query) => $query->whereHas('media'));
```

The underlying search service is `Lunar\Filament\Forms\Components\Support\RecordSearch` — call it directly from your own components:

```
use Lunar\Core\Models\Product;
use Lunar\Filament\Forms\Components\Support\RecordSearch;

$results = RecordSearch::for(Product::class, $search)->take(20)->get();
```

It prefers Laravel Scout when both `lunar.panel.scout_enabled` is true and the model uses Scout's `Searchable` trait, falls back to a translated-attribute DB search, and falls back again to a plain `name` column search for models that have neither.

---

Other form components
---------------------

[](#other-form-components)

### `Attributes` — the Lunar attribute editor

[](#attributes--the-lunar-attribute-editor)

Renders editable fields for every attribute attached to the current model (Product, Brand, Collection, etc.) according to its registered field type. Each field type knows how to draw itself, cast its data, and synthesize across Livewire.

```
use Lunar\Filament\Forms\Components\Attributes;

Attributes::make();                                          // attributes for the resource model
Attributes::make()->using(ProductVariant::class);            // attributes for a different model
Attributes::make()->relationship('variant');                 // load/save through a relationship
```

### `TranslatedText` — locale-aware text input

[](#translatedtext--locale-aware-text-input)

```
use Lunar\Filament\Forms\Components\TranslatedText as TranslatedTextInput;

TranslatedTextInput::make('name')->required();
```

Renders one input per Lunar `Language`, hydrating from `attribute_data->name->value` (translated `Text` and `TranslatedText` field types). Pair with `TranslatedRichEditor` for HTML content.

### `MediaSelect`, `Tags`, `Vimeo`, `YouTube`

[](#mediaselect-tags-vimeo-youtube)

Spatie Media Library integration, a chip-style tag input with autocomplete suggestions, and embedded-video field types for common content needs.

### `AttributeSelector`, `PermissionSelector`

[](#attributeselector-permissionselector)

CheckboxList-based pickers for product type → attribute mapping and staff → permission assignment respectively.

---

Table columns
-------------

[](#table-columns)

### `TranslatedTextColumn`

[](#translatedtextcolumn)

Renders a translated attribute, with optional tooltip when truncated:

```
use Lunar\Filament\Tables\Columns\TranslatedTextColumn;

TranslatedTextColumn::make('attribute_data.name')
    ->attributeData()
    ->limit(40)
    ->limitedTooltip();
```

### `ThumbnailImageColumn`

[](#thumbnailimagecolumn)

Renders a square thumbnail resolved from a closure:

```
use Lunar\Filament\Tables\Columns\ThumbnailImageColumn;

ThumbnailImageColumn::make('thumbnail')
    ->resolveThumbnailUrlUsing(fn ($record) => $record->getThumbnailImage());
```

---

Infolist entries
----------------

[](#infolist-entries)

- `Lunar\Filament\Infolists\Components\Timeline` — activity-log timeline (Spatie Activitylog backed).
- `Lunar\Filament\Infolists\Components\Tags` — read-only tag chips.
- `Lunar\Filament\Infolists\Components\Transaction` — payment-transaction summary card.

---

Resource schemas, tables, and relation managers
-----------------------------------------------

[](#resource-schemas-tables-and-relation-managers)

Each Lunar commerce model has a complete Filament schema set under `Lunar\Filament\Schemas\{Model}` and `Lunar\Filament\Tables\{Model}`. They are the same classes the Lunar admin panel uses internally.

```
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Tables\Table;
use Lunar\Core\Models\Brand;
use Lunar\Filament\Schemas\Brand\BrandForm;
use Lunar\Filament\Schemas\Brand\BrandInfolist;
use Lunar\Filament\Tables\Brand\BrandTable;

class MyBrandResource extends Resource
{
    protected static ?string $model = Brand::class;

    public static function form(Schema $schema): Schema
    {
        return BrandForm::configure($schema);
    }

    public static function infolist(Schema $schema): Schema
    {
        return BrandInfolist::configure($schema);
    }

    public static function table(Table $table): Table
    {
        return BrandTable::configure($table);
    }
}
```

Every schema/table class also exposes granular `getXxxFormComponent()` / `getXxxTableColumn()` static helpers, so you can pick a single field or column without inheriting the rest:

```
$schema->components([
    BrandForm::getNameFormComponent(),
    BrandForm::getDescriptionFormComponent(),
    \Filament\Forms\Components\Toggle::make('featured'),    // your own field
]);
```

Models with a complete schema, table, infolist, and relation managers: `Activity`, `AttributeGroup`, `Brand`, `Channel`, `Collection`, `CollectionGroup`, `Currency`, `Customer`, `CustomerGroup`, `Discount`, `Language`, `Order`, `Product`, `ProductOption`, `ProductType`, `ProductVariant`, `Staff`, `Tag`, `TaxClass`, `TaxRate`, `TaxZone`.

---

Actions
-------

[](#actions)

First-class Filament `Action` / `BulkAction` classes for every commerce verb the admin uses. The Filament class owns the modal schema, labels, notifications, and visibility predicate; the underlying business logic lives in a `Lunar\Core\Actions\*` counterpart so a CLI, API, or different UI can call the same code.

ActionWrapsWhere it fits`Orders\RefundOrderAction``Core\Actions\Orders\RefundOrder`Order header / detail page`Orders\CaptureOrderAction``Core\Actions\Orders\CaptureOrder`Order header / detail page`Orders\CloseOrderAction``Core\Actions\Orders\CloseOrder`Order header (archive a dealt-with order)`Orders\ReopenOrderAction``Core\Actions\Orders\ReopenOrder`Order header (un-archive a closed order)`Orders\NotifyCustomerAction``Core\Actions\Orders\NotifyCustomer`Order header (compose + send a customer notification from the order-scoped, sendable entries of the `OrderNotifications` catalogue; hidden when none are sendable)`Orders\AddOrderNoteAction`— (Filament-only single-field write)Order header`Orders\DownloadOrderPdfAction`— (Filament-only, subclass of `Support\DownloadPdfAction`)Order header`Products\DuplicateProductAction``Core\Actions\Products\DuplicateProduct`Product row / header`Products\PublishProductsBulkAction` / `UnpublishProductsBulkAction` / `ArchiveProductsBulkAction``Core\Actions\Products\UpdateProductStatus`Product table`Products\AdjustStockAction``Core\Actions\Products\AdjustStock`Variant row`Collections\CreateRootCollectionAction` / `CreateChildCollectionAction``Core\Actions\Collections\CreateRootCollection` / `CreateChildCollection`Collection tree view`Collections\MoveCollectionAction` / `DeleteCollectionAction``Core\Actions\Collections\MoveCollection` / `DeleteCollection`Collection tree viewDrop into any header/row/bulk action array — they work like any Filament action:

```
use Lunar\Filament\Actions\Orders\CaptureOrderAction;
use Lunar\Filament\Actions\Orders\CloseOrderAction;
use Lunar\Filament\Actions\Orders\RefundOrderAction;

protected function getDefaultHeaderActions(): array
{
    return [
        CaptureOrderAction::make(),
        RefundOrderAction::make(),
        CloseOrderAction::make(),
    ];
}
```

Need the verb outside Filament (e.g. an API endpoint)? Call the core action directly:

```
use Lunar\Core\Actions\Orders\RefundOrder;

$result = RefundOrder::run(
    order: $order,
    transactionId: $transaction->id,
    amount: '25.00',
    notes: 'Customer requested partial refund',
);
```

The core action validates the amount against `RefundOrder::availableToRefund($order)`, dispatches through the underlying payment driver, and returns the driver's `PaymentRefund` result. Bulk Filament actions are thin loops over the same core action wrapped in a single transaction.

Shared `Concerns` traits (`InteractsWithTransactions`, `ConfirmsDestructiveAction`) cover the repeating form fragments — extend or override them in a subclass to bend the schema without re-implementing the whole action.

---

Global search
-------------

[](#global-search)

Each searchable Lunar model has a `GlobalSearchDescriptor` subclass that owns its searchable attribute list, result title, result details, and eager-loaded query. Consumers compose their own Filament resource and opt in with one trait and one property:

```
use Filament\Resources\Resource;
use Lunar\Core\Models\Product;
use Lunar\Filament\GlobalSearch\Concerns\HasLunarGlobalSearch;
use Lunar\Filament\GlobalSearch\ProductGlobalSearch;

class MyProductResource extends Resource
{
    use HasLunarGlobalSearch;

    protected static ?string $model = Product::class;

    protected static string $globalSearch = ProductGlobalSearch::class;
}
```

The trait forwards `getGloballySearchableAttributes`, `getGlobalSearchResultTitle`, `getGlobalSearchResultDetails`, and `getGlobalSearchEloquentQuery` to the descriptor, and routes the actual constraint-building through `RecordSearch` — the same Scout-vs-translated-attribute backend the entity selectors use. Scout is used when `lunar.panel.scout_enabled=true` and the model uses `Laravel\Scout\Searchable`; otherwise the query falls back to LIKE-matching across the resource's attribute list plus any searchable `TranslatedText` attributes.

`getGlobalSearchResultUrl` stays on the resource — only the resource knows its own URL.

Descriptors shipped: `OrderGlobalSearch`, `ProductGlobalSearch`, `CustomerGlobalSearch`, `CollectionGlobalSearch`, `BrandGlobalSearch`.

There is no panel-wide auto-registration to enable or disable — global search is opt-in per resource via the trait. A consumer who only wants Lunar models in their existing resources adds the trait there; one who omits it gets no Lunar global-search rows.

---

Dashboard widgets
-----------------

[](#dashboard-widgets)

Drop into your panel's `widgets([…])` configuration:

```
use Lunar\Filament\Widgets\Dashboard\Orders\AverageOrderValueChart;
use Lunar\Filament\Widgets\Dashboard\Orders\LatestOrdersTable;
use Lunar\Filament\Widgets\Dashboard\Orders\NewVsReturningCustomersChart;
use Lunar\Filament\Widgets\Dashboard\Orders\OrdersSalesChart;
use Lunar\Filament\Widgets\Dashboard\Orders\OrderStatsOverview;
use Lunar\Filament\Widgets\Dashboard\Orders\OrderTotalsChart;
use Lunar\Filament\Widgets\Dashboard\Orders\PopularProductsTable;

return $panel->widgets([
    OrderStatsOverview::class,
    OrdersSalesChart::class,
    OrderTotalsChart::class,
    AverageOrderValueChart::class,
    NewVsReturningCustomersChart::class,
    LatestOrdersTable::class,
    PopularProductsTable::class,
]);
```

Also available: `Lunar\Filament\Widgets\Customer\CustomerStatsOverviewWidget`, `Lunar\Filament\Widgets\Collections\CollectionTreeView`, `Lunar\Filament\Widgets\Products\ProductOptionsWidget`, `Lunar\Filament\Widgets\Products\VariantSwitcherTable`.

Widgets that link to Lunar records (e.g. "click an order in this table") use a record-URL resolver. Wire it up to your own resources in your panel provider:

```
use Lunar\Filament\Support\Facades\RecordUrls;

RecordUrls::resolveUsing('order', fn ($order) => MyOrderResource::getUrl('view', ['record' => $order]));
RecordUrls::resolveUsing('product_variant', fn ($variant) => MyProductResource::getUrl('edit', ['record' => $variant->product]));
```

When no resolver is registered, the widget gracefully omits the link.

---

Attribute system
----------------

[](#attribute-system)

Lunar's flexible-attributes system is configured per-product-type and rendered automatically by the `Attributes` form component. The shipped field types live under `Lunar\Filament\FieldTypes\*` — `TextField`, `TranslatedText`, `Dropdown`, `Toggle`, `Number`, `File`, `ListField`, `Vimeo`, `YouTube`. Each is auto-registered via the service provider.

Register your own field type:

```
use Lunar\Filament\FieldTypes\BaseFieldType;
use Lunar\Filament\Support\Facades\AttributeData;

class ColorPicker extends BaseFieldType
{
    public function getFilamentComponent($attribute, $component) { /* … */ }
    public function getCast(): string { /* … */ }
}

AttributeData::registerFieldType(ColorPicker::class);
```

---

Customisation strategies
------------------------

[](#customisation-strategies)

Three ways to bend the bridge to your own UX, each with different upgrade implications.

ApproachWhen to reach for itUpgrade impact**Extension hooks** — `LunarFilament::extensions([…])`Add or modify components on an existing schema without owning the fileAdditive — bridge improvements still reach you on minor releases**Subclass and rebind** — bind your subclass in the containerFully replace a schema/table class without copying itFull replacement — bridge improvements still reach the parent methods you don't override**Publish stubs** — `vendor:publish --tag=lunar-filament.schemas`Take complete ownership of one or more files in your app namespaceOne-way door — bridge improvements no longer reach the published file; re-merge by hand### Extension hooks

[](#extension-hooks)

```
use Lunar\Filament\Schemas\Product\ProductForm;
use Lunar\Filament\Support\Facades\LunarFilament;

LunarFilament::extensions([
    ProductForm::class => new class {
        public function configureForm($schema)
        {
            return $schema->components([
                ...$schema->getComponents(),
                Filament\Forms\Components\Toggle::make('featured'),
            ]);
        }
    },
]);
```

Register your extensions in a service provider's `boot()` method. Hooks stack — register multiple extensions against the same target and each runs in registration order, passing its return value into the next.

### Subclass and rebind

[](#subclass-and-rebind)

```
namespace App\Filament\Schemas\Product;

class ProductForm extends \Lunar\Filament\Schemas\Product\ProductForm
{
    public static function getBrandComponent(): \Filament\Schemas\Components\Component
    {
        return parent::getBrandComponent()->hidden();
    }
}

// In a service provider:
$this->app->bind(
    \Lunar\Filament\Schemas\Product\ProductForm::class,
    \App\Filament\Schemas\Product\ProductForm::class,
);
```

### Publish stubs

[](#publish-stubs)

```
php artisan vendor:publish --tag=lunar-filament.schemas
```

Copies every schema, table, infolist, and relation manager into `app/Filament/…` (configurable in `config/lunar-filament.php` → `publish_path`). The runtime resolver prefers your published copy when both exist.

You can also publish:

```
php artisan vendor:publish --tag=lunar-filament.config    # config file
php artisan vendor:publish --tag=lunar-filament.lang      # translation files (16 locales)
php artisan vendor:publish --tag=lunar-filament.views     # blade views
```

---

Configuration
-------------

[](#configuration)

Publish and tweak `config/lunar-filament.php` to change:

- `publish_path` — where stub publication writes files (default: `app/Filament`).
- `resolver.prefer_published` — runtime preference between published and bridge classes.
- `register_widgets_on_default_panel` — opt-in auto-registration of the dashboard widgets (off by default for downstream-panel installs).
- `record_url_resolvers` — closures that map a record + key to a URL inside your panel.

---

Translations
------------

[](#translations)

The package ships translations in 16 locales: `ar`, `bg`, `de`, `en`, `es`, `fa`, `fr`, `hr`, `hu`, `mn`, `nl`, `pl`, `pt_BR`, `ro`, `tr`, `vi`. Override per-key by publishing the lang files (`php artisan vendor:publish --tag=lunar-filament.lang`) and editing `lang/vendor/lunar-filament/{locale}/…`.

---

Standalone Filament panel example
---------------------------------

[](#standalone-filament-panel-example)

A minimum panel that uses bridge components without Lunar's admin shell:

```
use Filament\Panel;
use Filament\PanelProvider;
use Lunar\Filament\Widgets\Dashboard\Orders\OrderStatsOverview;
use Lunar\Filament\Widgets\Dashboard\Orders\OrdersSalesChart;

class MyPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->id('store')
            ->path('store')
            ->resources([
                MyBrandResource::class,        // uses Lunar\Filament\Schemas\Brand\BrandForm internally
                MyProductResource::class,
                MyOrderResource::class,
            ])
            ->widgets([
                OrderStatsOverview::class,
                OrdersSalesChart::class,
            ]);
    }
}
```

---

Versioning
----------

[](#versioning)

The bridge tracks Filament's release cadence. A Filament major (v5 → v6) drives a bridge major; the Lunar admin shell tightens its constraint when ready.

For v2 the package is developed inside the [Lunar monorepo](https://github.com/lunarphp/lunar). It extracts into its own repository (`lunarphp/filament`) at the v2.0.0 stable cut.

License
-------

[](#license)

MIT.

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity36

Early-stage or recently created project

 Bus Factor1

Top contributor holds 50% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

0d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/112434999?v=4)[Lunar - Headless E-Commerce for Laravel](/maintainers/lunarphp)[@lunarphp](https://github.com/lunarphp)

---

Top Contributors

[![actions-user](https://avatars.githubusercontent.com/u/65916846?v=4)](https://github.com/actions-user "actions-user (1 commits)")[![glennjacobs](https://avatars.githubusercontent.com/u/647407?v=4)](https://github.com/glennjacobs "glennjacobs (1 commits)")

---

Tags

laravelheadlessecommercefilamentlunar

###  Code Quality

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/lunarphp-filament/health.svg)

```
[![Health](https://phpackages.com/badges/lunarphp-filament/health.svg)](https://phpackages.com/packages/lunarphp-filament)
```

###  Alternatives

[a2insights/filament-saas

Filament Saas for A2Insights

171.7k](/packages/a2insights-filament-saas)[slimani/filament-media-manager

A media manager plugin for Filament.

126.9k](/packages/slimani-filament-media-manager)[mradder/filament-logger

Audit logging, activity tracking, exports, alerts, and dashboards for Filament admin panels.

2310.5k](/packages/mradder-filament-logger)[openplain/filament-tree-view

Tree view for Filament resources - drop-in replacement for Table with drag-and-drop hierarchical data management

3628.2k](/packages/openplain-filament-tree-view)[andreia/filament-ui-switcher

Add a modal with options to switch between different UI layouts and styles (colors, fonts, font sizes).

246.4k](/packages/andreia-filament-ui-switcher)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
