Skip to main content

Technical Overview

This section is for engineers who need to read or change the code. It covers:

  • Setup guide — how to bring the full stack up on a laptop, including both Flutter apps.
  • Backend (Laravel) — structure, database schema, models, controllers, routes, middleware, form requests, resources, Filament admin panel.
  • Frontend (React) — structure, contexts, components, services, styling.
  • Mobile (Flutter) — shared architecture, plus deep-dives into the vetty (pet-owner) and vetdoctor (clinic) apps.
  • Authentication — the end-to-end flow across web, mobile and Filament.
  • API reference — every public endpoint with methods, parameters, and response shape.

Repositories at a glance

vetty/
├── backend/ # Laravel 12 API + Filament admin
│ ├── app/
│ │ ├── Http/
│ │ │ ├── Controllers/ # Api/V1, Filament resources separate
│ │ │ ├── Middleware/ # tenant.resolve, require.permission, require.premium
│ │ │ ├── Requests/ # FormRequests grouped by version
│ │ │ └── Resources/ # API response shapers grouped by version
│ │ ├── Models/ # Eloquent models (incl. PetShare, PetVaccination, ServiceSetting)
│ │ ├── Filament/ # Filament resources/pages/widgets
│ │ ├── OpenApi/ # Swagger-PHP shared schemas
│ │ ├── Notifications/ # Driver-swappable email/SMS adapters
│ │ └── Providers/ # AppServiceProvider + Filament panel
│ ├── routes/ # api.php, web.php, console.php
│ ├── database/ # migrations, factories, seeders
│ ├── config/ # framework config
│ └── composer.json
├── ui/ # React 18 SPA (clinic + owner web portal)
│ ├── src/
│ │ ├── components/ # Feature modules + common UI
│ │ ├── contexts/ # AuthContext, TenantContext
│ │ ├── hooks/ # usePatients, useAppointments, usePatientRecords
│ │ ├── services/ # adapters (http / mock) + factory
│ │ ├── lib/ # api.js, normalizers.js
│ │ └── App.js
│ ├── tailwind.config.js
│ └── package.json
├── vetyy/ # Flutter pet-owner app (emerald theme)
│ ├── lib/
│ │ ├── config/env.dart # apiBase / webBase (dart-define)
│ │ ├── core/api/ # ApiClient + ApiException
│ │ ├── core/auth/ # AuthStore (ChangeNotifier + prefs)
│ │ ├── core/theme.dart # VettyTheme.light()
│ │ ├── features/auth/ # login, register, forgot-password
│ │ ├── features/pets/ # list, form, detail + vaccinations
│ │ ├── features/shares/ # share QR generator + service
│ │ ├── features/providers/ # directory search
│ │ ├── features/home/ # HomeShell (Pets + Nearby tabs)
│ │ └── main.dart
│ ├── test/widget_test.dart
│ └── pubspec.yaml
└── vetdoctor/ # Flutter vet/clinic app (indigo theme)
├── lib/
│ ├── core/ # mirror of vetty; AuthStore adds tenant
│ ├── features/auth/ # login, forgot-password (no register)
│ ├── features/shares/ # ScanScreen (mobile_scanner) + redeem
│ ├── features/appointments/# today's schedule
│ ├── features/home/ # DashboardScreen
│ └── main.dart
├── test/widget_test.dart
└── pubspec.yaml

Conventions

Backend

  • Namespacing — controllers, requests, and resources are all versioned under App\Http\*\Api\V1. When you add v2, copy the folder and bump the namespace.
  • Form Requests — every write endpoint has its own FormRequest class; validation does not live in controllers.
  • API Resources — every read endpoint returns an Api\V1\*Resource (or collection). Controllers do not return raw models.
  • Route parameters — tenant-scoped routes use {tenant} (resolved through route-model binding into a Tenant).
  • Migrations — named with timestamp + entity (e.g. 2026_04_15_175400_create_appointments_table.php).
  • OpenAPI — annotate every controller method with #[OA\Post(…)] / #[OA\Get(…)] attributes so the spec stays in sync.

Frontend

  • Module pattern — one folder per feature (components/patients/, components/appointments/), each exposing a top-level *Module.js component that renders the page.
  • Services — anything that touches the network goes through a service in services/adapters/; UI components never call fetch directly.
  • HooksusePatients, useAppointments encapsulate the service call + loading/error state so components stay declarative.
  • Normalizers — API responses are transformed into UI shapes in lib/normalizers.js before rendering; UI code never pokes at snake_case keys.
  • Tailwind — use core utilities; the primary palette is pre-configured (bg-primary-600, text-primary-500, etc.).

Mobile (Flutter)

  • Feature folders — one directory per feature under lib/features/, each with a small service class (*_service.dart) and 1–3 screens. No state-management library; everything is StatefulWidget + ChangeNotifier where needed.
  • Services hold HTTP, screens hold UX — widgets never call ApiClient directly; they go through the feature service. That keeps the screens test-friendly and the HTTP layer centralised.
  • Persistent authAuthStore is a ChangeNotifier that writes token + user (and tenant for vetdoctor) to shared_preferences under vetty.auth.* / vetdoctor.auth.* keys, and notifies listeners on change so main.dart flips between the login and home routes.
  • Config via dart-defineEnv.apiBase and Env.webBase are String.fromEnvironment — dev defaults point at http://10.0.2.2:8000/api/v1 (Android emulator), shipped builds override with --dart-define=VETTY_API_BASE=....
  • Endpoint paths match the backend exactly — owner-scoped endpoints include the /owner/ prefix (/owner/me/pets, /owner/me/shares), clinic-scoped endpoints include /tenant/{id}/…, and shared public surfaces (/providers, /shares/{code}, /shares/redeem) sit at the root.