filakitphp/base
Filakit Base is the shared foundation for Filakit PHP packages, providing core service providers, utilities, and conventions for Laravel and Filament projects. It helps developers build consistent, extensible admin panels and modules faster.
Treat this as a fork, not a dependency. There is no composer require filakitphp/base runtime surface worth adopting — it's a Laravel 13 + Filament 3 application scaffold. Day one is:
git clone https://github.com/filakitphp/base my-panel
cd my-panel && rm -rf .git && git init
composer install
bun install # not pnpm — 3.3.56 migrated the toolchain
cp .env.example .env && php artisan key:generate
php artisan migrate --seed
bun run dev & php artisan serve
Log in at /admin. If login fails, the seed user is defined in the seeder — check database/seeders/ before assuming a bug.
Where to look first, in this order:
app/Providers/Filament/*.php — the panel provider is the real entry point. Path, auth guard, middleware, colors, and registered resources/pages/widgets all live here. Read it before touching anything else.app/Filament/Resources/UserResource.php — in 3.3.56 this delegates to filament-user rather than local scaffolding. Read it to understand the auth boundary you're inheriting.extends across app/Filament/ to find what the scaffold already points at, then open those classes. That's your actual API surface; the README is marketing..github/workflows/tests.yml and phpstan.neon — these define the quality bar the fork is expected to hold. Match them before you add features, or you'll be fixing a hundred static-analysis errors later.First use case: scaffold one plain CRUD resource end-to-end against a throwaway table (e.g. Post). php artisan make:filament-resource Post --generate. Deploy it through the panel provider, confirm it appears in nav, list/create/edit work, and phpstan analyse stays green. That single loop exercises the resource base class, the panel config, the auth guard, and CI — everything you'll touch daily. Do it before you design your real schema.
Extend the base resource, don't copy-paste it. The value of the scaffold is that every resource inherits the same nav grouping, table defaults, form layout, and authorization hooks. Your resources should look like:
class PostResource extends BaseResource // whatever the scaffold names it
{
protected static ?string $model = Post::class;
public static function form(Form $form): Form
{
return $form->schema([
// fields only — layout/defaults come from the parent
]);
}
public static function table(Table $table): Table
{
return parent::table($table)->columns([...]);
}
}
If you find yourself overriding form()/table() entirely and re-declaring wrappers, you've defeated the point — either adjust the base class (it's your fork, you own it) or stop extending it.
One panel provider, many resources. Register resources in the provider rather than relying on discovery, once you pass ~10 resources. Explicit registration makes php artisan filament:optimize-style caching predictable and makes it obvious in review what's exposed where.
Keep authorization in policies, wired from the base class. The scaffold centralizes auth via the filament-user integration; resources should defer to policies (PostPolicy) rather than embedding ->visible(fn () => auth()->user()->isAdmin()) on individual fields. Field-level visible() closures scattered across resources are the most common way these panels rot — they become impossible to audit.
Split complex resources early. For anything with more than ~8 fields or role-dependent schemas, use Filament's schema classes (PostForm, PostTable) rather than inlining in the resource. You'll want them for reuse in relation managers and custom pages, and the base classes usually assume this separation.
Widgets: treat the dashboard as a real feature. Base widget classes give you consistent card sizing and polling. Register widgets in the panel provider rather than the discoverWidgets default once you need per-role dashboards — ->widgets([...]) conditional on the authenticated user is far easier to reason about than canView() on every widget.
Local loop you'll actually run daily:
bun run dev # Vite/HMR, must be running
php artisan serve
php artisan make:filament-resource X --generate
php artisan test --filter=Resource
vendor/bin/phpstan analyse
Run PHPStan on every resource you add, not just at PR time. The scaffold ships with a clean baseline; the moment you let it drift, the workflow becomes noise and gets disabled.
Tests: hit the panel as a user. Filament resources are cheap to smoke-test with Livewire's testing helpers — livewire(ListPosts::class)->assertCanSeeTableRecords(...), assertForbidden() for the policy path. Two tests per resource (authorized list renders, unauthorized list is forbidden) catches the auth regressions that this scaffold is most exposed to.
Integration tip: any Filament plugin you add must be compatible with the exact Filament tag the base pins (3.3.x line). Check plugin composer.json constraints against the version in your lockfile before composer require, not after the panel 500s.
The version number is not your semver contract. 3.3.56 tracks Filament's tag, not an API guarantee from filakitphp. A "patch" bump has already shipped a behavioral change (PR #92, filament-user replacing local auth scaffolding). Pin at fork time, diff before rebasing, and never assume 3.3.x → 3.3.y is safe.
filament-user is the highest-blast-radius thing you inherit. The user model, UserResource, and login page now come from that package. Before you build on it, confirm: does it implement the contracts your app needs (FilamentUser, password reset, 2FA, email verification)? If you have existing auth requirements, decide explicitly — adopt it, or rip it out and write your own UserResource. Half-adopting (custom model, package resource) is the failure mode; expect silent authorization gaps rather than loud errors.
bun is a hard toolchain commitment. As of 3.3.56, frontend builds use bun. Consequences you'll hit: pnpm-lock.yaml may be stale or absent, Dockerfiles/CI images invoking pnpm install silently fail or install a stale tree, and onboarding docs from before 3.3.56 are wrong. If your runners don't have bun, fix that before the first deploy — a non-reproducible asset build is the single most likely "works on my machine" divergence here. If you must stay on pnpm, revert the lockfile and package.json scripts deliberately and document it in the fork's README.
PHPStan on PHP 8.4 is a signal, not proof. CI linting 8.4 means the scaffold's own code analyses cleanly there — it does not mean every transitive dependency, plugin, or your code runs correctly on 8.4. Add your own runtime test matrix before claiming 8.4 support.
Dependency-only releases are a treadmill. This tag contains ~14 Dependabot PRs. If your fork auto-merges them, you're shipping unreviewed transitive changes into an admin panel — the highest-privilege surface you own. Configure Dependabot to open PRs, not merge them, and batch-review on a cadence (monthly is fine for a scaffold). Group patch bumps; review minor/major individually.
Debugging the panel: when a resource 404s or nav vanishes, check in this order — (1) is it registered in the panel provider's discoverResources path or explicit list, (2) does the policy's viewAny return true for the current user, (3) does the model implement whatever contract the base resource requires. Filament swallows authorization failures as "not visible," which reads as a registration bug and wastes an hour.
Extension points worth knowing: the base resource class, the panel provider, and the filament-user config (publish it: php artisan vendor:publish --tag=filament-user-config or whatever the tag is — check vendor/). Those three cover ~90% of customization. Reaching for a service provider override outside them usually means you should be editing the base class directly.
Bus factor: development is effectively single-maintainer plus bots. Assume self-support outside core Filament, keep a named owner on your fork, and don't let it drift so far from upstream that the diff becomes unrebaseable — or accept that it's a snapshot and stop tracking upstream entirely. Both are defensible; drifting in between is not.
How can I help you explore Laravel packages today?