# Technology Stack **Analysis Date:** 2026-02-13 ## Languages **Primary:** - PHP 8.1+ - Backend framework, ORM, business logic **Secondary:** - TypeScript - Not used (JavaScript tooling only) - JavaScript - Frontend interactivity via Alpine.js and Vite build ## Runtime **Environment:** - Laravel 10 (minimum 10.10) - PHP 8.1+ (configured in `composer.json`) **Package Managers:** - Composer (PHP) - Dependency management for backend - Lockfile: `composer.lock` (present) - npm (Node.js) - Frontend asset builds and development - Lockfile: `package-lock.json` (present) ## Frameworks **Core Backend:** - Laravel 10 - Full-stack web framework for routing, models, migrations, services - Location: `app/`, `routes/`, `config/`, `database/` **Frontend Templating:** - Blade (Laravel templating engine) - Server-side template rendering - Location: `resources/views/` **Frontend Interactivity:** - Alpine.js 3.4 - Lightweight reactive JavaScript for form handling and DOM manipulation - Package: `alpinejs@^3.4.2` in `package.json` **Build & Asset Pipeline:** - Vite 5 - Fast build tool for compiling CSS/JS - Package: `vite@^5.0.0` - Config: `vite.config.js` (Laravel Vite plugin configured) - Laravel Vite Plugin - Integration between Laravel and Vite - Package: `laravel-vite-plugin@^1.0.0` **Styling:** - Tailwind CSS 3.1 - Utility-first CSS framework - Package: `tailwindcss@^3.1.0` - Dark mode: `darkMode: 'class'` configured in tailwind config - Forms plugin: `@tailwindcss/forms@^0.5.2` for styled form elements - PostCSS 8.4.31 - CSS processing - Autoprefixer 10.4.2 - Browser vendor prefixes **Testing:** - PHPUnit 10.1 - PHP unit testing framework - Config: `phpunit.xml` - Test directory: `tests/` - Laravel Dusk 8.3 - Browser testing framework for end-to-end tests - Run: `php artisan dusk` - Mockery 1.4.4 - PHP mocking library for tests **Development Quality:** - Laravel Pint 1.0 - Code style formatter (PSR-12) - Laravel Tinker 2.8 - Interactive PHP REPL - Laravel Breeze 1.29 - Lightweight authentication scaffolding - FakerPHP 1.9.1 - Fake data generation for seeders - Spatie Ignition 2.0 - Error page debugging companion - Collision 7.0 - Error page styling **DevOps/Deployment:** - Laravel Sail 1.18 - Docker-based local development environment (optional) ## Key Dependencies **Critical Business Logic:** - `spatie/laravel-permission` 6.23 - RBAC role and permission system - Used for: Finance approvals, user role management - Config: `config/permission.php` - Tables: `roles`, `permissions`, `model_has_roles`, `model_has_permissions`, `role_has_permissions` - `barryvdh/laravel-dompdf` 3.1 - PDF generation for finance reports - Used for: Document export, compliance reports - Provider: `Barryvdh\DomPDF\ServiceProvider` - `maatwebsite/excel` 3.1 - Excel file import/export - Used for: Member data imports, financial report exports - Laravel 10 compatible version **HTTP & API Integration:** - `guzzlehttp/guzzle` 7.2 - HTTP client for external requests - Used in: `SiteRevalidationService` for Next.js webhook calls - Location: `app/Services/SiteRevalidationService.php` **QR Code Generation:** - `simplesoftwareio/simple-qrcode` 4.2 - QR code generation library - Used for: Member ID verification, document tracking **Authentication:** - `laravel/sanctum` 3.3 - API token authentication and CSRF protection - Used for: Public API endpoints (`/api/v1/*`) - Config: `config/sanctum.php` - Stateful domains: `localhost`, `127.0.0.1` (customizable via env) ## Configuration **Environment Configuration:** - `.env.example` - Template for environment variables - Required variables (non-secret): - `APP_NAME`, `APP_ENV`, `APP_DEBUG`, `APP_URL` - Application identity - `DB_CONNECTION`, `DB_HOST`, `DB_PORT`, `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD` - Database - `MAIL_MAILER`, `MAIL_HOST`, `MAIL_PORT`, `MAIL_FROM_ADDRESS` - Email - `CACHE_DRIVER`, `QUEUE_CONNECTION`, `SESSION_DRIVER` - Caching/queueing - `REGISTRATION_ENABLED` - Toggle public registration on/off - `NEXTJS_REVALIDATE_URL`, `NEXTJS_REVALIDATE_TOKEN` - Webhook to frontend - `NEXTJS_PUBLIC_PATH` - Optional: Local Next.js repo for asset syncing **Core Configs:** - `config/app.php` - Timezone: `Asia/Taipei`, Locale: `zh_TW`, Cipher: `AES-256-CBC` - `config/database.php` - Database connection options (MySQL primary, SQLite dev) - `config/auth.php` - Authentication guards (session-based), public registration toggle - `config/mail.php` - SMTP, Mailgun, Postmark, SES support - `config/accounting.php` - Account codes, amount tier thresholds, currency (TWD) - `config/filesystems.php` - Local, public, private, and S3 disk definitions - `config/cache.php` - File (default), Redis, Memcached, DynamoDB support - `config/queue.php` - Sync (default), database, Redis, SQS, Beanstalkd support - `config/services.php` - Third-party service credentials (Mailgun, Postmark, AWS SES, Next.js webhooks) - `config/logging.php` - Monolog channels (stack, single, daily, Slack, Papertrail) - `config/cors.php` - CORS policy for API endpoints - `config/session.php` - Session driver and lifetime (120 minutes default) ## Database **Primary (Production):** - MySQL 5.7+ (configured in `config/database.php`) - Character set: `utf8mb4`, Collation: `utf8mb4_unicode_ci` - Strict mode enabled **Development:** - SQLite supported as alternative (`DB_CONNECTION=sqlite`) - Location: `database/database.sqlite` **Migrations:** - Directory: `database/migrations/` - Run: `php artisan migrate` - Fresh reset: `php artisan migrate:fresh --seed` ## Caching & Session **Cache (Default: File):** - Driver: `file` (can be switched to Redis, Memcached, DynamoDB) - Location: `storage/framework/cache/data/` - Used for: Settings caching (`settings()` helper), query result caching **Sessions (Default: File):** - Driver: `file` (can be switched to database, Redis, etc.) - Lifetime: 120 minutes - Storage: `storage/framework/sessions/` **Queue (Default: Sync):** - Driver: `sync` (processes jobs immediately in production, can use `database`/`redis`) - Used for: Email sending, bulk operations - Failed jobs table: `failed_jobs` ## Email **Mailers Supported:** - SMTP (default) - Mailgun, custom SMTP servers - Mailgun API - Postmark API - AWS SES - Log (development) - Failover chains (SMTP → Log) **Dev Default:** - Mailpit (mock SMTP server) on `localhost:1025` - Configured in `.env.example` for local testing **Mail Queue:** - All transactional emails use `Mail::...->queue()` for async sending - Location: Email classes in `app/Mail/` ## File Storage **Private Files:** - Disk: `private` (stores in `storage/app/`) - Access: Served via controller responses only (no direct URL) - Used for: Encrypted documents, sensitive uploads **Public Files:** - Disk: `public` (stores in `storage/app/public/`) - URL: Accessible via `/storage/...` after running `php artisan storage:link` - Used for: Admin-uploaded images, article attachments **Optional S3:** - Disk: `s3` (configured for AWS S3) - Requires: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_DEFAULT_REGION`, `AWS_BUCKET` **Next.js Asset Sync (Optional):** - Location: `config/services.php` → `nextjs.public_path` - Feature: Auto-copy uploaded images to Next.js `public/` directory - Git integration: Optional auto-commit and push of assets - Used for: Serving static images from static Next.js build ## Deployment **Hosting Targets:** - Dedicated servers (traditional deployment with PHP-FPM + Nginx) - Docker (via Laravel Sail) - Vercel/Netlify (headless API mode) **Production Considerations:** - Database: Migrate to MySQL 8.0+ - Cache: Switch from `file` to Redis for multi-server setups - Queue: Switch from `sync` to `database` or `redis` - Session: Switch from `file` to `database` or `redis` - Mail: Configure Mailgun/SES for production email - Storage: Use S3 for file uploads instead of local disk - Assets: Compile with `npm run build` before deployment --- *Stack analysis: 2026-02-13*