nabeel/phpvms
phpVMS is a free, open-source virtual airline management system built on Laravel. It provides pilot and fleet management, flight bidding, PIREP filing, ACARS integration, route and schedule tools, and a complete admin panel for operating a virtual airline.
phpVMS is not a Composer library you require into an existing app — it is a complete Laravel application for running a virtual airline (airports, aircraft, flights, bids, PIREPs, finances, ranks, ACARS). "Leveraging" it means installing it as your application and extending it in place, not consuming it as a dependency. There are zero dependents on the package, which confirms this: treat it as a platform/fork, not a utility.
Minimal path to a working install:
git clone https://github.com/phpvms/phpvms.git (or grab a release archive — the repo is the source of truth; there is no composer create-project package).composer installcp .env.example .env && php artisan key:generateDB_*, APP_URL, QUEUE_CONNECTION, mail.php artisan migrate --seedphp artisan storage:linknpm ci && npm run buildpublic/, or php artisan serve locally. Log in with the seeded admin account and immediately change credentials.Where to look first, in this order:
routes/ and app/Http/Controllers/ — the admin panel and frontend flow are easy to trace here.app/Models/ — User, Pirep, Flight, Aircraft, Subfleet, Airport, Bid, Expense. These are the domain.modules/ — the extension point you will actually use (see below).themes/ — Blade-based theme overrides for the public site.database/seeders/ — shows the data model in practice (airports, aircraft, ranks).config/ — look for phpVMS-specific config plus stock Laravel config; the admin settings table (readable via the setting() helper) drives most runtime behavior, not .env.First use case to validate end-to-end: create an airport, an aircraft/subfleet, and a flight in the admin panel; place a bid as a pilot; then file a PIREP (manually via the UI first, then via the REST API as an ACARS client would). Watch the financial transaction and PIREP status transition — that single loop touches nearly every subsystem and is the fastest way to learn the app.
Extend through modules, not core edits. Use the module scaffolding (php artisan module:make <Name>) to add features: each module is a self-contained Laravel package with its own routes, migrations, models, and service provider, registered in modules_statuses.json. Keep all custom business logic here so core upgrades don't clobber it. Disable/enable modules from the admin panel when debugging.
Hook into domain events for business logic. File/accept flows emit events (PIREP filed/accepted, user registered, bid added, etc.). Register listeners in a module's EventServiceProvider — typically queued — and do scoring, Discord/Slack notifications, Discord webhooks, rank promotions, or logbook sync there instead of patching controllers. This is the cleanest supported integration point.
Integrate via the REST API. phpVMS exposes a versioned API (/api/v1/...) used by ACARS clients and external tools, authenticated with API keys/tokens. Pattern: create a dedicated API key per client, hit endpoints for airports/aircraft/flights, and POST PIREPs from your ACARS or telemetry pipeline. Treat the API as the contract — build external tooling (Discord bots, dispatch dashboards, SimBrief bridges) against it rather than against the database schema.
Theme the public site by overriding views. Themes live under themes/, with Blade files shadowing core views and helpers for theme assets/views. Override individual views rather than copying a whole theme unless you're rebranding heavily; fewer files to reconcile on upgrade.
Use the settings system, not .env, for operational knobs. Things like VA name, currency, PIREP rules, and feature toggles live in the admin settings UI and are read via the setting() helper. When you add a config toggle in a module, surface it in settings so ops staff can change it without a deploy.
Respect the scheduler and queues. ACARS live-flight polling, financial rollups, and notifications are cron-driven. Deploy pattern: * * * * * php artisan schedule:run plus a supervised queue worker (php artisan queue:work). Local QUEUE_CONNECTION=sync hides ordering bugs — test PIREP processing with a real queue before going live.
Custom fields for per-VA data. PIREP and user custom fields let you store additional attributes without migrations. Use these for reporting/metrics; use migrations only when you need real relational queries.
app/, resources/, etc. Anything you edit outside modules/ and themes/ is at risk. Keep a fork with a disciplined diff, or a git merge strategy, and re-test modules after every bump. The release date shown (2026-06-26) is later than typical — pin a specific tag and read the changelog rather than tracking main.schedule:run. Add a health check.migrate --seed (or re-running seeders) can duplicate airports/ranks/users or reset data. Seed once during install; after that, import data deliberately.php artisan optimize:clear (config, route, view) after changing themes, settings, or module routes. A cached view will happily serve the old theme.storage/logs/laravel.log first, then APP_DEBUG=true locally, module enable/disable to bisect, and php artisan route:list to confirm your module routes actually registered. Laravel Telescope is optional but worth adding in dev for PIREP request inspection.app/.How can I help you explore Laravel packages today?