Development Setup
Set up a Fleetbase development environment — mount live source, link packages, and work on extensions with hot reload.
Development Setup
This guide is for contributors and extension developers who need to work directly on Fleetbase source code or link a local package into a running instance. If you just want to run Fleetbase locally without modifying its internals, see Running Locally instead.
Prerequisites
- Docker v20.10+ and Docker Compose v2.0+
- Git with submodule support
- Node.js v18+ and pnpm — for running the console locally outside Docker
- PHP 8.1+ and Composer — for backend package work outside Docker
Clone with Submodules
The Fleetbase repository uses Git submodules for its packages. Development setup requires pulling all submodules so the packages/ directory contains live source:
git clone https://github.com/fleetbase/fleetbase.git
cd fleetbase
git submodule update --init --recursiveThis populates packages/ with the source for all first-party extensions (FleetOps, Storefront, Pallet, Ledger, and others). Each package contains two directories:
| Directory | Contents |
|---|---|
addon/ | Ember.js frontend addon code |
server/ | Laravel backend package (service provider, models, routes, migrations) |
Package Linking
Fleetbase includes a development linker in the repository so you do not have to hand-edit console/package.json, api/composer.json, and console/pnpm-workspace.yaml every time you switch extension work. Use it when you want a local package under packages/ to replace the published registry package.
The linker manages both sides of an extension:
- the Ember engine used by Console
- the Laravel package used by the API
- shared frontend packages such as
ember-core,ember-ui, andfleetops-data - backend-only shared packages such as
core-api
Install it once from the Fleetbase repository root:
npm linkAfter linking, the flb-package-linker command is available globally:
flb-package-linker --help
flb-package-linker list
flb-package-linker statusIf you do not want to install the command globally, run it directly:
node scripts/package-linker.mjs statusLink FleetOps for Development
FleetOps development usually needs the FleetOps extension plus the shared Ember packages it depends on. From the repository root:
flb-package-linker enable fleetops --shared ember-core ember-ui fleetops-data
flb-package-linker install fleetopsThis updates the local manifests and prints the install commands it would run:
cd console && pnpm install
cd api && composer update fleetbase/fleetops-api --with-dependenciesUse --install if you want the linker to run those commands immediately:
flb-package-linker enable fleetops --shared ember-core ember-ui fleetops-data --installLink Multiple Extensions
Pass more than one extension name to enable or disable them together:
flb-package-linker enable fleetops pallet --shared ember-core ember-ui fleetops-data
flb-package-linker install fleetops palletThe install command combines backend Composer packages into one update:
cd api && composer update fleetbase/fleetops-api fleetbase/pallet-api --with-dependenciesLink Shared Packages
When working on shared Ember packages, link them through the root Console workspace instead of editing every extension manually:
flb-package-linker enable-shared ember-core ember-ui fleetops-data
flb-package-linker installThe linker adds those packages to console/pnpm-workspace.yaml, sets linkWorkspacePackages: deep, enables workspace preference, and writes pnpm workspace overrides. This matters because Ember engines can otherwise resolve their own nested copy of a shared package, which makes local changes appear to be ignored.
For backend-only package work, link Core API the same way:
flb-package-linker enable-shared core-api
flb-package-linker install core-apiInspect and Undo Links
Check the current local-link state:
flb-package-linker status
flb-package-linker doctordoctor verifies the installed symlinks and reports duplicate Fleetbase package versions in the pnpm lockfile.
If you only want to undo specific links, disable them by name:
flb-package-linker disable fleetops pallet
flb-package-linker disable-shared ember-core ember-ui fleetops-data core-api
flb-package-linker install fleetops pallet core-apiTo fully clear every development link managed by the linker, use reset:
flb-package-linker reset --dry-run
flb-package-linker reset
flb-package-linker installThe dry run previews the manifest changes first. The real reset restores linked extensions and shared packages back to their saved registry ranges, removes Composer path repositories, removes local pnpm workspace entries and overrides, and deletes .fleetbase-dev-links.json once it is empty.
The linker stores original dependency ranges in .fleetbase-dev-links.json so the changes are reversible. That file is for local development state and should stay out of commits.
The commands above expect the current monorepo layout where console/, api/, and packages/ sit beside each other. Run flb-package-linker list to see which packages are recognized as extensions and which shared development dependencies can be linked.
Backend Development
Mount Source into Docker
To work on the API or packages with live source, add volume mounts in docker-compose.override.yml so your local files are used directly by the running containers:
services:
application:
environment:
ENVIRONMENT: "development"
APP_DEBUG: "true"
volumes:
- ./api:/fleetbase/api
- ./packages:/fleetbase/packagesAfter updating the override file, restart the stack:
docker compose up -dManual Backend Package Links
The package linker is the recommended workflow, but the underlying Composer setup is simple. To develop a backend package locally by hand, add a path repository entry in api/composer.json for each package. Composer will symlink the local directory into the vendor tree:
{
"repositories": [
{ "type": "path", "url": "../packages/fleetops", "options": { "symlink": true } },
{ "type": "path", "url": "../packages/pallet", "options": { "symlink": true } },
{ "type": "path", "url": "../packages/core-api", "options": { "symlink": true } }
]
}Then run Composer inside the application container to resolve the links:
docker compose exec application composer installAfter Composer installs, run the deploy script to apply any new migrations from the linked packages:
docker compose exec application bash -c "./deploy.sh"Octane and PHP Changes
Fleetbase runs Laravel Octane, which keeps the application in memory for performance. PHP file changes are not picked up automatically. After editing any PHP file, reload the Octane worker:
docker compose exec application php artisan octane:reloadIf you add new migrations, run them directly:
docker compose exec application php artisan migrateFrontend Development
There are two paths for frontend development: running the Ember dev server inside Docker, or running it locally on your machine. Both give you hot module replacement and live reload on file changes.
Path A — Docker (Dockerfile.server-build)
Dockerfile.server-build runs ember serve inside a container instead of doing a production build. This is useful if you want to keep everything in Docker without installing Node locally.
Override the console service in docker-compose.override.yml to build from the dev Dockerfile and mount your local source:
services:
console:
build:
context: ./console
dockerfile: Dockerfile.server-build
volumes:
- ./console:/console
- /console/node_modules
ports:
- "4200:4200"Then rebuild and start the console container:
docker compose up -d --build consoleThe console will be available at http://localhost:4200 with live reload on changes inside ./console/.
Path B — Local Ember Dev Server
Stop the console container and run the Ember dev server directly on your machine:
docker compose stop console
cd console
pnpm install
pnpm start:devThe console will be available at http://localhost:4200. This is the fastest iteration path — the dev server watches console/, packages/*/addon/, and any link:-ed addons, and live-reloads on changes.
Make sure console/environments/.env.development has API_HOST pointing at your running API container before starting:
API_HOST=http://localhost:8000Manual Frontend Package Links
The package linker is the recommended workflow for frontend packages too. If you need to make the change manually, open console/package.json and add a link: entry pointing to the package's root directory. The link: protocol tells the package manager to use your local filesystem copy instead of the published version:
{
"dependencies": {
"@fleetbase/fleetops-engine": "link:../packages/fleetops",
"@fleetbase/pallet-engine": "link:../packages/pallet"
}
}When working on shared packages such as @fleetbase/ember-ui, @fleetbase/ember-core, or @fleetbase/fleetops-data, prefer flb-package-linker enable-shared instead of manual link: entries. The linker configures pnpm workspace overrides and deep workspace linking so extension dependencies also resolve to the local package.
Then install dependencies in the console to resolve the links. Inside the console container (Path A):
docker compose exec console pnpm installOr locally (Path B):
cd console
pnpm installWorking on a Package
With volumes mounted and packages linked, the typical workflow for editing an extension package is:
Backend changes (PHP — packages/your-package/server/)
Edit the PHP files directly. After saving, reload Octane so the worker picks up the changes:
docker compose exec application php artisan octane:reloadIf you add new migrations, run them directly:
docker compose exec application php artisan migrateFrontend changes (Ember — packages/your-package/addon/)
The Ember dev server (either Docker or local) watches linked addons and live-reloads automatically. No additional steps needed.
Building a New Extension
To scaffold a new extension from scratch, use the Fleetbase CLI:
npm install -g @fleetbase/cli
flb scaffoldThe CLI runs interactively and prompts for the extension name, description, author, PHP namespace, and repository URL. It generates a new package with the correct structure (addon/, server/, package.json, composer.json) ready to link using the steps above.
You can also pass options directly to skip the prompts:
flb scaffold --name my-extension --namespace "MyCompany\\MyExtension"See the flb scaffold command reference for all available flags, and the Extension Development Quickstart for a full walkthrough of building and registering a new extension.
Licensing
Fleetbase is licensed under the GNU Affero General Public License v3 (AGPL-3.0). If you modify Fleetbase or build extensions that run as part of a networked service, the AGPL requires that you make your modified source code publicly accessible to users of that service.
If you intend to keep your modifications or extensions private — for example, as part of a commercial product or internal platform — you will need a commercial license. Book a call to discuss licensing options, or visit the Licensing page for further information.