Files
fuel-price/.claude/rules/architecture.md
Ovidiu U 5ad89e977d Add fuel API ingestion and historic storage design spec
Includes verified API authentication flow, correct base URL, all DB
table schemas for stations, current prices, history, and archive.
Fuel types corrected to match live API (B7_STANDARD, B7_PREMIUM).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 18:09:50 +01:00

2.4 KiB

Architecture

Core principle: fat Services, thin everything else

All business logic lives in Service classes. Controllers, Livewire components, and console commands are thin orchestrators — they call Services and return results. This keeps the app API-extractable later without a rewrite.

Directory structure

app/
├── Console/Commands/       # Scheduler commands (PollFuelPrices, RunScoringEngine)
├── Http/Controllers/       # Minimal — auth + Stripe webhook only
├── Livewire/               # Classic two-file Livewire components
├── Models/                 # Eloquent models
├── Notifications/          # Laravel Notification classes (multi-channel)
├── Services/               # ALL business logic lives here
│   ├── FuelPriceService.php        # Fuel Finder API polling + storage
│   ├── AlertScoringService.php     # Fill-up timing recommendation engine
│   ├── StationTaggingService.php   # Supermarket brand detection
│   ├── NotificationDispatchService.php  # Tier-aware notification routing
│   └── SubscriptionService.php    # Cashier/tier helpers
└── Jobs/                   # Queued jobs (dispatch notifications per user)

resources/views/
├── livewire/               # Livewire Blade templates
└── emails/                 # Mailable templates

routes/
├── web.php                 # All web routes (Livewire pages)
└── api.php                 # Empty for now — API added later if needed

Service class conventions

  • Constructor injection only — no facade usage inside Services
  • Services are bound in AppServiceProvider if they need interfaces
  • Each Service has one responsibility — do not merge concerns
  • Return typed DTOs or Eloquent collections — never raw arrays from Services
  • Services never dispatch jobs directly — that's the controller/command's job

No API yet

routes/api.php stays empty for v1. Do not create API controllers or Sanctum token auth. The app is Livewire-only until subscriber count justifies a native app. When the API is added later, it will reuse the same Service classes.

Livewire components (classic only)

Use two-file classic Livewire components. Do NOT use Volt single-file syntax. Volt files from the starter kit (auth screens) are left as-is — do not convert them. New components go in app/Livewire/ with corresponding Blade in resources/views/livewire/.