Development Workflow
How a normal day of development looks at Volāre: start the stack, pick up a task, branch, commit, open a PR and get it deployed. If you have not set up your machine yet, start with Installation.
The work loop at a glance
Section titled “The work loop at a glance”flowchart LR A[ClickUp task] -->|/task-work| B[Branch CU-id_slug] B --> C[Code + tests] C -->|/commit| D[Commits with Refs: CU-id] D -->|/pr-create| E[Pull request] E -->|CI + review| F[Merge to master] F -->|tag-on-merge + build| G[Images in ECR] G -->|infra-volare deploy| H[Staging / Production]
Each arrow labelled with a /command is a Claude Code skill that does that step for you
(see Slash Commands). The last two steps are described in
Deployment.
Daily Development
Section titled “Daily Development”Starting the Environment
Section titled “Starting the Environment”Run each block from the repository root:
# Backend containers (Arkana + API + queues + database)cd backend && ./vendor/bin/sail up -d# The Web (separate terminal)cd frontend && pnpm dev# These docs (optional, separate terminal)cd docs && pnpm devDevelopment URLs
Section titled “Development URLs”| Service | URL | Purpose |
|---|---|---|
| Arkana | http://localhost/admin | FilamentPHP back office |
| Backend API | http://localhost/api | Laravel API |
| Swagger | http://localhost/api/documentation | API docs |
| Telescope | http://localhost/telescope | Debug dashboard |
| The Web | http://localhost:4321 | Astro website |
| Documentation | http://localhost:4322 | This site |
| Mailpit | http://localhost:8025 | Email testing |
Git Workflow
Section titled “Git Workflow”Work is tracked in ClickUp. Never commit to master directly — every change goes through
a branch and a pull request.
Branch Naming
Section titled “Branch Naming”Branches follow ClickUp’s auto-branch template, <taskId>_<slug>, so ClickUp links the
branch back to the task:
CU-869dtaf1r_bogus-multi-stop-domestic-flight-legs/task-work <task-id> creates it for you from a fresh origin/master.
Commit Messages
Section titled “Commit Messages”Title format: type(scope): description (Conventional Commits).
The PR title is checked by the pr-title-check GitHub Action, and because PRs are
squash-merged it becomes the commit on master — and decides the next version number
(feat → minor, anything else → patch).
- Types:
feat,fix,docs,style,refactor,perf,test,build,ci,chore,revert - Scopes:
frontend,backend(required; usebackend,frontendfor both) - Task reference: in the commit body as a trailer,
Refs: CU-<taskId>— never in the title - Language: English, imperative mood (“add”, not “added”)
# Goodgit commit -m "feat(backend): add user dashboard with profile management" -m "Refs: CU-869dtaf1r"git commit -m "fix(backend): booking validation for empty dates" -m "Refs: CU-869dtaf1r"
# Badgit commit -m "CU-869dtaf1r feat(backend): add user dashboard" # task ref in titlegit commit -m "fix stuff"git commit -m "WIP"Do not add AI attribution (Co-Authored-By: Claude) to commits.
Slash Commands
Section titled “Slash Commands”Use Claude Code slash commands for common operations:
| Skill | Description |
|---|---|
/commit [message] |
Create commit with Conventional Commits format |
/pr-create |
Create PR (runs PHPStan check for PHP changes) |
/fix-phpstan [path] |
Run PHPStan and fix errors |
/rebase-master |
Rebase onto latest master |
/update-master |
Switch to master, pull changes, and sync dependencies (local only) |
/prune-branches |
Delete local branches whose remote tracking branch has been deleted |
/task-create [description] |
Create a ClickUp task from a description or plan |
/task-work [task-id] |
Start working on a ClickUp task (setup branch) |
/review-comment [text] |
Evaluate PR review comment validity |
/update-docs |
Update documentation for changed services |
/work-report [period] |
Generate work report/changelog (default: this week) |
/db-backup [description] |
Create a PostgreSQL backup and upload to S3 |
/db-restore [filename] |
Download a backup from S3 and restore locally |
Automated Hooks
Section titled “Automated Hooks”.claude/settings.json wires automation around edits:
- SessionStart (startup): runs
scripts/setup_env.shasynchronously to prepare the environment - PreToolUse (Edit/Write): on backend PHP,
.claude/hooks/require-skill.shblocks the edit until the matching MUST skill (laravel-best-practices,testing-best-practices,filament-development,mcp-development) is loaded in the session; onfrontend/src/**/*.astro|tsx,block-raw-hex.shrejects raw hex colours so components use the design-system tokens - Notification:
notify-google-chat.shforwards Claude Code notifications to Google Chat - PostToolUse (Edit/Write): on
backend/**/*.phpfiles runs Pint on the edited file only through Sail; ondocs/src/content/docs/**/*.mdfiles runsnpx markdownlint-cli2 --fix
Composer Scripts
Section titled “Composer Scripts”Canonical local CI entrypoints defined in backend/composer.json:
./vendor/bin/sail composer test # config:clear + lint:check + analyse:check + phpstan + tests./vendor/bin/sail composer lint # Pint (parallel)./vendor/bin/sail composer analyse # PHPStan./vendor/bin/sail composer test:type-coverage # Pest type coverage (min 100)./vendor/bin/sail composer dev # serve + queue:listen + pail + vite concurrentlyCode Quality
Section titled “Code Quality”PHPStan (Level 6)
Section titled “PHPStan (Level 6)”All PHP code must pass PHPStan Level 6 analysis:
# Run PHPStan./vendor/bin/sail exec laravel.test ./vendor/bin/phpstan analyse
# Auto-fix with slash command/fix-phpstanLaravel Pint
Section titled “Laravel Pint”Format code with Laravel Pint:
./vendor/bin/sail pintTesting
Section titled “Testing”Run tests with Pest:
# All tests./vendor/bin/sail artisan test
# Specific test./vendor/bin/sail artisan test --filter=BookingTest
# With coverage./vendor/bin/sail artisan test --coverageWorking with Agents
Section titled “Working with Agents”Claude Code handles general backend work (models, Filament resources, tests,
debugging) directly in the main session, guided by the MUST skills listed in
backend/AGENTS.md (laravel-best-practices, testing-best-practices,
filament-development, mcp-development), each enforced by the PreToolUse
hook. Specialized agents cover narrow domains:
| Agent | Use For |
|---|---|
@aerticket-api-agent |
Questions about the AerTicket API |
@intermundial-api-agent |
Intermundial Nexus API for travel insurance |
@documentation-agent |
Auditing, pruning, and keeping docs synchronized with code |
@offer-doctor |
Diagnosing why auto-generated travel offers are missing or fail |
Database Operations
Section titled “Database Operations”Migrations
Section titled “Migrations”# Create migration./vendor/bin/sail artisan make:migration create_bookings_table
# Run migrations./vendor/bin/sail artisan migrate
# Rollback./vendor/bin/sail artisan migrate:rollback
# Fresh with seeders./vendor/bin/sail artisan migrate:fresh --seedSeeders
Section titled “Seeders”# Create seeder./vendor/bin/sail artisan make:seeder BookingSeeder
# Run seeders./vendor/bin/sail artisan db:seed
# Specific seeder./vendor/bin/sail artisan db:seed --class=BookingSeederGenerating Test Data
Section titled “Generating Test Data”After running seeders (db:seed), populate your local environment with test data. Run in this order:
# 1. Seed base data (suppliers, airports, markets)./vendor/bin/sail artisan db:seed
# 2. Generate hotels./vendor/bin/sail artisan suppliers:hotels:generate --hotels-per-city=2
# 3. Generate activities./vendor/bin/sail artisan suppliers:activities:generate --activities-per-city=2
# 4. Generate services linked to hotels and activities./vendor/bin/sail artisan suppliers:services:generate --type=hotel --count=10./vendor/bin/sail artisan suppliers:services:generate --type=activity --count=10
# 5. Generate products with flight configs./vendor/bin/sail artisan products:generate --templates=5 --per-market=1All commands are interactive when options are omitted, and blocked from running in production.
For detailed options of each command, see Suppliers — Test Data Generation and Products — Test Data Generation.
Tinker
Section titled “Tinker”Interactive PHP shell for debugging:
./vendor/bin/sail artisan tinker
# Example queries>>> User::count()>>> Booking::with('user')->first()>>> Product::where('active', true)->get()Queue Management
Section titled “Queue Management”Monitor Jobs
Section titled “Monitor Jobs”# Process jobs./vendor/bin/sail artisan queue:work
# List failed jobs./vendor/bin/sail artisan queue:failed
# Retry failed job./vendor/bin/sail artisan queue:retry {id}
# Clear failed jobs./vendor/bin/sail artisan queue:flushDebugging
Section titled “Debugging”Laravel Telescope
Section titled “Laravel Telescope”Access at http://localhost/telescope for:
- Request/response inspection
- Database queries
- Queue jobs
- Exceptions
- Logs
Laravel Boost MCP
Section titled “Laravel Boost MCP”Use the Laravel Boost MCP tools:
# Get last errormcp__laravel-boost__last-error
# Query databasemcp__laravel-boost__database-query "SELECT * FROM users LIMIT 5"
# Execute tinker codemcp__laravel-boost__tinker "User::count()"
# Search docsmcp__laravel-boost__search-docs ["queue jobs", "redis"]Pull Request Workflow
Section titled “Pull Request Workflow”Before Creating PR
Section titled “Before Creating PR”- Run tests:
./vendor/bin/sail artisan test - Run PHPStan:
/fix-phpstan - Format code:
./vendor/bin/sail pint - Update documentation if needed
Creating PR
Section titled “Creating PR”Use the slash command:
/pr-createThis will:
- Check for uncommitted changes
- Run PHPStan if PHP files changed
- Push branch to remote
- Create PR with template
PR Review
Section titled “PR Review”PRs require:
- Passing CI checks (the Pest suite on SQLite, the Pint style check, and the advisory PostgreSQL lane)
- Code review approval
- Updated documentation (if applicable)
PHPStan is not a CI check: it runs locally through composer test and the /pr-create gate. Docs-content and backend-test PRs skip review and merge through the auto-merge path. The full workflow matrix lives in PR Merge Paths.