Files
preregister/.cursorrules

78 lines
3.5 KiB
Plaintext

# PreRegister — Cursor Rules
## Project Context
PreRegister is a Laravel 11 application for festival ticket pre-registration. Visitors can sign up on branded landing pages to get early/discounted ticket access. Subscriber data is stored locally and optionally synced to Mailwizz (email marketing platform).
## Tech Stack (strict — no alternatives)
- **Backend:** PHP 8.2+ / Laravel 11 / MySQL 8
- **Frontend:** Blade + Tailwind CSS 3 + Alpine.js 3
- **Auth:** Laravel Breeze (Blade stack)
- **No:** React, Vue, Livewire, Inertia, or any JS framework
## PHP Coding Standards
- Every file starts with `declare(strict_types=1);`
- Type hints on all method parameters, return types, and properties
- Follow PSR-12 coding standards
- Use `$fillable` (never `$guarded = []`) on every model
- Use Form Request classes for validation — never validate inline in controllers
- Controllers are thin: business logic goes in Service classes or Jobs
- Use Laravel's `encrypted` cast for sensitive data (API keys)
- Use `DB::transaction()` for multi-step database operations
- No `dd()` in committed code — use `Log::` facade instead
- Comments explain *why*, not *what*
## Laravel Conventions
- Route model binding with explicit column: `Route::get('/r/{page:slug}', ...)`
- Policies for authorization (not inline Gate checks)
- Blade components (`<x-component>`) for reusable UI
- Form Requests in `app/Http/Requests/`
- Service classes in `app/Services/`
- Queued Jobs for external API calls (Mailwizz)
- Config values via `config()` helper, never `env()` outside config files
## Database
- Docker MySQL on localhost:3306 (db: preregister, user: preregister, pass: preregister)
- Use `$table->id()` (unsigned big int) for all PKs
- UUID slugs for public-facing URLs
- Always run `php artisan migrate` after creating/changing migrations
- Run `php artisan migrate:fresh --seed` to reset
## Frontend Guidelines
- Tailwind utility classes — no custom CSS unless absolutely necessary
- Alpine.js for interactivity (countdown timers, form submissions, dynamic wizard steps)
- AJAX form submissions on public pages (return JSON, no page reloads)
- Mobile-first responsive design
- Public pages: full-screen background image + dark overlay + centered content card
## Mailwizz API
- Base URL: https://www.mailwizz.nl/api
- Auth: `X-Api-Key` header
- Send data as form-data (`Http::asForm()`)
- Checkboxlist fields: read as comma-separated string, send as array
- Always use `app/Services/MailwizzService.php` for API calls
- Sync subscribers via queued job `SyncSubscriberToMailwizz`
## File Structure
- Controllers in `app/Http/Controllers/Admin/` (backend) and `app/Http/Controllers/` (public)
- Views in `resources/views/admin/` (backend) and `resources/views/public/` (frontend)
- Shared form partials as `_form.blade.php`
## Security
- CSRF on all forms
- Rate limiting on public endpoints (`config/preregister.php` → `public_requests_per_minute`, applied in `routes/web.php`)
- Never expose API keys in frontend, logs, or responses
- Validate and restrict file uploads (image types, max size)
- UUID slugs prevent URL enumeration
## Git Commits
Use conventional commits:
- `feat: description` for new features
- `fix: description` for bug fixes
- `refactor: description` for code improvements
- Commit after each logical unit, not after entire features
## When Unsure
- Check `PreRegister-Development-Prompt.md` in the project root — it has the full specification
- Ask for clarification rather than guessing
- Prefer explicit over clever