# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Commands ```bash # Development (starts PHP server + queue + logs + Vite concurrently) composer dev # Build assets for production npm run build # Vite dev server only npm run dev # Run all tests composer test php artisan test # Run a single test file php artisan test tests/Feature/ExampleTest.php # Run a single test by name php artisan test --filter=TestName # Migrations php artisan migrate ``` ## Architecture ### Design - Tailwind CSS v4 - Modals sind immer vom Livewire Modals - Kein Inline-Style nur wenn wirklich notwendig. - Immer prüfen das das Style nicht kaputt ist und wenn Icons in Buttons mit Text sind, sind diese immer nebeneinadner Nie übereinander. ### What this is Mailwolt is a self-hosted mail server administration panel (German UI). It manages domains, mailboxes, aliases, DNS records (DKIM/DMARC/SPF/TLSA), TLS, Fail2ban, IMAP, and email quarantine/queues. It also has a mail sandbox for testing Postfix transports. ### Layout & Routing - **`resources/views/layouts/dvx.blade.php`** is the actual app layout (not `app.blade.php`). Livewire full-page components use `#[Layout('layouts.dvx')]`. - Routes are in `routes/web.php` — each page maps directly to a Livewire full-page component via `->name()`. - Navigation structure is driven by `config/ui-menu.php`. - Für den Style wird Tailwind CSS v4 ### Livewire component structure ``` app/Livewire/Ui/ ├── Nx/ — Current production UI (Dashboard, DomainList, MailboxList, AliasList, etc.) ├── Domain/ — Domain modals and DKIM/DNS views ├── Mail/ — Mailbox/alias modals, queue, quarantine ├── Security/ — Fail2ban, SSL, RSpamd, TLS, audit logs ├── System/ — Settings, users, API keys, webhooks, sandbox, backups ├── Search/ — Global search palette modal └── Webmail/ — Webmail-specific components ``` Full-page components live in `Ui/Nx/` and `Ui/System/`, `Ui/Security/`, etc. Modals are always in a `Modal/` subfolder and extend `LivewireUI\Modal\ModalComponent`. ### Modals (wire-elements/modal v2) - Open from **outside** a Livewire component: `onclick="Livewire.dispatch('openModal', {component:'ui.system.modal.my-modal', arguments:{key:value}})"` - Open from **inside** a Livewire component: `$this->dispatch('openModal', component: '...', arguments: [...])` - **Never** use `wire:click="$dispatch('openModal',...)"` outside a Livewire component context — it won't work. - Modal argument keys must match the `mount(int $keyName)` parameter names exactly. - To prevent closing on backdrop/Escape, override in the modal class: ```php public static function closeModalOnClickAway(): bool { return false; } public static function closeModalOnEscape(): bool { return false; } public static function closeModalOnEscapeIsForceful(): bool { return false; } ``` - To force-close the entire modal stack: `$this->forceClose()->closeModal()` ### Livewire dependency injection - **Never** use constructor injection in Livewire components — Livewire calls `new Component()` with no args. - Use `boot(MyService $service)` instead: this is called on every request and supports DI. ### CSS design system The app uses a custom `mw-*` variable and class system defined in `resources/css/app.css` (Tailwind CSS v4, no `tailwind.config.js`): **CSS variables:** - `--mw-bg`, `--mw-bg3`, `--mw-bg4` — background layers - `--mw-b1`, `--mw-b2`, `--mw-b3` — border shades - `--mw-t1` through `--mw-t5` — text shades (t1 = primary, t4/t5 = muted) - `--mw-v`, `--mw-v2`, `--mw-vbg` — purple accent (primary brand color) - `--mw-gr` — green (success) **Reusable component classes:** `.mw-btn-primary`, `.mw-btn-secondary`, `.mw-btn-cancel`, `.mw-btn-save`, `.mw-btn-del`, `.mbx-act-btn`, `.mbx-act-danger`, `.mw-modal-frame`, `.mw-modal-head`, `.mw-modal-body`, `.mw-modal-foot`, `.mw-modal-label`, `.mw-modal-input`, `.mw-modal-error`, `.mbx-badge-mute`, `.mbx-badge-ok`, `.mbx-badge-warn`. ### Services `app/Services/` contains: `DkimService`, `DnsRecordService`, `ImapService`, `MailStorage`, `SandboxMailParser`, `SandboxService`, `TlsaService`, `TotpService`, `WebhookService`. ### API REST API under `/api/v1/` uses Laravel Sanctum. Token abilities map to scopes like `mailboxes:read`, `domains:write`, etc. Defined in `routes/api.php`. ### Sandbox mail system The mail sandbox intercepts Postfix mail via a pipe transport (`php artisan sandbox:receive`). `SandboxRoute` model controls which domains/addresses are intercepted. `SandboxService::syncTransportFile()` writes `/etc/postfix/transport.sandbox` and runs `postmap`. ### Queue & real-time - Queue driver: database (configurable). Jobs in `app/Jobs/`. - Real-time updates use Laravel Reverb + Pusher.js. Livewire polls (`wire:poll.5s`) are used as fallback on some pages.