Technology Stack
Backend
| Layer | Choice | Version | Notes |
|---|---|---|---|
| Language | PHP | ^8.2 | From composer.json require.php |
| Framework | Laravel | ^12.0 | Uses the new PHP-8 attribute-based structure |
| Admin UI | Filament | ^5.5 | Livewire-powered, mounted at /systemadmin |
| API auth | laravel/sanctum | ^4.0 | Token-based for SPA/mobile; session for Filament |
| OpenAPI | zircote/swagger-php | ^6.1 | Attribute-driven spec generation |
| PDF rendering | barryvdh/laravel-dompdf | latest | Receipts, vaccination certificates, pet passport, statement |
| Payments | razorpay/razorpay | latest | Owner-side checkout + webhooks |
| REPL | laravel/tinker | ^2.10 | Dev-only |
| Database (prod) | MySQL | ≥ 8.0 | Configured in .env.example |
| Database (tests) | SQLite | :memory: | Fast hermetic phpunit runs (RefreshDatabase) |
| Cache driver | database (prod), array (tests) | — | |
| Queue driver | database (prod), sync (tests) | — | Notification jobs run on a dedicated notifications queue |
| Mail driver | mailgun / ses / mail / log | — | Switchable per tenant via service_settings; tests use array |
| Session driver | database (prod), array (tests) | — | |
| Testing | PHPUnit + Pest infra | 11.x | RefreshDatabase per test, factory-driven setup |
Web frontend (admin / clinic / owner web portal)
| Layer | Choice | Version | Notes |
|---|---|---|---|
| Library | React | ^18.2.0 | |
| Build tooling | react-scripts | 5.0.1 | Create-React-App |
| Styling | Tailwind CSS | ^3.4.0 | Custom primary palette (emerald) |
| Icons | lucide-react | latest | Replaces text-button labels per task #11 |
| CSS pipeline | PostCSS + autoprefixer | — | |
| HTTP client | native fetch | — | Thin wrapper in src/services/core/httpClient.js |
| State | React Context | — | AuthContext, TenantContext, PermissionContext |
| Router | none | — | Module switch driven by state in App.js |
| Auth storage | localStorage | — | Audit P0 — should move to httpOnly cookie |
Mobile (vetty + vetdoctor)
| Layer | Choice | Notes |
|---|---|---|
| Framework | Flutter (Dart) | vetyy/, vetdoctor/ — share core/ patterns |
| HTTP client | thin wrapper around Dio-style | Bearer attached per request |
| Auth storage | SharedPreferences | Audit P0 — should move to flutter_secure_storage |
| Platform targets | iOS, Android, web (Flutter web), macOS / Windows / Linux for vetdoctor | |
| Razorpay | razorpay_flutter | vetty only |
| QR scanner | mobile_scanner | vetdoctor for share-code scan, vetty for code reading |
| File upload | file_picker, image_picker | vetty pet documents + vetdoctor attachments |
Docs
| Layer | Choice | Version |
|---|---|---|
| Static-site generator | Docusaurus | ^3.5.2 |
| Diagrams | @docusaurus/theme-mermaid | ^3.5.2 |
| Code highlighting | prism-react-renderer | ^2.3.0 |
Why each choice
- Laravel 12 + Filament 5 — fastest way to get a production-grade API, queue, mailer and admin panel in one PHP codebase. Filament removes the need to hand-roll a back office.
- Sanctum over Passport — Vetty only needs API tokens and SPA sessions, not full OAuth2. Sanctum is lighter and ships with Laravel.
- Zircote Swagger-PHP with attributes — keeps the OpenAPI spec colocated with each controller method, so it never drifts from the implementation.
- React + Tailwind — a common, well-known combo. Tailwind's utility classes keep components self-contained without a heavy design system.
- Create React App (for now) — matches the existing
ui/project; a move to Vite is a drop-in improvement when needed. - Context instead of Redux — the app has a small number of globals (current user, current tenant) so Redux or Zustand would be overkill.
- MySQL + SQLite for tests — MySQL for production richness, SQLite for fast, hermetic test runs (
database/verify.sqlite).
Version pin cheatsheet
From backend/composer.json:
{
"require": {
"php": "^8.2",
"filament/filament": "^5.5",
"laravel/framework": "^12.0",
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.10.1",
"zircote/swagger-php": "^6.1"
}
}
From ui/package.json:
{
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1"
},
"devDependencies": {
"tailwindcss": "^3.4.0",
"autoprefixer": "^10.4.16",
"postcss": "^8.4.31"
}
}