1. phases
Itinera API
  • ✈ Itinera API Documentation
  • Docs
    • legacy
      • Itinera — System Overview
      • Technology Stack & Architecture
      • Getting Started Guide
      • Infrastructure
      • Frontend Application
      • Architecture Overview
      • API Reference
      • Backend Services
      • Development Guidelines
    • phases
      • 01. Architecture Overview & Checkout Idempotency
      • Phase 2: Commerce & Checkout Engine
      • Phase 3: Webhooks & Asynchronous Fulfillment
      • Phase 4: Security Perimeter & Authentication
      • Phase 5: Database Schema & Entity Relationships
      • Phase 6: AI Quota & Telemetry Subsystems
      • Phase 7: API Route Matrix & FormRequests
      • Phase 8: Global Exception & Error Handling
      • Phase 9: Frontend Ecosystem & State Management
      • Phase 10: Design System & Component Library
      • Phase 11: Interactive GSAP Animations
      • Phase 12: Deployment & CI/CD Pipeline
      • Phase 13: Testing Strategies
      • Phase 14: Performance & Optimization
      • Phase 15: Developer Onboarding & Runbooks
      • 15-Phase Comprehensive Wiki & Documentation Plan
  • APIs
    • Auth
      • Register a new user
      • Log in a user
      • Log out user
      • Refresh JWT token
      • Forgot password request
      • Reset password verification
      • Get current user profile
      • Update user profile
      • Redirect to Google OAuth
      • Google OAuth Callback
      • Verify email via signed URL
    • Catalog
      • List all countries
      • Get country details
      • List all cities
      • List all regions
      • List all destinations
      • Get destination details
      • Get hotels by destination
      • List all hotels
      • Get hotel details
      • Get reviews for a hotel
      • List all flights
      • Get flight details
      • List all restaurants
      • Get restaurant details
      • List all attractions
      • Get current weather
      • Submit review for an entity
      • Delete review
      • Toggle favourite status for entity
      • List my submitted reviews
    • Bookings
      • Book a tour destination
    • V1 Aliases
      • V1 List all countries
      • V1 Get country details
      • V1 List all cities
      • V1 List all destinations
      • V1 Get destination details
      • V1 Get hotels by destination
      • V1 List all hotels
      • V1 Get hotel details
      • V1 Get reviews for a hotel
      • V1 List all flights
      • V1 Get flight details
      • V1 List all restaurants
      • V1 Get restaurant details
      • V1 List all attractions
      • V1 Get attraction details
      • V1 List all regions
      • V1 Get weather details
    • Trips
      • List user trips
      • Create a new trip
      • Get trip details
      • Update trip details
      • Delete a trip
      • Get creation metadata
      • Attach items to a trip
      • Update trip item
      • Detach items from a trip
      • Fork a trip
    • Conversations
      • List user conversations
      • Start a new conversation
      • Get conversation details
      • List messages in conversation
      • Send message to conversation
      • Mark conversation as read
    • Commerce Plans
      • List public plans
      • Get public plan details
    • Commerce Subscriptions
      • Subscribe to a plan
      • Upgrade active plan
      • Get active subscription info
      • Cancel active subscription
    • Commerce Checkout
      • Initiate Paymob payment checkout
    • Integrations
      • Paymob status webhook callback
      • Paymob redirect return callback
    • System Settings & Support
      • Submit public contact message
      • Subscribe to system newsletter
      • Get list of my reports
      • List all notifications
      • Mark single notification as read
      • List available surveys
      • Submit answers for survey
      • Get survey details
      • Update survey details
      • Delete survey response
    • AI Tools
      • Enhance itinerary details using AI
      • Request AI review of itinerary
      • Plan route using AI assistance
      • Get AI quota remaining details
      • Chat with AI Concierge assistant
      • Get AI Review progress by ID
    • Agency Integration
      • Request agency assignment
      • List agency active tasks
      • List agency managed trips
      • Get agency total earnings
      • Get agency profile details
      • Update agency profile details
    • Admin User Management
      • List users inside admin dashboard
      • Get user profile
      • Set user active status
      • Block user profile
    • Admin Catalog Moderation
      • Create new catalog category
      • Create new catalog destination
      • Create new hotel catalog record
      • Create new flight catalog record
      • Create new restaurant catalog record
      • Create new attraction catalog record
  • Schemas
    • User
    • ErrorResponse
    • Trip
    • Destination
    • Hotel
    • Flight
    • Restaurant
    • Attraction
    • Booking
    • Review
    • Agency
    • Survey
  1. phases

Phase 12: Deployment & CI/CD Pipeline

This document maps how the monorepo builds and ships as two Railway services from a single Dockerfile, how GitHub Actions gates merges, and how the backend container boots (cache, migrate, queue) and serves traffic behind nginx.

1. Build Matrix: One Dockerfile, Two Services#

Dockerfile:8 declares ARG SERVICE_ROLE=frontend; Railway injects the per-service value as a build ARG (docs.railway.com/builds/dockerfiles). Final line selects the stage:
ServiceSERVICE_ROLEBase imageArtifact
Frontendfrontendnginx:1.27-alpinefullstack/Frontend/ static site + nginx.conf + entrypoint.sh (sed-injects API_BASE)
Backendbackendphp:8.5-fpm-alpine (two stages: vendor → backend)Laravel API + vendor/ + storage/ perms + docker/{php.ini,nginx.conf,supervisord.conf,entrypoint.sh}
railway.json:3-14 locks this in: "builder":"DOCKERFILE", dockerfilePath:"Dockerfile", runtime:"V2", numReplicas:1, restartPolicyType:"ON_FAILURE" maxRetries:10, sleepApplication:false.

Backend image layers#

Stage vendor: php:8.5-fpm-alpine + apk add git libzip gd ... + composer install --no-dev --prefer-dist --optimize-autoloader --no-scripts from fullstack/Backend/composer.json (platform php 8.5).
Stage backend: nginx + supervisor + php extensions (pdo_mysql zip pcntl bcmath gd) + move php.ini-production, copy docker/php.ini, copy vendor + source, mkdir -p storage/framework/{cache,sessions,views} storage/logs bootstrap/cache + chown www-data:www-data.
EXPOSE 8080, HEALTHCHECK curl -sf http://localhost:8080/up | grep -q '"status":"ok"'.
docker/php.ini — opcache.enable=1, memory 256M, max_files 20000, revalidate_freq 0, validate_timestamps 0, memory_limit 256M, post_max_size 50M, display_errors Off, session.cookie_secure=1.

2. CI — .github/workflows/ci.yml:1-48#

Triggered on push: [main, develop, feat/community-hub] and pull_request: [main, develop]. Two parallel jobs, both working-directory: fullstack/Backend:
lint: shivammathur/setup-php@2 php 8.2 + composer install → ./vendor/bin/pint --test.
test: same setup + extensions: mbstring pdo pdo_sqlite dom gd intl zip → cp .env.example .env && php artisan key:generate && php artisan jwt:secret --force → php artisan test.
No frontend npm test/build in CI — showcase itinera-showcase-react is gated locally via oxlint/vitest (see tasks/todo.md).

3. Backend Runtime — docker/entrypoint.sh + supervisord.conf#

Entrypoint (strict set -e, cd /var/www/html):
1.
php artisan config:cache — bakes Railway env (CORS_ALLOWED_ORIGINS, PAYMOB_HMAC, JWT_SECRET, etc.) into bootstrap cache.
2.
php artisan route:cache
3.
php artisan view:cache (|| true — API-only may have no blades)
4.
php artisan storage:link (|| true)
5.
php artisan migrate --force — idempotent schema drift.
6.
if [ "$SEED_ON_DEPLOY" = "true" ] → php artisan db:seed --force (first deploy only).
7.
chown -R www-data:www-data storage bootstrap/cache && chmod -R 775.
8.
exec supervisord -c /etc/supervisor/conf.d/supervisord.conf.
supervisord.conf (nodaemon, logfile /var/log/supervisor/supervisord.log):
php-fpm --nodaemonize priority 10.
nginx priority 20 depends_on php-fpm, runs envsubst '${PORT}' < /etc/nginx/nginx.conf > /tmp/nginx.conf && nginx -c /tmp/nginx.conf -g 'daemon off;' — PORT injected by Railway.
queue: php artisan queue:work --sleep=3 --tries=3 --max-time=3600 priority 30, numprocs 1 (FulfillOrderListener, mail queue; see Phase 3).

Nginx — docker/nginx.conf (backend)#

Upstream php-fpm via fastcgi_pass 127.0.0.1:9000, listen $PORT, root /var/www/html/public, try_files $uri $uri/ /index.php?$query_string, client_max_body_size 50M, fastcgi buffers. Health /up is public (no auth) for Railway probe.

4. Frontend Runtime — fullstack/Frontend/{nginx.conf,entrypoint.sh}#

nginx.conf — listen ${PORT}, root /usr/share/nginx/html, try_files $uri $uri/ /index.html (SPA fallback). Caching tiers:
/assets/js/config.js + /assets/js/core/config.js — no-cache, must-revalidate (sed-injected API_BASE changes per deploy).
*.js|css|map — public, max-age=3600, must-revalidate + etag on (was 7d, kept serving stale JS).
png|jpg|svg|woff2 — max-age=604800.
*.html — no-cache.
entrypoint.sh — if $API_BASE set, find ... -name '*.js' -exec grep -l '__API_BASE__' {} + then sed -i "s#__API_BASE__#${API_BASE}#g"; then envsubst '${PORT}' for nginx and exec "$@".
Health: wget -q -O /dev/null http://127.0.0.1:${PORT:-80}/.

5. Pipeline Diagram#

6. Principles#

1.
One Dockerfile, two images. FROM ${SERVICE_ROLE} avoids divergent build contexts; frontend stays nginx-only, backend bakes vendor then php-fpm — no Node in prod backend.
2.
Cache bakes env. config:cache runs at entrypoint, not build, so Railway vars are live. Frontend __API_BASE__ sed covers static JS without rebuild.
3.
Migrate is idempotent. migrate --force on every boot is safe; seeding is gated behind SEED_ON_DEPLOY=true.
4.
Health is public, everything else is guarded. /up responds without auth for Railway; CI's php artisan test covers auth/RBAC/throttle before merge.
5.
Queue as a managed process. supervisord keeps queue:work alive beside php-fpm/nginx; --max-time 3600 bounds leaky jobs.
Modified at 2026-08-25 22:41:45
Previous
Phase 11: Interactive GSAP Animations
Next
Phase 13: Testing Strategies
Built with