Skip to content

Architecture Overview

Volāre is a travel platform built as a monorepo with two products:

  • Web (byvolare.com) — the customer-facing online travel agency, an Astro frontend where travellers browse destinations and buy their trips.
  • Arkana (arkana.byvolare.com) — the brain of Volāre: the Laravel + FilamentPHP back office where the team configures everything (products, offers, pricing, suppliers, bookings, CMS content) and which serves the REST API the Web consumes.
┌─────────────────────────────────────────────────────────────────┐
│ Clients │
│ Web Browser │ Mobile App │ Admin Panel │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Cloudflare (CDN/Edge) │
│ Static Assets │ Edge Caching │ DDoS Protection │
└─────────────────────────────────────────────────────────────────┘
┌───────────────┴───────────────┐
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────┐
│ Web (Astro) │ │ Arkana (Laravel) │
│ byvolare.com │ │ (Docker/AWS) │
│ (Cloudflare) │ │ │
│ - SSR/SSG pages │────▶│ - REST API │
│ - Product pages │ │ - FilamentPHP Admin │
│ - Market routing │ │ - Queue workers │
└─────────────────────────┘ │ - Background jobs │
└─────────────────────────┘
┌───────────────────────────┼───────────────────────────┐
▼ ▼ ▼
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ PostgreSQL │ │ Redis │ │ External APIs │
│ │ │ │ │ │
│ - Primary DB │ │ - Cache │ │ - AerTicket │
│ - Full-text search│ │ - Sessions │ │ - Payment gateway │
│ - Queue/Job store │ │ │ │ - Email service │
└─────────────────────┘ └─────────────────────┘ └─────────────────────┘
Integration Purpose
AerTicket Flight search, booking, and ticketing
Stripe (Laravel Cashier) Card payments
Redsys Card payments (Spanish gateway)
Resend Transactional email
Pipedrive CRM synchronization (via pipedrive-sync queue)
Google OAuth Admin authentication (Socialite)
volare/
├── backend/ # Arkana: Laravel 13 + FilamentPHP v5 back office + API
│ ├── app/ # Application code
│ ├── config/ # Configuration
│ ├── database/ # Migrations, seeders
│ ├── routes/ # API and web routes
│ └── tests/ # Pest tests
├── frontend/ # Web: byvolare.com storefront (Astro 6 + Tailwind CSS v4)
│ ├── src/ # Source code
│ │ ├── pages/ # File-based routing
│ │ ├── components/
│ │ └── layouts/
│ └── public/ # Static assets
├── docs/ # Starlight documentation
│ └── src/content/ # Documentation content
├── analytics-mcp/ # Local Google Analytics MCP server
├── stagehand/ # Browserbase Stagehand E2E tests
├── emails/ # HTML email templates
├── AGENTS.md # Source of truth for project guidelines
└── .claude/ # Claude Code configuration
├── agents/ # Specialized AI agents
└── skills/ # Slash commands (symlink to .agents/skills)

The Astro frontend uses a dual-adapter setup defined in frontend/astro.config.mjs:

  • Local/default: @astrojs/node in standalone mode, with filesystem-backed sessions
  • Cloudflare (DEPLOY_TARGET=cloudflare): @astrojs/cloudflare targeting Workers, with sessions stored in KV via the SESSION_KV binding
┌─────────────────────────────────────────────┐
│ Presentation Layer │
│ Controllers │ Resources │ Middleware │
├─────────────────────────────────────────────┤
│ Application Layer │
│ Services │ Actions │ Jobs │ Events │
├─────────────────────────────────────────────┤
│ Domain Layer │
│ Models │ DTOs │ Enums │ Policies │
├─────────────────────────────────────────────┤
│ Infrastructure Layer │
│ Database │ Cache │ Queue │ APIs │
└─────────────────────────────────────────────┘
Pattern Usage
Service Layer Business logic encapsulation
DTOs Data transfer between layers
Actions Single-purpose operations
Form Requests Input validation
Resources API response transformation
Policies Authorization logic
1. HTTP Request arrives
2. Route matched, middleware executed
3. Controller receives request
4. Form Request validates input
5. Service layer processes business logic
6. Eloquent models fetch/save data
7. Resource transforms response
8. JSON response returned
1. Job dispatched from application
2. Job serialized to database
3. Queue worker picks up job
4. Job handler executes
5. Success: job deleted
6. Failure: retry or move to failed_jobs
Model Purpose
Product Base travel products
ProductByMarket Market-specific product versions
ProductByMarketTranslation Localized content
Booking Customer bookings
FlightBooking Flight-specific booking data
Offer Combined product + flight offers
Market Geographic markets
Airport Airport data with FTS
User Admin users with RBAC
Product (template)
└── hasMany: ProductByMarket (per market)
└── hasMany: ProductByMarketTranslation (per locale)
Booking
└── belongsTo: User
└── hasMany: FlightBooking (one per leg)
└── belongsTo: Airport (departure, arrival)
Offer
└── belongsTo: ProductByMarket
└── belongsTo: FlightBooking
Layer Technology Purpose
CDN Cloudflare Static assets, edge caching
Application Redis Query results, sessions
Database PostgreSQL Query plan caching
  • Cache-aside: Load on miss, store on read
  • Write-through: Update cache on write
  • TTL-based: Automatic expiration

Two dedicated worker containers are defined in backend/compose.yaml:

queue # aerticket-tickets, aerticket-fastlane, aerticket-bookings,
# aerticket-voids, pipedrive-sync, offer-recalculations, default
queue-flights # flight-searches (isolated so flight-search caching cannot
# starve booking/ticketing jobs)

Within the queue worker, queue order defines priority: aerticket-tickets is processed first, default last.

Category Queue Examples
Ticketing aerticket-tickets, aerticket-fastlane Issue tickets, fastlane ticketing
Booking aerticket-bookings Create/update bookings
Voids aerticket-voids Void bookings/tickets
CRM Sync pipedrive-sync Pipedrive synchronization
Offers offer-recalculations Offer recalculation jobs
Flight Search flight-searches Flight-search caching
Notifications default Emails, notifications
  • Admin Panel: Session-based with CSRF
  • API: Token-based (Sanctum)
  • OAuth: Google integration
  • RBAC: Role-based access control
  • Policies: Model-level permissions
  • Gates: Feature-level permissions
  • Encryption: Sensitive data at rest
  • HTTPS: All traffic encrypted
  • Input validation: Form requests
  • Output encoding: XSS prevention
Docker Compose
├── Laravel (port 80)
├── PostgreSQL 18 (port 5432)
├── Redis (port 6379)
├── Queue Worker (database driver; aerticket + sync + default queues)
├── Flights Queue Worker (flight-searches queue)
├── Nightwatch Agent
└── Mailpit (port 8025)
AWS / Cloudflare
├── Frontend: Cloudflare Pages
├── Backend: AWS ECS / EC2
├── Database: AWS RDS (PostgreSQL)
├── Cache: AWS ElastiCache (Redis)
├── Queue: Amazon SQS
└── Storage: AWS S3
Tool Purpose
Laravel Telescope Development debugging
Laravel Nightwatch Production monitoring
Health Endpoints Service health checks
GET /health # Application health
GET /telescope # Debug dashboard