Estrutura do Projeto
Entenda a organização de diretórios e arquivos do Filament Core Starter Kit.
Visão Geral
O Starter Kit segue a estrutura padrão do Laravel 12 com extensões específicas do Filament 4 e organização modular.
text
filament-core-starter-kit/
├── app/ # Código da aplicação
├── bootstrap/ # Inicialização do Laravel
├── config/ # Arquivos de configuração
├── database/ # Migrações, seeders, factories
├── public/ # Assets públicos
├── resources/ # Views, CSS, JavaScript
├── routes/ # Definições de rotas
├── storage/ # Arquivos gerados
├── tests/ # Testes automatizados
└── vendor/ # Dependências do ComposerDiretório app/
Estrutura Principal
text
app/
├── Console/ # Comandos Artisan customizados
│ └── Kernel.php
├── Exceptions/ # Handlers de exceções
│ └── Handler.php
├── Filament/ # Recursos do Filament Admin
│ ├── Resources/ # CRUD resources
│ ├── Pages/ # Páginas customizadas
│ └── Widgets/ # Dashboard widgets
├── Http/ # Camada HTTP
│ ├── Controllers/ # Controllers da aplicação
│ ├── Middleware/ # Middlewares HTTP
│ └── Requests/ # Form Requests
├── Models/ # Eloquent Models
│ └── User.php
├── Providers/ # Service Providers
│ ├── AppServiceProvider.php
│ ├── EventServiceProvider.php
│ └── FilamentServiceProvider.php
├── Policies/ # Authorization policies
└── Services/ # Serviços da aplicaçãoapp/Filament/Resources/
Onde ficam os recursos do painel administrativo:
text
app/Filament/Resources/
├── PersonResource.php # Resource principal
├── PersonResource/
│ ├── Pages/
│ │ ├── CreatePerson.php # Página de criação
│ │ ├── EditPerson.php # Página de edição
│ │ └── ListPeople.php # Página de listagem
│ └── RelationManagers/ # Gestores de relações
│ └── ContactsRelationManager.php
├── InvoiceResource.php
└── CommunicationResource.phpExemplo de Resource:
php
// app/Filament/Resources/PersonResource.php
namespace App\Filament\Resources;
use Filament\Resources\Resource;
use App\Models\Person;
class PersonResource extends Resource
{
protected static ?string $model = Person::class;
protected static ?string $navigationIcon = 'heroicon-o-users';
public static function form(Form $form): Form { /* ... */ }
public static function table(Table $table): Table { /* ... */ }
public static function getPages(): array { /* ... */ }
}app/Filament/Widgets/
Widgets do Dashboard:
text
app/Filament/Widgets/
├── PeopleOverview.php # Métricas de pessoas
├── InvoiceChart.php # Gráfico de faturas
└── RecentActivities.php # Atividades recentesExemplo de Widget:
php
// app/Filament/Widgets/PeopleOverview.php
namespace App\Filament\Widgets;
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
class PeopleOverview extends BaseWidget
{
protected function getStats(): array
{
return [
Stat::make('Total de Pessoas', Person::count()),
Stat::make('Novos este mês', Person::thisMonth()->count()),
];
}
}app/Models/
Eloquent Models da aplicação:
text
app/Models/
├── User.php # Modelo de usuário
├── Person.php # Pessoa (física/jurídica)
├── Contact.php # Contatos
├── Document.php # Documentos (CPF, CNPJ)
├── Invoice.php # Faturas
├── InvoiceItem.php # Itens de fatura
└── Communication.php # Mensagens/comunicaçõesExemplo de Model:
php
// app/Models/Person.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
class Person extends Model
{
protected $fillable = ['name', 'type', 'status'];
public function contact(): HasOne
{
return $this->hasOne(Contact::class);
}
public function document(): HasOne
{
return $this->hasOne(Document::class);
}
}app/Services/
Lógica de negócio complexa:
text
app/Services/
├── InvoiceService.php # Lógica de faturas
├── TaxCalculatorService.php # Cálculo de impostos
├── CommunicationService.php # Envio de mensagens
└── DocumentValidatorService.php # Validação de CPF/CNPJExemplo de Service:
php
// app/Services/TaxCalculatorService.php
namespace App\Services;
use App\Models\Invoice;
class TaxCalculatorService
{
public function calculate(Invoice $invoice): array
{
// Lógica complexa de cálculo de impostos
return [
'icms' => $this->calculateICMS($invoice),
'pis' => $this->calculatePIS($invoice),
'cofins' => $this->calculateCOFINS($invoice),
];
}
}Diretório config/
Arquivos Principais
text
config/
├── app.php # Configurações gerais
├── database.php # Configurações de DB
├── filament.php # Configurações do Filament
├── filament-core.php # Configurações dos módulos
├── services.php # Serviços externos (APIs)
└── logging.php # Configurações de logsconfig/filament-core.php
Configuração específica dos módulos:
php
return [
'modules' => [
'invoices' => env('FILAMENT_MODULE_INVOICES', true),
'people' => env('FILAMENT_MODULE_PEOPLE', true),
'communications' => env('FILAMENT_MODULE_COMMUNICATIONS', true),
],
'features' => [
'multi_tenant' => env('FILAMENT_MULTI_TENANT', false),
'api_access' => env('FILAMENT_API_ACCESS', true),
],
];Diretório database/
Estrutura de Migrações
text
database/
├── migrations/
│ ├── 2024_01_01_000000_create_users_table.php
│ ├── 2024_01_02_000000_create_people_table.php
│ ├── 2024_01_02_000001_create_contacts_table.php
│ ├── 2024_01_02_000002_create_documents_table.php
│ ├── 2024_01_03_000000_create_invoices_table.php
│ ├── 2024_01_03_000001_create_invoice_items_table.php
│ └── 2024_01_04_000000_create_communications_table.php
├── seeders/
│ ├── DatabaseSeeder.php
│ ├── UserSeeder.php
│ ├── PeopleSeeder.php
│ └── InvoicesSeeder.php
└── factories/
├── UserFactory.php
├── PersonFactory.php
└── InvoiceFactory.phpExemplo de Migration:
php
// database/migrations/2024_01_02_000000_create_people_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('people', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->enum('type', ['individual', 'company']);
$table->enum('status', ['active', 'inactive'])->default('active');
$table->timestamps();
$table->softDeletes();
});
}
};Diretório resources/
Assets e Views
text
resources/
├── css/
│ └── app.css # Estilos customizados
├── js/
│ ├── app.js # JavaScript principal
│ └── bootstrap.js # Bootstrap do JS
└── views/
├── welcome.blade.php # Página inicial
└── errors/
├── 404.blade.php
└── 500.blade.phpCustomização de CSS
css
/* resources/css/app.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
/* Customizações do Filament */
.filament-brand {
@apply text-purple-700 font-bold;
}Diretório routes/
Definições de Rotas
text
routes/
├── web.php # Rotas web públicas
├── api.php # Rotas de API
└── console.php # Rotas do ArtisanExemplo:
php
// routes/web.php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
// Filament routes são registradas automaticamente em /adminDiretório tests/
Estrutura de Testes
text
tests/
├── Feature/
│ ├── People/
│ │ ├── CreatePersonTest.php
│ │ ├── UpdatePersonTest.php
│ │ └── DeletePersonTest.php
│ ├── Invoices/
│ │ ├── CreateInvoiceTest.php
│ │ └── CalculateTaxTest.php
│ └── Communications/
│ └── SendMessageTest.php
├── Unit/
│ ├── Services/
│ │ ├── TaxCalculatorTest.php
│ │ └── DocumentValidatorTest.php
│ └── Models/
│ ├── PersonTest.php
│ └── InvoiceTest.php
└── TestCase.phpExemplo de Teste:
php
// tests/Feature/People/CreatePersonTest.php
namespace Tests\Feature\People;
use Tests\TestCase;
use App\Models\User;
use App\Models\Person;
class CreatePersonTest extends TestCase
{
public function test_can_create_person(): void
{
$user = User::factory()->create();
$this->actingAs($user)
->post('/admin/people', [
'name' => 'João Silva',
'type' => 'individual',
])
->assertRedirect();
$this->assertDatabaseHas('people', [
'name' => 'João Silva',
]);
}
}Diretório storage/
Estrutura de Storage
text
storage/
├── app/ # Arquivos da aplicação
│ ├── public/ # Arquivos públicos (acessíveis via storage:link)
│ └── private/ # Arquivos privados
├── framework/ # Cache do framework
│ ├── cache/
│ ├── sessions/
│ └── views/
├── logs/ # Logs da aplicação
│ └── laravel.log
└── debugbar/ # Laravel Debugbar (dev only)Link Simbólico
bash
# Criar link público para storage
php artisan storage:link
# Resultado:
# public/storage -> storage/app/publicDiretório public/
Assets Públicos
text
public/
├── index.php # Entry point
├── css/ # CSS compilado (Vite)
├── js/ # JavaScript compilado (Vite)
├── images/ # Imagens estáticas
│ ├── logo.svg
│ └── favicon.ico
├── storage/ # Link simbólico para storage/app/public
└── .htaccess # Configurações ApacheOnde Adicionar Código Customizado
Novos Recursos do Filament
bash
# Criar novo resource
php artisan make:filament-resource Product
# Resultado:
# app/Filament/Resources/ProductResource.php
# app/Filament/Resources/ProductResource/Pages/Novos Models
bash
# Criar model com migration
php artisan make:model Product -m
# Com factory e seeder
php artisan make:model Product -mfs
# Resultado:
# app/Models/Product.php
# database/migrations/xxxx_create_products_table.php
# database/factories/ProductFactory.php
# database/seeders/ProductSeeder.phpNovos Services
bash
# Criar service manualmente
touch app/Services/ProductService.phpphp
// app/Services/ProductService.php
namespace App\Services;
class ProductService
{
public function createProduct(array $data): Product
{
// Lógica de negócio
}
}Novos Widgets
bash
# Criar widget
php artisan make:filament-widget ProductStats
# Resultado:
# app/Filament/Widgets/ProductStats.phpListeners de Eventos
bash
# Criar listener
php artisan make:listener SendProductNotification
# Registrar em EventServiceProviderphp
// app/Providers/EventServiceProvider.php
protected $listen = [
ProductCreated::class => [
SendProductNotification::class,
],
];Convenções de Nomenclatura
Classes
- Models: Singular, PascalCase (
Person,Invoice) - Resources: Sufixo
Resource(PersonResource) - Services: Sufixo
Service(TaxCalculatorService) - Controllers: Sufixo
Controller(ApiController) - Policies: Sufixo
Policy(PersonPolicy)
Arquivos
- Migrations:
yyyy_mm_dd_hhmmss_action_table_name.php - Seeders: PascalCase +
Seeder(PeopleSeeder.php) - Tests: Sufixo
Test(CreatePersonTest.php)
Banco de Dados
- Tabelas: Plural, snake_case (
people,invoice_items) - Colunas: Snake_case (
created_at,person_id) - Foreign Keys:
{model}_id(person_id,invoice_id)
Próximos Passos
Agora que você entende a estrutura:
- 📖 Veja Configurações Detalhadas
- 🚀 Explore Funcionalidades Principais
- 🔧 Aprenda a Estender o Sistema
- 🚢 Prepare o Deploy em Produção