PHPackages                             mddev31/filament-dynamic-dashboard - 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. mddev31/filament-dynamic-dashboard

ActiveLibrary[Admin Panels](/categories/admin)

mddev31/filament-dynamic-dashboard
==================================

Dynamic dashboard for Laravel Filament.

v0.4.3(2mo ago)7563↓100%4MITPHPPHP ^8.3

Since Jan 26Pushed 1mo agoCompare

[ Source](https://github.com/MDDev31/filament-dynamic-dashboard)[ Packagist](https://packagist.org/packages/mddev31/filament-dynamic-dashboard)[ Docs](https://github.com/mddev31/filament-dynamic-dashboard)[ RSS](/packages/mddev31-filament-dynamic-dashboard/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (10)Versions (15)Used By (0)

Filament Dynamic Dashboard
==========================

[](#filament-dynamic-dashboard)

User-configurable dashboards for Filament v4+.

[![PHP 8.3+](https://camo.githubusercontent.com/c8d8dad6beb757a2b8acba331d16140813699543b88a37af0a81f20bd35f61de/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e332532422d626c7565)](https://www.php.net/)[![Filament 4/5](https://camo.githubusercontent.com/36a32735dc97e34b080638caa544ff7d5f2b49ed9be152ea450900b522a325df/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f46696c616d656e742d34253230253743253230352d6f72616e6765)](https://filamentphp.com/)[![Laravel 10/11/12](https://camo.githubusercontent.com/934c60d4b198c50fe53587c7ef11138695a83b6f668b40ef8f995dab4ac7b805/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d3130253230253743253230313125323025374325323031322d726564)](https://laravel.com/)[![License MIT](https://camo.githubusercontent.com/5caa455d8debc46fb23abbadb45a733a937f3910a73fc875c2f7820468e1bb54/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e)](LICENSE.md)

Introduction
------------

[](#introduction)

Filament Dynamic Dashboard lets end-users create, switch, and manage multiple dashboards directly from the Filament UI. Widgets are added, removed, and reordered per dashboard without any code changes. Each dashboard supports its own filters, default values, and per-filter visibility settings. Optional Spatie Permission integration provides role-based dashboard visibility out of the box.

[![Global Dashboard](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/global-dashboard.jpg)](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/global-dashboard.jpg)

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

[](#requirements)

- PHP &gt;= 8.3
- Filament &gt;= 4.1.10
- Laravel 10, 11, or 12
- (Optional) `spatie/laravel-permission` for role-based visibility

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

[](#installation)

Install via Composer:

```
composer require mddev31/filament-dynamic-dashboard
```

Publish and run the migrations:

```
php artisan vendor:publish --tag=filament-dynamic-dashboard-migrations
php artisan migrate
```

### Vite / Tailwind CSS compatibility

[](#vite--tailwind-css-compatibility)

This package uses Tailwind CSS classes in its Blade views. For these styles to be compiled correctly, Tailwind must be able to scan the package views.

In your Filament theme file (e.g. `resources/css/filament/admin/theme.css`), add the following `@source` directive: (if theme.css doesn't exist, see [filament documentation](https://filamentphp.com/docs/5.x/styling/overview#creating-a-custom-theme)

```
@source '../../../../vendor/mddev31/filament-dynamic-dashboard/resources/views/**/*';
```

Optionally publish the configuration file:

```
php artisan vendor:publish --tag=filament-dynamic-dashboard-config
```

Optionally publish translations:

```
php artisan vendor:publish --tag=filament-dynamic-dashboard-translations
```

Creating a Dashboard Page
-------------------------

[](#creating-a-dashboard-page)

Create a Filament page that extends `DynamicDashboard`. All standard Filament `Page` features (navigation icon, slug, group, etc.) remain available.

### Minimal Dashboard

[](#minimal-dashboard)

```
namespace App\Filament\Pages;

use MDDev\DynamicDashboard\Pages\DynamicDashboard;

class Dashboard extends DynamicDashboard
{

}
```

### Overridable Methods

[](#overridable-methods)

MethodSignaturePurpose`getDashboardFilters()``static array`Return Filament `Field` components shown in the filter bar`getDefaultFilterSchema()``static array`Return custom fields for editing default filter values (keyed by filter name)`resolveFilterDefaults()``static array`Transform stored defaults into actual filter values at apply time`getColumns()``int|array`Grid columns for the widget layout (defaults to config)`widgetsGrid()``Component`Override the grid layout used to render widgets`canEdit()``static bool`Whether the current user can add/edit/delete widgets and manage dashboards`canDisplay()``static bool`Whether the current user can view a specific dashboard`showWidgetLoader()``static bool`Whether to show loading indicators on widgets (default: `true`)Creating a Dynamic Widget
-------------------------

[](#creating-a-dynamic-widget)

Any Filament Widget can become a dynamic widget by implementing the `DynamicWidget` interface. This requires three static methods:

MethodReturn TypePurpose`getWidgetLabel()``string`Display name shown in the widget type selector`getSettingsFormSchema()``array`Filament form components for widget-specific settings`getSettingsCasts()``array`Cast definitions for settings values (primitives, BackedEnums, arrays)### Simple Widget (no settings)

[](#simple-widget-no-settings)

```
namespace App\Filament\Widgets;

use Filament\Widgets\StatsOverviewWidget;
use Filament\Widgets\Concerns\InteractsWithPageFilters;
use MDDev\DynamicDashboard\Contracts\DynamicWidget;

class SimpleStatsWidget extends StatsOverviewWidget implements DynamicWidget
{
    use InteractsWithPageFilters;

    public static function getWidgetLabel(): string
    {
        return 'Simple Stats';
    }

    public static function getSettingsFormSchema(): array
    {
        return [];
    }

    public static function getSettingsCasts(): array
    {
        return [];
    }

    protected function getStats(): array
    {
        // Access page filters via $this->pageFilters['country'] etc.
        return [/* ... */];
    }
}
```

### Widget with Settings

[](#widget-with-settings)

```
namespace App\Filament\Widgets;

use App\Enums\ResultTypeEnum;
use App\Enums\GroupingEnum;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Component;
use Filament\Widgets\Concerns\InteractsWithPageFilters;
use Leandrocfe\FilamentApexCharts\Widgets\ApexChartWidget;
use MDDev\DynamicDashboard\Contracts\DynamicWidget;

class SalesChartWidget extends ApexChartWidget implements DynamicWidget
{
    use InteractsWithPageFilters;

    public ResultTypeEnum $resultType = ResultTypeEnum::GrossRevenue;
    public GroupingEnum $groupBy = GroupingEnum::Channel;
    public ?int $limit = 5;

    public static function getWidgetLabel(): string
    {
        return 'Sales Chart';
    }

    /**
     * @return array
     */
    public static function getSettingsFormSchema(): array
    {
        return [
            Select::make('resultType')
                ->label('Result type')
                ->options(ResultTypeEnum::class)
                ->required()
                ->default(ResultTypeEnum::GrossRevenue->value),

            Select::make('groupBy')
                ->label('Group by')
                ->options(GroupingEnum::class)
                ->required()
                ->default(GroupingEnum::Channel->value),

            TextInput::make('limit')
                ->label('Limit')
                ->numeric()
                ->required()
                ->default(5),
        ];
    }

    /**
     * @return array
     */
    public static function getSettingsCasts(): array
    {
        return [
            'resultType' => ResultTypeEnum::class,      // BackedEnum
            'groupBy'    => GroupingEnum::class,         // BackedEnum
            'limit'      => 'int',                      // Primitive
        ];
    }

    protected function getOptions(): array
    {
        // $this->resultType, $this->groupBy, $this->limit are cast automatically
        // $this->pageFilters contains dashboard filters
        return [/* ... */];
    }
}
```

### How Settings Work

[](#how-settings-work)

The three pieces — **public properties**, **form schema**, and **casts** — are linked by a shared key name:

PieceRoleExample`public ResultTypeEnum $resultType`Livewire property that receives the value at render timeThe widget reads `$this->resultType``Select::make('resultType')` in `getSettingsFormSchema()`Form field the admin fills in (stored as JSON in the database)Key `resultType` is saved in the `settings` JSON column`'resultType' => ResultTypeEnum::class` in `getSettingsCasts()`Type-cast rule applied when reading the JSON backRaw string is converted to a `BackedEnum`**The key name must be identical across all three.** The form field name becomes the JSON key in the database, which is then cast and injected into the matching public property on the Livewire widget component.

#### Hydration flow

[](#hydration-flow)

```
Admin saves form
    → settings stored as JSON  {"resultType": "gross_revenue", "limit": 5}
    → on render, AsWidgetSettings cast applies getSettingsCasts()
    → cast values spread into Widget::make(['resultType' => ResultTypeEnum::GrossRevenue, 'limit' => 5, ...])
    → Livewire hydrates public properties  $this->resultType, $this->limit

```

> **Tip:** Always give your public properties a default value. If a setting is not yet saved in the database, the default on the property is used.

### Settings Casts

[](#settings-casts)

The `getSettingsCasts()` method defines how stored JSON values are hydrated:

CastExampleDescription`'int'`, `'integer'``'limit' => 'int'`Cast to integer`'float'`, `'double'``'ratio' => 'float'`Cast to float`'string'``'label' => 'string'`Cast to string`'bool'`, `'boolean'``'enabled' => 'bool'`Cast to boolean`MyEnum::class``'type' => ResultTypeEnum::class`Cast to a `BackedEnum` via `tryFrom()``['array', MyEnum::class]``'types' => ['array', ResultTypeEnum::class]`Cast each element of an array to a `BackedEnum`### Restricting a Widget to Specific Pages

[](#restricting-a-widget-to-specific-pages)

Implement the optional `availableForDashboard()` method to limit which dashboard pages can use the widget:

```
public static function availableForDashboard(): array
{
    return [
        \App\Filament\Pages\Dashboard::class,
        // Widget will only appear on these dashboard pages
    ];
}
```

An empty array (or omitting the method entirely) means the widget is available on all dynamic dashboards.

### Widget Visibility

[](#widget-visibility)

Filament's `canView()` method is respected automatically. If `canView()` returns `false`, the widget is hidden from the type selector and not rendered on the dashboard.

### Accessing Widget Metadata

[](#accessing-widget-metadata)

Widgets can access their own ID and title by declaring public properties. The dashboard will automatically inject these values:

```
class MyWidget extends StatsOverviewWidget implements DynamicWidget
{
    use InteractsWithPageFilters;

    public int $dynamicDashboardWidgetId;
    public string $dynamicDashboardWidgetTitle;

    protected function getStats(): array
    {
        // Use $this->dynamicDashboardWidgetId or $this->dynamicDashboardWidgetTitle
        return [/* ... */];
    }

    // ... other methods
}
```

Both properties are optional — declare only the ones you need.

### Widget Loading Indicator

[](#widget-loading-indicator)

Each widget displays a loading overlay while its Livewire component is updating. This behaviour is enabled by default and can be toggled globally or per-widget.

#### Disable globally

[](#disable-globally)

Override `showWidgetLoader()` in your dashboard subclass to disable the loader for all widgets:

```
class Dashboard extends DynamicDashboard
{
    public static function showWidgetLoader(): bool
    {
        return false;
    }
}
```

#### Per-widget override

[](#per-widget-override)

Add an optional static `showLoader()` method on any widget class. No interface change is required.

```
class HeavyChartWidget extends ApexChartWidget implements DynamicWidget
{
    /**
     * Force-enable or disable the loading indicator for this widget.
     * Return null to use the dashboard default.
     */
    public static function showLoader(): ?bool
    {
        return false; // disable loader for this widget
    }

    // ... other methods
}
```

#### Resolution order

[](#resolution-order)

1. If the widget class has a `showLoader()` method and it returns a non-null boolean, that value is used.
2. Otherwise the dashboard's `showWidgetLoader()` value is used (default: `true`).

This means a widget can force-enable the loader (`return true`) even when the dashboard default is `false`, or disable it (`return false`) when the dashboard default is `true`.

Templates
---------

[](#templates)

Templates define reusable layout structures for your dashboards. Each template contains **positions** where widgets can be placed.

### How Templates Work

[](#how-templates-work)

- A **Template** is a layout structure that can be shared across multiple dashboards
- **Positions** are areas within the template where widgets are rendered
- Positions can be nested up to 3 levels deep for complex layouts
- Each position spans between 1 and 12 columns in a responsive 12-column grid

### Automatic Defaults

[](#automatic-defaults)

The system simplifies the UI by hiding unnecessary selectors:

- **Template selector**: Only shown when 2 or more templates exist. If only one template exists, it is used automatically.
- **Position selector**: Only shown when the template has multiple positions. If only one position exists, widgets are automatically assigned to it.

This means for simple setups with a single template and single position, users only need to select their widget type — no extra configuration required.

Managing Filters
----------------

[](#managing-filters)

### Defining Filters

[](#defining-filters)

Override `getDashboardFilters()` to return an array of Filament `Field` components:

```
public static function getDashboardFilters(): array
{
    return [
        Select::make('country')
            ->label('Country')
            ->options(Country::pluck('name', 'id'))
            ->multiple()
            ->searchable(),

        DatePicker::make('start_date')
            ->label('Start date'),
    ];
}
```

### Per-Dashboard Filter Session

[](#per-dashboard-filter-session)

Each dashboard stores its filters independently in the session (keyed by page class and dashboard ID). Switching dashboards restores the last-used filters for that dashboard.

### Per-Dashboard Filter Visibility

[](#per-dashboard-filter-visibility)

Admins can toggle which filters are visible for each dashboard from the **Visible filters** tab in the dashboard manager.

### Per-Dashboard Default Values

[](#per-dashboard-default-values)

Default filter values are stored in the dashboard's `filters` JSON column. They are applied on first visit or when the user clicks the reset button.

### Custom Default Value Fields

[](#custom-default-value-fields)

Override `getDefaultFilterSchema()` to provide alternative field types for editing defaults. For example, a relative date selector instead of an absolute date picker:

```
public static function getDefaultFilterSchema(): array
{
    return [
        'period' => Select::make('period')
            ->label('Default period')
            ->options([
                'this_month'   => 'This month',
                'last_month'   => 'Last month',
                'last_7_days'  => 'Last 7 days',
                'last_30_days' => 'Last 30 days',
            ]),
    ];
}
```

Filters not present in this array fall back to their original component from `getDashboardFilters()`.

### Resolving Defaults at Apply Time

[](#resolving-defaults-at-apply-time)

Override `resolveFilterDefaults()` to transform stored defaults into actual filter values:

```
public static function resolveFilterDefaults(array $defaults): array
{
    if (!empty($defaults['period']) && is_string($defaults['period'])) {
        $defaults['period'] = match ($defaults['period']) {
            'this_month'   => now()->startOfMonth()->format('Y-m-d').' - '.now()->format('Y-m-d'),
            'last_30_days' => now()->subDays(29)->format('Y-m-d').' - '.now()->format('Y-m-d'),
            default        => $defaults['period'],
        };
    }

    return $defaults;
}
```

### Accessing Filters in Widgets

[](#accessing-filters-in-widgets)

Widgets access page filters through Filament's `InteractsWithPageFilters` trait:

```
use Filament\Widgets\Concerns\InteractsWithPageFilters;

class MyWidget extends StatsOverviewWidget implements DynamicWidget
{
    use InteractsWithPageFilters;

    protected function getStats(): array
    {
        $country = $this->pageFilters['country'] ?? null;
        // ...
    }
}
```

### Resetting Filters

[](#resetting-filters)

The filter bar includes a reset button. Clicking it calls `resetFilters()`, which re-applies the dashboard's stored defaults (or clears filters if none are configured).

Dashboard User Interface
------------------------

[](#dashboard-user-interface)

### Dashboard Selector

[](#dashboard-selector)

A dropdown button in the page header lets users switch between dashboards. The current dashboard is highlighted with a check icon. An additional **Manage dashboards** entry (visible to editors) opens the management slideover.

[![Dashboard Switcher](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/dashboard-switcher.jpg)](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/dashboard-switcher.jpg)

### Add Widget

[](#add-widget)

The **Add Widget** button (visible to editors on unlocked dashboards) opens a modal with:

- **Title** -- display name for the widget
- **Display title** -- toggle to show/hide the title badge above the widget
- **Widget Type** -- dropdown of all available `DynamicWidget` implementations
- **Size** -- slider from 1 to 12 grid columns (XS to XL)
- **Position** -- select where the widget appears in the template layout (only visible when multiple positions exist)
- **Order** -- choose the widget's position relative to others (visible only when multiple widgets are present in this area)
- **Widget Settings** -- dynamic form section showing the selected widget's `getSettingsFormSchema()`

[![Add Widget](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/edit-add-widget.jpg)](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/edit-add-widget.jpg)

### Widget Wrapper

[](#widget-wrapper)

Each widget is wrapped with a hover overlay revealing edit and delete icon buttons. When **Display title** is enabled, a title badge is shown above the widget.

### Dashboard Manager (Slideover)

[](#dashboard-manager-slideover)

The dashboard manager slideover contains two tabs: **Dashboards** and **Templates**.

#### Dashboards Tab

[](#dashboards-tab)

A reorderable table of all dashboards with:

[![Manage Dashboards](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/manage-dashboards.jpg)](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/manage-dashboards.jpg)

- **Active** toggle -- enable/disable dashboards
- **Locked** toggle -- prevent widget modifications
- **Edit** action -- opens a tabbed modal:
    - **General** -- name, description, template (if multiple exist), roles (if Spatie enabled)
    - **Widgets** -- reorderable list of widgets
    - **Visible filters** -- toggles per filter field
    - **Default values** -- set default filter values
- **Duplicate** action -- deep-copies the dashboard with all widgets
- **Delete** action -- removes the dashboard

[![Edit Dashboard - General](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/edit-add-dashboard-general.jpg)](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/edit-add-dashboard-general.jpg)

[![Edit Dashboard - Visible Filters](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/edit-add-dashboard-visible-filters.jpg)](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/edit-add-dashboard-visible-filters.jpg)

[![Edit Dashboard - Default Values](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/edit-add-dashboard-default-values.jpg)](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/edit-add-dashboard-default-values.jpg)

#### Templates Tab

[](#templates-tab)

Manage layout templates with:

[![Templates List](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/template-grid-list.jpg)](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/template-grid-list.jpg)

- **Preview** action -- visual representation of the template structure with color-coded positions
- **Edit** action -- modify template name and positions:
    - Each position has a **Name** and **Size** (Tiny to Full width)
    - Add nested positions (up to 3 levels)
    - Positions with linked widgets cannot be deleted
- **Duplicate** action -- copy template with all positions
- **Delete** action -- remove template (protected if in use or is default)

Only one template can be marked as **Default** at a time.

[![Edit Template](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/edit-grid-template.jpg)](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/edit-grid-template.jpg)

[![Template Preview](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/template-preview.jpg)](https://raw.githubusercontent.com/MDDev31/filament-dynamic-dashboard/master/doc/img/template-preview.jpg)

### Safety Guards

[](#safety-guards)

- Cannot deactivate or delete the last remaining active dashboard
- Cannot delete the currently viewed dashboard
- Locked dashboards hide the add/edit/delete widget buttons
- Cannot delete the default template
- Cannot delete a template in use by dashboards
- Cannot delete positions that have widgets linked to them

Permissions &amp; Authorization
-------------------------------

[](#permissions--authorization)

### canEdit()

[](#canedit)

Override `canEdit()` to restrict who can manage dashboards and widgets. When `false`, the add widget button, widget edit/delete overlays, and the manage dashboards entry are hidden.

```
public static function canEdit(): bool
{
    return auth()->user()?->hasRole('admin') ?? false;
}
```

### canDisplay()

[](#candisplay)

Override `canDisplay()` to control per-dashboard visibility. The default logic is:

1. Editors (`canEdit() === true`) always see all dashboards
2. If the dashboard model has Spatie roles, check `user->hasAnyRole(dashboard->roles)`
3. Fall back to the page-level `canAccess()`

```
public static function canDisplay(DynamicDashboardModel $dashboard): bool
{
    // Custom logic example
    if ($dashboard->getName() === 'Internal') {
        return auth()->user()?->is_staff ?? false;
    }

    return parent::canDisplay($dashboard);
}
```

### Spatie Permission Integration

[](#spatie-permission-integration)

1. Set `use_spatie_permissions` to `true` in the config
2. The `DashboardWithRoles` model is automatically swapped in (adds the `HasRoles` trait)
3. A **Roles** multi-select appears in the dashboard manager form
4. `canDisplay()` checks `user->hasAnyRole(dashboard->roles)` when roles are assigned

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

[](#configuration)

Publish the config file:

```
php artisan vendor:publish --tag=filament-dynamic-dashboard-config
```

KeyTypeDefaultDescription`dashboard_columns``array``['sm' => 3, 'md' => 6, 'lg' => 12]`Responsive grid breakpoints for the dashboard layout`widget_columns``int``3`Default grid column span for new widgets`use_spatie_permissions``bool``false`Enable Spatie role integrationTranslations
------------

[](#translations)

Supported languages: **English** (`en`), **French** (`fr`), **Spanish** (`es`), **Portuguese** (`pt`), **German** (`de`), **Russian** (`ru`), **Chinese** (`zh`), **Bulgarian** (`bg`), **Croatian** (`hr`), **Danish** (`da`), **Estonian** (`et`), **Finnish** (`fi`), **Greek** (`el`), **Hungarian** (`hu`), **Italian** (`it`), **Dutch** (`nl`), **Polish** (`pl`), **Romanian** (`ro`), **Swedish** (`sv`), **Czech** (`cs`), **Japanese** (`ja`), **Arabic** (`ar`), **Turkish** (`tr`).

Publish translations to customize them:

```
php artisan vendor:publish --tag=filament-dynamic-dashboard-translations
```

All translation keys are namespaced under `filament-dynamic-dashboard::dashboard.*`.

Changelog
---------

[](#changelog)

See [CHANGELOG.md](https://github.com/MDDev31/filament-dynamic-dashboard/blob/master/CHANGELOG.md) for release notes.

Credits
-------

[](#credits)

Special thanks to :

- All the Filament core Team.
- [filament-apex-charts](https://github.com/leandrocfe/filament-apex-charts) by [Leandro Ferreira](https://github.com/leandrocfe) to give me the idea to build this plugin

License
-------

[](#license)

The MIT License (MIT). See [LICENSE.md](https://github.com/MDDev31/filament-dynamic-dashboard/blob/master/LICENSE.md) for details.

###  Health Score

46

—

FairBetter than 93% of packages

Maintenance89

Actively maintained with recent releases

Popularity26

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 60% 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 ~3 days

Total

14

Last Release

66d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7dd673c5f5cbac09bc02db3aed80b168236327e49a379bf5f1ec0823946ea95d?d=identicon)[MDDev31](/maintainers/MDDev31)

---

Top Contributors

[![MDDev31](https://avatars.githubusercontent.com/u/222838434?v=4)](https://github.com/MDDev31 "MDDev31 (3 commits)")[![attargah](https://avatars.githubusercontent.com/u/67326574?v=4)](https://github.com/attargah "attargah (2 commits)")

---

Tags

laraveldashboardfilament

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/mddev31-filament-dynamic-dashboard/health.svg)

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

###  Alternatives

[awcodes/filament-quick-create

Plugin for Filament Admin that adds a dropdown menu to the header to quickly create new items.

246177.6k7](/packages/awcodes-filament-quick-create)[andreia/filament-ui-switcher

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

233.8k](/packages/andreia-filament-ui-switcher)[guava/filament-knowledge-base

A filament plugin that adds a knowledge base and help to your filament panel(s).

206120.5k1](/packages/guava-filament-knowledge-base)[ralphjsmit/laravel-filament-seo

A package to combine the power of Laravel SEO and Filament Admin.

15398.7k10](/packages/ralphjsmit-laravel-filament-seo)[caresome/filament-neobrutalism-theme

A neobrutalism theme for FilamentPHP admin panels

303.2k](/packages/caresome-filament-neobrutalism-theme)[geo-sot/filament-env-editor

Access .env file though Filament admin panel

2432.3k1](/packages/geo-sot-filament-env-editor)

PHPackages © 2026

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