mokhosh/filament-kanban
A Kanban board package for Filament and Laravel. Turn any Eloquent model into a drag-and-drop Kanban board with sortable columns and cards, status transitions, and a clean, customizable UI that integrates seamlessly into your Filament admin panels.
mokhosh/filament-kanban drops a drag-and-drop board into a Filament panel. It ships no tables of its own — it reads and writes columns on a model you already have, which is why setup is mostly wiring.
composer require mokhosh/filament-kanbanclass TasksKanban extends \Mokhosh\FilamentKanban\Pages\KanbanBoard
{
protected static string $model = Task::class;
protected static string $statusEnum = TaskStatus::class; // backed enum, or use a status attribute
protected static string $recordSortAttribute = 'sort';
}
/admin/tasks-kanban.Where to look first: the base KanbanBoard class itself (that is the real API surface — every hook, property, and view name lives there), then the published Blade views under resources/views/vendor/filament-kanban. The README covers the happy path; the base class covers everything you will actually need.
First use case: a Task with Todo / Doing / Done, dragged between columns, with the new status and order persisted on drop. Confirm that write happens before you build anything on top of it — if the enum or sort attribute is misconfigured, the board renders fine and silently no-ops on drop.
Enum columns vs. attribute columns. The enum route is cleaner (type safety, labels for free) and is what most projects should use. Fall back to a plain status attribute + custom column list when statuses come from a database table, are per-tenant, or are workflow-driven rather than hard-coded.
Side effects belong in a hook, not an observer. Status changes triggered by drag-and-drop fire the same model events as any other save, so an observer works — but board-specific concerns (re-sorting, toast notifications, "moved to Done" timestamps) are easier to keep in the page's status-change / sort-change hook, where you still have the old and new values. Overriding those hooks is the single most common customization.
Custom card markup. Publish the views and override the record/card partial rather than trying to configure card content through properties. Keep the card Blade file lean — it renders once per record per column, so an accidental lazy-loading relationship or $record->comments->count() inside it will produce an N+1 the moment a board exceeds a few dozen cards.
Scoping and multi-tenancy. Override the query the board uses (getRecords() and friends) to constrain by tenant, team, or assignee. Boards are conventionally one page per scope; when you need the same board inside a resource (e.g. tasks for a project), mount it as a relation-scoped page rather than duplicating the board class.
Multiple boards, one model. Keep a separate page class per board and give each its own sort scope, or your sort integers from board A will interleave with board B. If they must share a table, prefix the sort attribute or filter by a board discriminator in the query.
Permissions. The board has no built-in authorization beyond Filament's page visibility. Gate the page with canView(), and for read-only roles either hide the page or accept that drags will attempt a write — check update on the model inside your status-change hook and abort there if you need a soft lock.
Testing. These boards are Livewire components; call the move/handle-drop method directly in a Livewire test and assert the model's status and sort columns. That is far more stable than trying to simulate HTML5 drag events.
lockForUpdate — concurrent drags by two admins will otherwise collide.vendor:publish of the views/assets, run php artisan view:clear — stale compiled views are the usual explanation for "my override isn't showing up."How can I help you explore Laravel packages today?