Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Laravel Filament 3 Custom Resource Guide

By Kokil Thapa | Last reviewed: September 2026

You searched for the filament admin panel Laravel official documentation because the vendor docs explain components well but rarely show how a custom resource fits a real app. Filament 3 turns Eloquent models into admin CRUD through declarative PHP classes. This guide maps the official docs to production patterns I use on Laravel developer in Nepal client work—legal portals, booking systems, and internal tools. Start with the Filament official documentation, then apply the resource patterns below.

Where does the Filament admin panel Laravel official documentation fit custom resources?

Filament splits docs into panels, resources, forms, tables, and actions. Custom resources sit at the centre. Each resource is one PHP class that binds an Eloquent model to admin UI. The official pages describe API surface area. This section shows how those pieces connect on a live project.

Install the panel and read the right doc sections

On Laravel 12 or 13 with PHP 8.3+, install Filament 3 through Composer. Follow the panel installation guide in the vendor docs. Register your panel in a provider class. Set the path, middleware stack, and auth guard there. For framework context, cross-check the Laravel official documentation on service providers and middleware.

composer require filament/filament:"^3.3"
php artisan filament:install --panels

After install, bookmark three doc areas: Resources, Form Builder, and Table Builder. Most custom work happens inside resource classes, not panel boot code. I keep panel providers thin. Heavy logic belongs in resources, policies, or dedicated action classes.

Generate a resource against your model

Every custom resource starts with Artisan. Always pass the model explicitly. Use --generate for a first draft, then audit the output.

php artisan make:filament-resource CaseFile --model=App\\Models\\CaseFile --generate

The generator introspects columns and fillable fields. It creates text inputs by default. You still replace naive fields with Select, DatePicker, FileUpload, or RichEditor where business rules demand it. Never deploy generated schemas without review. Wrong validation on a legal-tech portal can expose fields that should stay internal.

The three methods that define behaviour

A Filament resource exposes three configuration hooks. Treat them as separate concerns:

  • form(Form $form): Form — Create and edit UI. Schema components carry validation through ->rules() or inferred rules.
  • table(Table $table): Table — List view with columns, filters, sorting, row actions, and bulk actions.
  • getRelations(): array — RelationManager classes for nested CRUD on child models.
Filament Resource Structureform()Schema fieldsValidationCreate / Edittable()ColumnsFiltersActionsgetRelations()RelationManagersNested CRUDTabbed UIForm pagesLivewire submitList pagePaginated queryChild tabsScoped modelsEloquent Model + Database
Filament admin panel Laravel official documentation: resource methods map to admin UI and database layers

Keep form() focused on field definitions. Move complex conditionals into custom form components or small helper classes. That discipline stops 800-line resource files. For greenfield admin work, see our custom software development in Nepal service if you want implementation help beyond docs.

How do you handle relationships in Filament 3 custom resources?

Real apps rarely stop at one table. Cases have clients, documents, and invoices. The official docs cover Select, Repeater, and RelationManager separately. Pick the wrong pattern and you get N+1 queries or broken saves.

RelationManagers for independent child records

Generate a manager when child records have their own lifecycle. Documents on a case file fit this model well.

php artisan make:filament-relation-manager CaseFileResource documents title

Register it in getRelations():

public static function getRelations(): array
{
    return [
        DocumentsRelationManager::class,
        HearingsRelationManager::class,
    ];
}

Each manager owns its own form() and table(). Editing a document does not resubmit the parent case. On a notary portal I maintained, this cut edit-page weight because we stopped eager-loading every attachment on the main form.

For belongsTo links, use Select::make('client_id')->relationship('client', 'name'). Enable search and preload for large tables. For small hasMany sets edited with the parent, use Repeater. Invoice line items are a common fit.

Verify inverse relationships on the Eloquent model first. Missing documents() or client() methods produce empty selects and silent save failures. Pair this with Laravel N+1 query detection and fixes when list pages slow down.

Relationship Component ChoiceWhat link type?BelongsToHasMany fewHasMany manySelect->relationship()Searchable FK pickRepeaterInline schemaSaves with parentRelationManagerSeparate tabOwn CRUD cycleOver 10 child rows or heavy files → RelationManagerAlways edited with parent → Repeater
Filament admin panel Laravel official documentation: pick Select, Repeater, or RelationManager by data shape

The Mijar Law Associates client portal uses nested document workflows. RelationManagers kept uploads scoped per case without bloating the parent form.

How do you customize Filament 3 tables and add custom actions?

Default tables work for demos. Production lists need tuned queries, computed columns, and business actions. Most Filament slowness I see starts in the table query, not Livewire rendering.

Eager-load and index sort columns

Every relationship column triggers extra queries unless you eager-load. Override the table query or use ->modifyQueryUsing() with ->with(['client', 'assignedTo']). For computed values, avoid per-row queries inside getStateUsing(). Prefer model accessors backed by joins or cached aggregates.

Add database indexes on filtered and sorted columns. Filament's ->sortable() emits ORDER BY clauses. Without indexes, large tables crawl. Read database indexing for performance before blaming Filament.

Row, header, and bulk actions

Built-in CRUD actions cover basics. Business flows need custom Action classes. Example: generate a PDF brief from a case record.

Action::make('generate_pdf')
    ->label('Download Brief')
    ->icon('heroicon-o-document-arrow-down')
    ->action(function (CaseFile $record) {
        $pdf = PdfGenerator::forCase($record);
        return response()->streamDownload(
            fn () => print($pdf->output()),
            "case-{$record->number}.pdf"
        );
    })
    ->requiresConfirmation()
    ->visible(fn (CaseFile $record) => $record->status === 'approved')

Put authorization in visible() and policy checks, not inside the action body after click. Filament evaluates visibility before render. That matches patterns in Laravel API best practices where gates run before handlers execute.

Action TypeUse CasePerformanceAuth Pattern
Header ActionCreate, export CSV, global importLow — once per pagecan('create') policy
Row ActionEdit, approve, PDF, single deleteMedium — per visible rowcan('update', $record)
Bulk ActionBatch status change, mass assignHigh — collection opscan('deleteAny') or custom
FilterRole-scoped or date filtersVariable — query costGlobal scope or policy scope

Compare Filament with other admin options in Laravel Nova vs Filament vs Backpack if you are still choosing a stack.

How do you implement authorization in Filament 3 resources?

Admin panels fail audits when auth is bolted on late. Filament integrates with Laravel Policies and Spatie Permission. On legal-tech projects I enforce three layers: resource access, record scope, and field visibility.

Resource and record gates

Hide entire sections with canAccess() on the resource class:

public static function canAccess(): bool
{
    return auth()->user()->hasPermissionTo('manage_cases');
}

Wire standard policy methods — viewAny, update, delete — on the model. Filament calls them automatically when configured. For Spatie setup details, see Laravel Spatie Permission role management and policies and gates guide.

Tenancy and field-level control

Multi-tenant apps should use native panel tenancy. Define ->tenant(Company::class) in the panel provider. Queries scope automatically. Stop scattering where('company_id') across resources.

Hide sensitive fields with schema visibility:

TextInput::make('billing_rate')
    ->visible(fn () => auth()->user()->can('view_billing'))
    ->disabled(fn () => ! auth()->user()->can('edit_billing'))
Filament Authorization LayersLayer 1: Resource AccesscanAccess() hides menu and routesPartners only see Financial ReportsLayer 2: Record ScopePolicies + tenancy filter listsStaff see only assigned casesLayer 3: Field VisibilitySchema visible() and disabled()Paralegals skip billing fields
Filament admin panel Laravel official documentation: defense in depth across resource, record, and field layers

Enterprise panels with strict RBAC often need enterprise application development in Nepal level planning before the first resource ships.

How do you debug and optimize Filament 3 resource performance?

Filament hides Livewire and Alpine details. That abstraction helps until something breaks under load. Use a fixed checklist when a resource feels slow or flaky.

Fix slow table loads first

Open Laravel Debugbar on the list page. Twenty-five rows should not trigger fifty queries. Fix order:

  1. Eager-load every relationship used in columns and filters.
  2. Replace expensive getStateUsing() logic with DB aggregates or cached attributes.
  3. Default pagination to 25–50 rows. Drop "show all" on large tables.
  4. Index columns used in ->sortable() and ->searchable().

Forms, uploads, and async work

Large repeaters and file fields can hit max_input_vars or post_max_size. Raise limits in PHP-FPM config when needed. Prefer Spatie Media Library for documents instead of inline base64 uploads.

Queue heavy imports and PDF jobs through Laravel queues with Redis. Blocking HTTP requests on 5,000-row CSV imports kills demos and production alike.

Validate schemas before deploy

Test that required fields reject bad input. Assert authorized roles see actions and hidden fields stay hidden. Filament ships testing helpers compatible with Pest. Pair admin tests with Form Request validation patterns on public-facing APIs sharing the same models.

When debugging JSON payloads from custom actions, a local JSON formatter saves time parsing API responses. Track framework upgrades through Laravel 12 new features so Filament packages stay compatible.

Filament Performance Debug FlowSlow list?Check query countN+1 foundAdd with()Still slowAdd indexesFixedShip itForm timeout?Raise PHP limits + use Media LibraryHeavy import?Dispatch queue jobMeasure → Fix query → Queue heavy work → Test authFollow filament admin panel Laravel official documentation testing notes
Filament admin panel Laravel official documentation: systematic path from slow tables to stable production resources

For a broader Filament walkthrough, read our Laravel Filament admin panel tutorial. The Adventure Third Pole Trek booking system shows Livewire admin patterns on a real Laravel app.

Key Takeaways

  • Start at filamentphp.com/docs, then map Resources, Forms, and Tables docs to your Eloquent models.
  • Generate resources with --model and --generate, but always audit form and table output before deploy.
  • Use RelationManagers for large or independent child data; Select and Repeater for simple links.
  • Eager-load relationships in table queries and index sorted columns to prevent N+1 slowness.
  • Enforce auth at resource, record, and field layers with policies and Spatie Permission.
  • Queue imports and heavy actions; test resources with Pest before production release.

People Also Ask

What is a Filament resource in Laravel?

A Filament resource is a PHP class that connects one Eloquent model to admin CRUD UI. It defines forms for create/edit, tables for listing, and optional RelationManagers for child records. The panel router renders these automatically.

Does Filament 3 work with Laravel 12 and 13?

Yes. Filament 3 supports Laravel 11, 12, and 13 on PHP 8.2 or higher. Laravel 13 requires PHP 8.3 minimum. Check the Filament upgrade guide before bumping framework versions on existing panels.

How do I hide a Filament resource from certain users?

Override canAccess() on the resource class or rely on Laravel Policy viewAny methods. Combine with Spatie roles for menu-level control. Use schema visible() for field-level restrictions inside allowed records.

Where is the official Filament documentation for custom forms and tables?

The filament admin panel Laravel official documentation hosts Form Builder and Table Builder sections under filamentphp.com/docs. Custom resources reference those APIs inside form() and table() methods on your resource class.

Ship production Filament panels with confidence

This guide bridges the gap between the filament admin panel Laravel official documentation and the custom resource patterns production apps need. Generate resources deliberately, choose relationship components by data shape, optimize queries early, and layer authorization before launch. Filament 3 is mature enough for client portals and internal ops when configured with discipline. Need hands-on help building an admin panel for your Laravel app? Contact us to discuss your project, or reach out directly for a quick scoping call. Review modern Laravel architecture best practices to keep the wider app as clean as the panel.

Frequently Asked Questions

Filament 3 is a TALL-stack admin panel builder for Laravel 11 and 12. It generates secure CRUD interfaces, tables, and forms directly from Eloquent models, drastically reducing boilerplate for custom business resources compared to building Blade templates manually.

The package is open-source and free. Development costs depend on complexity; a standard custom resource typically takes 4-8 hours for an experienced developer, costing roughly NPR 20,000–40,000 (USD 150–300) in the Nepal market depending on relation handling and validation logic.

Filament 3 requires PHP 8.2 minimum. It runs perfectly on PHP 8.2, 8.3, and 8.4 with Laravel 11 or 12. You do not need to upgrade to 8.4 solely for Filament compatibility, though 8.3 is currently the most stable production choice for 2026 deployments.

Run php artisan make:filament-resource ResourceName to generate the resource class, list page, edit page, and create page. Define your form schema in the form() method and table columns in the table() method. Filament handles routing, authorization policies, and basic CRUD operations automatically based on these definitions.

Yes, override the getEloquentQuery() method on your ListRecords page class. This allows you to add global scopes, eager load relationships to prevent N+1 issues, or filter records by tenant or user role. In my experience, this is essential for performant tables on large datasets where default queries become slow without explicit optimization.

Use the Select component with multiple() enabled or the CheckboxList component for simple pivots. For pivot data, use Repeater with a relationship() configuration. Always ensure your Eloquent model defines the relationship correctly first. On legal-tech portals I have built, this pattern reliably manages document-category tagging and service-area assignments without custom controllers.

Yes, provided you implement Laravel Policies. Filament respects authorize(), viewAny(), update(), and delete() policy methods by default. Never rely solely on UI hiding; always enforce server-side authorization. For projects like Mijar Law Associates, I combine Filament's native policy integration with Spatie Laravel Permission to ensure strict role-based access control over sensitive case files.

Use Action::make('name') inside the table's actions() array. Define the action logic using ->action(fn ($record) => ...). You can add confirmation dialogs, modal forms, and authorization checks directly. This replaces the need for separate controller endpoints for tasks like approving orders or sending notifications, keeping related logic encapsulated within the resource definition itself.

This usually indicates a missing or misconfigured Policy. Generate one via php artisan make:policy ModelPolicy and register it in AuthServiceProvider or let Laravel auto-discover it. Ensure the authenticated user has the required permissions. During deployment, also verify that opcache is cleared; stale policy caches frequently cause phantom 403s in production environments after code updates.

Enable pagination, avoid loading unnecessary relations, and use database indexes on filtered/sorted columns. Replace text search with full-text indexes if using MySQL 8.0+. Use deferLoading() on heavy tabs. On e-commerce projects like Nepal Gift Card, I found that disabling global counts and using cursor pagination significantly reduced memory usage on inventory tables exceeding 50,000 SKUs.

Absolutely. Filament lives alongside standard Laravel routes and controllers. You can link to external routes from Filament navigation or redirect to Filament resources from traditional Blade pages. They share the same session, auth guard, and middleware stack. This hybrid approach works well when migrating legacy admin panels incrementally rather than rewriting everything at once.

Use FileUpload or SpatieMediaLibraryUpload components with disk('private') for sensitive documents. Configure validation rules for MIME types and size limits. Store files outside public/webroot when possible. For legal portals handling marriage certificates or court documents, I always enforce private storage with signed URLs for download, ensuring files are never publicly accessible even if filenames are guessed.

Use Filament's built-in testing helpers extending Laravel's HTTP tests. Test form submissions, table rendering, and action execution via assertFormSet(), assertTableColumnExists(), and callAction(). Focus on business logic and authorization rather than UI rendering. In practice, testing the underlying Eloquent model and Policy separately provides faster feedback than full browser tests for most resource behaviors.

Publish Filament's translation files via php artisan filament:translations and add ne locale entries. Override static getModelLabel() and getPluralModelLabel() in your resource class for dynamic labels. For bilingual sites serving Nepal audiences, I maintain separate translation keys for legal terms to ensure accurate Nepali terminology in admin interfaces while keeping English fallbacks for developer-facing strings.

Avoid Filament when the interface requires highly custom interactive workflows, real-time collaborative editing, or consumer-facing designs diverging significantly from admin patterns. Filament excels at structured data management but becomes restrictive for unique UX demands. If you find yourself fighting the framework's conventions extensively, a custom Vue or Livewire component with standard Laravel controllers may be more maintainable long-term.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: