From 0d33c99f3045ffee1ac7739efd8ef1b46ba9a144 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 25 Jan 2026 03:19:12 +0200 Subject: [PATCH] Ignore CLAUDE.md and bump build number --- .gitignore | 1 + CLAUDE.md | 2037 ---------------------------------------------------- VERSION | 2 +- 3 files changed, 2 insertions(+), 2038 deletions(-) delete mode 100644 CLAUDE.md diff --git a/.gitignore b/.gitignore index 751ba4a..7032eeb 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ yarn-error.log /.idea /.vscode /.claude +CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 5a05162..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,2037 +0,0 @@ -# Jabali Web Hosting Panel - -A modern web hosting control panel built with Laravel 12, Filament v5, and Livewire 4. - -## Installation Requirements - -**Critical for mail server functionality:** -- Fresh Debian 12/13 installation (no existing web/mail software) -- Domain with glue records pointing to server IP (`ns1.domain.com` → IP) -- PTR record (reverse DNS) pointing to mail hostname (`IP` → `mail.domain.com`) -- Port 25 open (check with VPS provider) - -See README.md "Prerequisites" section for detailed DNS setup instructions. - -### Subdomain Installation - -The panel can be installed on a subdomain (e.g., `panel.example.com`). The installer automatically: - -- Extracts the root domain (`example.com`) for DNS zone creation -- Sets nameservers as `ns1.example.com` and `ns2.example.com` -- Creates an A record for the subdomain (`panel` → server IP) -- Configures email at the root domain (`webmaster@example.com`) - -**Example:** Installing on `panel.example.com` -``` -DNS Zone: example.com -NS Records: ns1.example.com, ns2.example.com -A Records: @, www, panel, mail, ns1, ns2 → server IP -Email: webmaster@example.com -``` - -## Database - -The panel uses **SQLite** by default (not MySQL). The database file is located at: -``` -/var/www/jabali/database/database.sqlite -``` - -## Quick Reference - -```bash -# IMPORTANT: All artisan commands must be run from /var/www/jabali/ -cd /var/www/jabali - -# Development -composer dev # Start all dev servers (artisan, queue, pail, vite) -composer test # Run PHPUnit tests -./vendor/bin/pint # Format PHP code -php artisan serve # Web server only -php artisan tinker # Interactive REPL - -# Production -php artisan migrate # Run migrations -php artisan config:cache # Cache configuration -php artisan route:cache # Cache routes -``` - -## Git Workflow - -**Important:** Only push to git when explicitly requested by the user. Do not auto-push after commits. - -### Version Numbers - -**IMPORTANT:** Before every push, bump the `VERSION` in the `VERSION` file: - -```bash -# VERSION file format: -VERSION=0.9-rc - -# Bump before pushing: -# 0.9-rc → 0.9-rc1 → 0.9-rc2 → 0.9-rc3 → ... -``` - -| Field | When to Bump | Format | -|-------|--------------|--------| -| `VERSION` | Every push | `0.9-rc`, `0.9-rc1`, `0.9-rc2`, ... | - -## Test Server - -```bash -# SSH Access -ssh test-server - -# IMPORTANT: When running git or artisan commands on test server, -# always cd to /var/www/jabali first: -ssh test-server "cd /var/www/jabali && git pull" -ssh test-server "cd /var/www/jabali && php artisan optimize:clear" -``` - -| Panel | URL | Email | Password | -|-------|-----|-------|----------| -| Admin | https://mx.jabali-panel.com/jabali-admin/ | admin@mx.jabali-panel.com | PycpS1dUuLvxMMQs | -| User | https://mx.jabali-panel.com/jabali-panel/ | user@jabali-panel.com | PycpS1dUuLvxMMQs | -| Webmail | https://mx.jabali-panel.com/webmail/ | (use mailbox credentials) | | - -## Project Structure - -``` -/var/www/jabali/ -├── app/ -│ ├── Filament/ -│ │ ├── Admin/ # Admin panel (route: /admin) -│ │ │ ├── Pages/ # Admin pages (Dashboard, Services, etc.) -│ │ │ ├── Resources/# Admin resources (Users) -│ │ │ └── Widgets/ # Admin widgets (Stats, Disk, Network) -│ │ └── Jabali/ # User panel (route: /panel) -│ │ ├── Pages/ # User pages (Domains, Email, WordPress, etc.) -│ │ └── Widgets/ # User widgets (Stats, Disk, Domains) -│ ├── Models/ # Eloquent models (22 models) -│ ├── Services/ # Business logic services -│ └── Console/Commands/ # Artisan commands -├── bin/ -│ ├── jabali-agent # Privileged operations daemon (runs as root) -│ └── screenshot # Chromium screenshot capture script -├── config/ # Laravel config files -│ └── languages.php # Supported languages configuration -├── database/migrations/ # Database migrations -├── lang/ # Translation files (JSON) -│ ├── en.json # English (base) -│ ├── es.json # Spanish -│ ├── fr.json # French -│ ├── ru.json # Russian -│ ├── pt.json # Portuguese -│ ├── ar.json # Arabic (RTL) -│ └── he.json # Hebrew (RTL) -└── resources/views/filament/ # Blade templates for Filament pages -``` - -## Architecture - -### Two Panels -- **Admin Panel** (`/admin`): Server-wide management, user administration -- **User Panel** (`/panel`): Per-user domain, email, database management - -### Privileged Agent -The `bin/jabali-agent` daemon runs as root and handles operations requiring elevated privileges: -- System user creation/deletion -- Domain/vhost configuration -- Email (Postfix/Dovecot) management -- SSL certificate operations -- Database operations -- Backup operations - -Communication via Unix socket at `/var/run/jabali/agent.sock`. - -### Key Services -- **AgentClient**: PHP client for communicating with jabali-agent -- **AdminNotificationService**: System notifications (SSL, backups, quotas) - -### Self-Healing Services -The `bin/jabali-health-monitor` daemon automatically monitors and restarts critical services when they fail. - -**Monitored Services:** -- nginx, mariadb, jabali-agent, php-fpm -- postfix, dovecot, named (if installed) -- redis-server, fail2ban (if installed) - -**Features:** -- Checks services every 30 seconds -- Automatic restart on failure (up to 3 attempts) -- Email notifications via `AdminNotificationService` -- Systemd restart policies as backup protection - -**Files:** -| File | Purpose | -|------|---------| -| `bin/jabali-health-monitor` | Health monitoring daemon | -| `/etc/systemd/system/jabali-health-monitor.service` | Systemd service unit | -| `/var/log/jabali/health-monitor.log` | Event log | -| `/var/run/jabali/health-monitor.state` | Service state tracking | - -**Commands:** -```bash -# Check status -systemctl status jabali-health-monitor - -# View logs -journalctl -u jabali-health-monitor -f - -# Manual notification test -php artisan notify:service-health down nginx --description="Web Server" -``` - -**Notification Setting:** `notify_service_health` in dns_settings table (Admin > Server Settings) - -### Admin Notifications & Monitoring - -The system sends email notifications to configured admin recipients for various events. - -**Configuration:** Admin > Server Settings > Notifications tab - -**Notification Types:** -| Type | Setting | Description | -|------|---------|-------------| -| SSL Errors | `notify_ssl_errors` | Certificate errors and expiration warnings | -| Backup Failures | `notify_backup_failures` | Failed scheduled backups | -| Disk Quota | `notify_disk_quota` | Users reaching 90% quota | -| Login Failures | `notify_login_failures` | Brute force and Fail2ban alerts | -| SSH Logins | `notify_ssh_logins` | Successful SSH login alerts | -| System Updates | `notify_system_updates` | Panel update availability | -| Service Health | `notify_service_health` | Service failures and auto-restarts | -| High Load | `notify_high_load` | Server load exceeds threshold | - -**Notification Log:** -All sent notifications are logged in `notification_logs` table and viewable in Admin > Server Settings > Notifications tab. - -**High Load Monitoring:** -- Monitors server load average every minute via `jabali-health-monitor` -- Configurable threshold (default: 5.0) and duration (default: 5 minutes) -- Sends alert when load exceeds threshold for configured duration -- Settings: `load_threshold`, `load_alert_minutes` in dns_settings - -**Commands:** -```bash -# Manual high load notification test -php artisan notify:high-load - -# Test email -# Use "Send Test Email" button in Server Settings > Notifications -``` - -### Backup System - -The panel provides comprehensive backup functionality for both users and administrators. - -**Backup Types:** -| Type | Description | Storage | -|------|-------------|---------| -| User Backup | Single user's domains, databases, mailboxes | `/home/{user}/backups/` | -| Server Backup (Full) | All users as tar.gz archive | `/var/backups/jabali/` | -| Server Backup (Incremental) | Rsync to remote destination | Remote SFTP/NFS | - -**Admin Backup Features:** -- **Create Server Backup**: Backup all users or selected users -- **Restore Backup**: Selective restore with modal UI -- **Download Backup**: Download local backups (creates zip for directories) - -**Restore Options:** -| Option | Description | -|--------|-------------| -| Website Files | Restore domain files to `/home/{user}/domains/` | -| Databases | Restore MySQL databases with security sanitization | -| MySQL Users | Restore MySQL users and their permissions | -| Mailboxes | Restore email mailboxes and messages | -| SSL Certificates | Restore SSL certificates for domains | -| DNS Zones | Restore DNS zone files | - -**Backup Contents:** -``` -backup_folder/ -├── manifest.json # Backup metadata -├── {username}.tar.gz # Per-user archive containing: -│ ├── files/ # Domain files -│ │ └── {domain}/ -│ ├── mysql/ # Database dumps -│ │ ├── {database}.sql.gz -│ │ └── users.sql # MySQL users and grants -│ ├── mail/ # Mailbox data -│ │ └── {domain}/{user}/ -│ ├── ssl/ # SSL certificates -│ │ └── {domain}/ -│ └── dns/ # DNS zone files -│ └── {domain}.zone -``` - -**Security Validations (Restore):** -The backup restore process includes comprehensive security checks to prevent privilege escalation: - -| Check | Description | -|-------|-------------| -| Database Prefix | Only restore databases matching user's prefix (`{username}_*`) | -| MySQL Users | Only restore users with correct prefix, block global grants | -| SQL Sanitization | Remove DEFINER, GRANT, SET GLOBAL from dumps | -| Domain Ownership | Verify user owns domains before restoring files/SSL/DNS | -| Symlink Prevention | Remove dangerous symlinks pointing outside backup | -| Path Traversal | Block `..` sequences in paths | -| DNS Validation | Validate zone files with `named-checkzone` | - -**Agent Actions:** -``` -backup.create - Create user backup -backup.restore - Restore backup with selective options -backup.get_info - Get backup manifest/contents -backup.create_server - Create server-wide backup -backup.delete - Delete backup file -backup.upload_remote - Upload backup to remote destination -backup.download_remote - Download backup from remote -backup.incremental - Create incremental backup via rsync -backup.test_destination - Test remote backup destination -``` - -**Download Route:** -``` -GET /jabali-admin/backup-download?id={backup_id} # Admin (requires is_admin) -GET /jabali-panel/backup-download?path={base64} # User (validates ownership) -``` - -**Files:** -| File | Purpose | -|------|---------| -| `app/Filament/Admin/Pages/Backups.php` | Admin backup management UI | -| `app/Filament/Jabali/Pages/Backups.php` | User backup management UI | -| `app/Http/Controllers/BackupDownloadController.php` | Download handlers | -| `bin/jabali-agent` | Backup/restore implementation | -| `/var/log/jabali/agent.log` | Security audit log for blocked operations | - -### DNSSEC Support - -DNSSEC (Domain Name System Security Extensions) adds cryptographic signatures to DNS records. - -**Management:** Admin > Server Settings > DNS tab > DNSSEC section - -**Features:** -- Enable/disable DNSSEC per domain -- Automatic KSK (Key Signing Key) and ZSK (Zone Signing Key) generation -- Uses ECDSAP256SHA256 algorithm -- Auto-generates DS records for registrar configuration -- Inline zone signing with auto-dnssec maintain - -**Agent Actions:** -``` -dns.enable_dnssec - Generate keys and sign zone -dns.disable_dnssec - Remove keys and unsign zone -dns.get_dnssec_status - Check DNSSEC status and keys -dns.get_ds_records - Get DS records for registrar -``` - -**Files:** -| Path | Description | -|------|-------------| -| `/etc/bind/keys/{domain}/` | DNSSEC keys directory | -| `/etc/bind/zones/db.{domain}` | Unsigned zone file | -| `/etc/bind/zones/db.{domain}.signed` | Signed zone file | - -**Setup Process:** -1. Enable DNSSEC for domain in Server Settings -2. Copy DS record from modal -3. Add DS record to domain registrar -4. Wait for DNS propagation (up to 48 hours) - -### Test Credentials -| Panel | URL | Email | Password | -|-------|-----|-------|----------| -| Admin | `https://jabali.lan/jabali-admin` | `admin@jabali.lan` | `123123123` | -| User | `https://jabali.lan/jabali-panel` | `user@jabali.lan` | `wjqr9t6Z#%r&@C$4` | - -## Models - -| Model | Table | Description | -|-------|-------|-------------| -| User | users | Panel users (system users) | -| Domain | domains | Hosted domains | -| EmailDomain | email_domains | Email-enabled domains | -| Mailbox | mailboxes | Email mailboxes | -| EmailForwarder | email_forwarders | Email forwarding rules | -| DnsRecord | dns_records | DNS zone records | -| DnsSetting | dns_settings | Key-value settings store | -| SslCertificate | ssl_certificates | SSL/TLS certificates | -| MysqlCredential | mysql_credentials | Database credentials | -| Backup | backups | User backups | -| BackupSchedule | backup_schedules | Scheduled backups | -| BackupDestination | backup_destinations | Remote backup targets | -| CronJob | cron_jobs | User cron jobs | -| AuditLog | audit_logs | Admin audit trail | -| NotificationLog | notification_logs | Admin notification history | - -## Filament Pages - -### Admin Panel -- Dashboard, Services, ServerStatus, ServerSettings -- SslManager, PhpManager, EmailSettings, DnsZones -- Backups, AuditLogs, Fail2ban, ClamAV, Security, ServerImports - -### User Panel -- Dashboard, Domains, DnsRecords, Files -- Email, WordPress, Databases, Ssl -- Backups, CronJobs, SshKeys, PhpSettings, Logs - -## Dashboard Configurations - -### Admin Dashboard (`/jabali-admin`) - -**Location:** `App\Filament\Admin\Pages\Dashboard` - -**Header Widgets:** -- `DashboardStatsWidget` - Stats cards showing Users, Domains, Mailboxes, Databases, SSL Certificates - - Uses `` components with icon, value (bold), label - - Responsive: 1 col mobile, 2 cols tablet, 5 cols desktop - -**Schema Components:** -- `RecentActivityTable` - Embedded audit log table via `EmbeddedTable::make()` - -**Header Actions:** -- Refresh - Reloads the page -- Setup Wizard - Onboarding modal (visible until completed) -- Take Tour - Starts the admin panel tour - -**Files:** -| File | Purpose | -|------|---------| -| `app/Filament/Admin/Pages/Dashboard.php` | Dashboard page class | -| `app/Filament/Admin/Widgets/DashboardStatsWidget.php` | Stats widget | -| `resources/views/filament/admin/widgets/dashboard-stats.blade.php` | Stats template | -| `app/Filament/Admin/Widgets/Dashboard/RecentActivityTable.php` | Activity table widget | - -### User Dashboard (`/jabali-panel`) - -**Location:** `App\Filament\Jabali\Pages\Dashboard` - -**Widgets (in order):** -1. `StatsOverview` - Stats cards showing Domains, Mailboxes, Databases, SSL Certificates - - Responsive: 1 col mobile, 2 cols tablet, 4 cols desktop -2. `DiskUsageWidget` - Disk quota visualization with progress bar -3. `DomainsWidget` - Recent domains table with SSL status -4. `MailboxesWidget` - Recent mailboxes table -5. `RecentBackupsWidget` - Latest backups table - -**Layout:** 2-column responsive grid (1 col mobile, 2 cols desktop) - -**Subheading:** Personalized welcome message ("Welcome back, {name}!") - -**Files:** -| File | Purpose | -|------|---------| -| `app/Filament/Jabali/Pages/Dashboard.php` | Dashboard page class | -| `app/Filament/Jabali/Widgets/StatsOverview.php` | Stats widget | -| `resources/views/filament/jabali/widgets/stats-overview.blade.php` | Stats template | -| `app/Filament/Jabali/Widgets/DiskUsageWidget.php` | Disk usage widget | -| `app/Filament/Jabali/Widgets/DomainsWidget.php` | Domains table widget | -| `app/Filament/Jabali/Widgets/MailboxesWidget.php` | Mailboxes table widget | -| `app/Filament/Jabali/Widgets/RecentBackupsWidget.php` | Backups table widget | - -## Agent Actions - -The jabali-agent supports these action categories: - -``` -user.* - System user management -domain.* - Domain/vhost operations -wp.* - WordPress installation/management -email.* - Email domain/mailbox operations -mysql.* - Database operations -dns.* - DNS zone management (includes DNSSEC) -php.* - PHP version management -ssl.* - SSL certificate operations -backup.* - Backup/restore operations (see Backup System section) -service.* - System service control -ufw.* - Firewall management -file.* - File operations -ssh.* - SSH key management -cron.* - Cron job management -quota.* - Disk quota management -clamav.* - Antivirus scanning -metrics.* - System metrics -scanner.* - Security scanning (Lynis, Nikto) -logs.* - Log access -redis.* - Redis user management -``` - -**Detailed Action Reference:** - -| Action | Parameters | Description | -|--------|------------|-------------| -| `dns.enable_dnssec` | `domain` | Generate keys and sign zone | -| `dns.disable_dnssec` | `domain` | Remove keys and unsign zone | -| `dns.get_dnssec_status` | `domain` | Check DNSSEC status and keys | -| `dns.get_ds_records` | `domain` | Get DS records for registrar | -| `backup.create` | `username`, `options` | Create user backup | -| `backup.restore` | `username`, `backup_path`, `restore_*` | Restore with selective options | -| `backup.get_info` | `backup_path` | Get backup manifest | -| `backup.create_server` | `path`, `options` | Create server backup | -| `backup.delete` | `path` | Delete backup | -| `backup.upload_remote` | `local_path`, `config` | Upload to remote | -| `backup.download_remote` | `remote_path`, `local_path`, `config` | Download from remote | -| `backup.incremental` | `config`, `options` | Incremental rsync backup | -| `backup.test_destination` | `config` | Test remote destination | -| `backup.delete_remote` | `remote_path`, `config` | Delete backup from remote | - -## Backup System - -The backup system supports both user-level and server-wide backups with local and remote storage. - -### Backup Types - -| Type | Description | Storage | -|------|-------------|---------| -| **Full (tar.gz)** | Complete archive of all data | Local or remote | -| **Incremental (rsync)** | Space-efficient with hard links | Remote only (SFTP/NFS) | - -### Remote Destinations - -Supported destination types: -- **SFTP** - SSH-based file transfer to remote servers -- **NFS** - Network File System mounts -- **S3** - S3-compatible object storage (AWS, MinIO, etc.) - -### Backup Schedules & Retention - -Scheduled backups run via the `backups:run-schedules` artisan command (called by cron). Each schedule has: -- **Frequency**: Hourly, daily, weekly, or monthly -- **Retention Count**: Number of backups to keep (default: 7) -- **Destination**: Local or remote storage - -**Retention Policy:** -- Applied automatically after each backup completes -- Deletes oldest backups beyond the retention count -- Works for both local files and remote destinations -- Implemented in `App\Jobs\RunServerBackup::applyRetention()` - -**Important:** The queue worker must be running for scheduled backups and retention: -```bash -systemctl status jabali-queue # Check status -systemctl restart jabali-queue # Restart to pick up code changes -``` - -### Backup Files - -| Path | Description | -|------|-------------| -| `/var/backups/jabali/` | Default server backup location | -| `/home/{user}/backups/` | User backup location | -| `metadata/panel_data.json` | Panel database records (domains, mailboxes, etc.) | -| `mysql/` | Database dumps (.sql.gz) | -| `zones/` | DNS zone files | -| `ssl/` | SSL certificates | -| `mail/` | Mailbox data | - -### Related Models - -- `Backup` - Individual backup records -- `BackupSchedule` - Schedule configuration with retention settings -- `BackupDestination` - Remote storage configuration - -### Related Jobs - -- `RunServerBackup` - Executes backup and applies retention -- `IndexRemoteBackups` - Indexes backups on remote destinations - -## Security Features - -### Security Page (Admin) - -Located at `/jabali-admin/security`, provides: -- **Overview** - System security status and recent audit logs -- **Firewall** - UFW rules management -- **Fail2ban** - Intrusion prevention with jail management -- **Antivirus** - ClamAV scanning -- **SSH** - SSH hardening settings -- **Vulnerability Scanner** - Security scanning tools - -### Security Scanning Tools - -| Tool | Purpose | Installation | -|------|---------|--------------| -| **Lynis** | System security auditing | Pre-installed | -| **Nikto** | Web server vulnerability scanner | `/opt/nikto` (GitHub clone) | -| **WPScan** | WordPress vulnerability scanner | Ruby gem | - -**Nikto Configuration:** -- Installed from GitHub at `/opt/nikto` -- Symlinked to `/usr/local/bin/nikto` -- Called with full path in timeout commands (PATH restriction) - -**WPScan Configuration:** -- Cache directory: `/var/www/.wpscan` (owned by www-data) -- Run with `HOME=/var/www` environment variable -- Version displayed without ASCII banner using `grep -i 'version'` - -### Audit Logs - -All administrative actions are logged to the `audit_logs` table. - -**Logged Events:** -- Authentication (login, logout, login_failed) -- CRUD operations on domains, mailboxes, users -- System configuration changes -- Security-related actions - -**Audit Log Retention:** -- Configured via `audit_log_retention_days` setting (default: 90 days) -- Pruned daily at 2:00 AM via scheduled task -- Method: `AuditLog::prune()` - -**Viewing Logs:** -- Admin Panel: Security page → Overview tab (paginated table) -- Direct page: `/jabali-admin/audit-logs` (hidden from sidebar) - -### Related Files - -| File | Description | -|------|-------------| -| `app/Models/AuditLog.php` | Audit log model with prune method | -| `app/Filament/Admin/Pages/Security.php` | Security dashboard | -| `app/Filament/Admin/Widgets/Security/AuditLogsTable.php` | Audit logs table widget | -| `routes/console.php` | Scheduled audit log pruning | - -## Code Style - -- PHP 8.2+ with strict types -- Follow Laravel conventions -- Use `DnsSetting::get()` / `DnsSetting::set()` for key-value storage -- All privileged operations go through jabali-agent - -## Filament v4 UI Guidelines - -**CRITICAL: Build using ONLY Filament v4 native components and styles with proper spacing. Always use pure Filament native components with proper icons and colors.** - -### Architecture Guidelines - -1. **Use Filament Resources for Eloquent Models**: When data is backed by an Eloquent model, prefer creating a Filament Resource (`php artisan make:filament-resource`) over custom pages. - -2. **Use Tables for List Data**: When displaying list data (arrays or collections), ALWAYS use proper Filament tables via `EmbeddedTable::make()` or the `HasTable` trait. - -3. **Use Schema-based Pages for Complex UIs**: For pages with multiple sections, tabs, and mixed content (forms + tables + stats), use Schema-based pages with embedded table widgets. - -4. **Prefer Existing Patterns**: Look at existing pages in the codebase (e.g., `Security.php`, `DnsRecords.php`, `SshKeys.php`) for examples of how to implement similar features. - -### Absolute Rules (NO EXCEPTIONS) -- **NO custom HTML** - Never use raw `
`, ``, `

`, `

    ` etc. in Filament pages -- **NO inline styles** - Never use `style="..."` attributes -- **NO custom CSS** - Never create CSS files for Filament components -- **NO custom blade templates** - Don't create View components with custom HTML for UI elements -- **USE Filament components** - Sections, badges, buttons, tables, infolists, stats widgets, grids -- **USE proper icons** - Always use `->icon('heroicon-o-*')` on sections and actions -- **USE proper colors** - Always use `->iconColor('success'|'danger'|'warning'|'gray')` for status indication -- **USE Tailwind classes** - Only when absolutely necessary for minor adjustments -- **MUST be responsive** - All pages must work on mobile, tablet, and desktop - -### Allowed Components -Use these Filament native components exclusively: - -| Category | Components | -|----------|------------| -| Layout | `Section::make()`, `Grid::make()`, `Group::make()`, `Tabs::make()` | -| Display | `Text::make()`, ``, `` | -| Actions | `Actions::make()`, `Action::make()`, `` | -| Forms | TextInput, Select, Toggle, FileUpload, Checkbox, etc. | -| Data | Tables, Infolists, Stats Widgets, `EmbeddedTable::make()` | -| Feedback | ``, Notifications | - -### Tables with Array Data (IMPORTANT) - -When displaying list data, **ALWAYS use proper Filament tables**, not Sections or custom HTML. Use `EmbeddedTable::make()` to embed table widgets within Schema-based pages. - -**Creating a Self-Refreshing Table Widget:** - -For tables with actions that modify data (enable/disable, delete, etc.), the widget should reload its own data directly rather than dispatching events to the parent (which causes full page re-renders). - -```php -send('some.action', []); - if ($result['success'] ?? false) { - $this->items = $result['items'] ?? []; - $this->resetTable(); // Force table to re-render with new data - } - } catch (\Exception $e) { - // Keep existing data on error - } - } - - public function makeFilamentTranslatableContentDriver(): ?\Filament\Support\Contracts\TranslatableContentDriver - { - return null; - } - - public function table(Table $table): Table - { - return $table - ->records(fn () => $this->items) - ->columns([ - TextColumn::make('name')->label(__('Name'))->searchable(), - IconColumn::make('enabled') - ->label(__('Status')) - ->boolean() - ->trueIcon('heroicon-o-check-circle') - ->falseIcon('heroicon-o-x-circle') - ->trueColor('success') - ->falseColor('gray'), - ]) - ->actions([ - Action::make('toggle') - ->label(fn (array $record): string => ($record['enabled'] ?? false) ? __('Disable') : __('Enable')) - ->icon(fn (array $record): string => ($record['enabled'] ?? false) ? 'heroicon-o-x-circle' : 'heroicon-o-check-circle') - ->color(fn (array $record): string => ($record['enabled'] ?? false) ? 'danger' : 'success') - ->action(function (array $record): void { - try { - $agent = new AgentClient(); - $result = $agent->send('item.toggle', ['id' => $record['id']]); - - if ($result['success'] ?? false) { - Notification::make() - ->title(__('Status updated')) - ->success() - ->send(); - - // Reload data directly - don't dispatch events to parent - $this->reloadData(); - } else { - throw new \Exception($result['error'] ?? __('Operation failed')); - } - } catch (\Exception $e) { - Notification::make() - ->title(__('Error')) - ->body($e->getMessage()) - ->danger() - ->send(); - } - }), - ]) - ->striped() - ->emptyStateHeading(__('No items')) - ->emptyStateIcon('heroicon-o-inbox'); - } - - public function render() - { - return $this->getTable()->render(); - } -} -``` - -**Embedding Table in Schema:** -```php -use Filament\Schemas\Components\EmbeddedTable; -use App\Filament\Admin\Widgets\Security\MyDataTable; - -// In your page's schema -Section::make(__('Data List')) - ->icon('heroicon-o-list-bullet') - ->schema([ - EmbeddedTable::make(MyDataTable::class, ['items' => $this->items]), - ]) -``` - -**Key Points:** -- Implement `HasTable`, `HasSchemas`, and `HasActions` interfaces -- Use `InteractsWithTable`, `InteractsWithSchemas`, and `InteractsWithActions` traits -- Use `->records(fn () => $this->arrayData)` for array/collection data -- Use `->query(Model::query())` for Eloquent models -- Use `->actions([])` for row actions on array-based tables -- Always implement `makeFilamentTranslatableContentDriver()` returning null -- Return `$this->getTable()->render()` in render method (NOT `view('filament-tables::index')`) -- Import actions from `Filament\Actions\Action` (NOT `Filament\Tables\Actions\Action`) -- **After modifying data, call `$this->resetTable()` to force the table to re-render** -- **Reload data directly in the widget rather than dispatching events to parent** (avoids full page re-renders) - -### Section with Icons and Colors -Always use Section's native icon and color support: -```php -use Filament\Schemas\Components\Section; - -// Status card with icon and color -Section::make(__('Active')) - ->description(__('Firewall')) - ->icon('heroicon-o-shield-check') - ->iconColor('success') // success, danger, warning, gray - -// Section with header actions -Section::make(__('Settings')) - ->icon('heroicon-o-cog') - ->headerActions([ - Action::make('save')->label(__('Save')), - ]) - ->schema([...]) -``` - -### Responsive Grid Layout -Use Grid with responsive column configuration: -```php -use Filament\Schemas\Components\Grid; -use Filament\Schemas\Components\Section; - -// 3-column responsive grid for stat cards -Grid::make(['default' => 1, 'sm' => 3]) - ->schema([ - Section::make(__('Active')) - ->description(__('Firewall')) - ->icon('heroicon-o-shield-check') - ->iconColor('success'), - Section::make('0') - ->description(__('IPs Banned')) - ->icon('heroicon-o-lock-closed') - ->iconColor('success'), - Section::make('0') - ->description(__('Threats')) - ->icon('heroicon-o-bug-ant') - ->iconColor('gray'), - ]) -``` - -### Stats Overview Widget Pattern - -For dashboard stats (domains count, mailboxes count, etc.), use a custom Widget with `` components in a blade template. - -**Widget class:** -```php - $userCount, - 'label' => __('Users'), - 'icon' => 'heroicon-o-users', - 'color' => 'primary', - ], - [ - 'value' => $domainCount, - 'label' => __('Domains'), - 'icon' => 'heroicon-o-globe-alt', - 'color' => 'success', - ], - // ... more stats - ]; - } -} -``` - -**Blade template** (`resources/views/filament/{panel}/widgets/dashboard-stats.blade.php`): -```blade - - -
    - @foreach($this->getStats() as $stat) - - - {{ $stat['value'] }} - - {{ $stat['label'] }} - - @endforeach -
    -
    -``` - -**Key points:** -- Use custom Widget extending `Filament\Widgets\Widget` with a blade view -- Use `` for each stat card with icon and icon-color -- Value goes in `heading` slot with bold styling, label goes in `description` slot -- Use CSS media queries in `