Development Guide
This guide covers the development process and tools used in the Whitebox project and how you can develop new features or plugins for Whitebox and contribute to the project.
Prerequisites¶
- Docker (for running the Whitebox server)
- git-lfs (for downloading asset files)
- git (for cloning the repository)
Understanding Docker Configuration¶
To facilitate easy deployment and testing, Whitebox includes Docker configurations. Dockerfiles define the necessary environment for running or developing the Whitebox, including all required dependencies and configuration. Compose files orchestrate the setup of the server, database, and other services.
All Whitebox containers build on a shared whitebox-base image that is
published to the GitLab container registry. It bundles Python 3.14, Node.js 22,
Poetry, and common system libraries so that backend, frontend, and CI jobs all
start from the same consistent foundation. See
Docker Registry Images for details.
The Dockerfile is usually configured in two stages: one for building the application and another for running it. This separation optimizes the build process and reduces the final image size.
Setting up Development Environment¶
The recommended way developers working on Whitebox is to use the dev containers. It is a pre-configured Docker container that includes all the necessary dependencies and tools for development. Once launched, the container will simply start an environment.
To access the environment, you will need to enter the shell of the container (think "SSH-ing" into the container). From there you can access the environment, install project dependencies, run the required services, etc, same as you would with an SSH session.
This allows you to develop code on your local machine and run it in the container without having to rebuild the container each time you make a change.
Starting Development Containers¶
For a primary checkout, create a .env file in the repository root. You can use
the provided .env.example file as a template:
Edit the .env file to set variables as needed. Linked worktrees may either
have their own .env or reuse the primary checkout's ignored .env. The
development wrapper selects configuration in this order:
- The file named by
WHITEBOX_DEV_ENV_FILE(relative paths are resolved from the directory where the wrapper is invoked). .envin the active worktree..envin the primary checkout, for a linked worktree.
It fails without reading Compose configuration if none of these is usable. To
select a file explicitly, for example, run
WHITEBOX_DEV_ENV_FILE=/path/to/dev.env make dev-up.
Start the development containers from the repository root:
Always use the root make dev-* targets for common operations or
./bin/dev-compose ... for other development Compose operations. The wrapper
derives a stable project identity from the canonical worktree path and anchors
Compose, source mounts, plugin mounts, and project resources to that worktree.
Raw Compose invocations and global container-targeted commands bypass that
boundary and can target the wrong checkout.
Published development ports are dynamic and bind to loopback by default so
separate worktrees can run concurrently without exposing development services.
Print the same-origin browser URL with make dev-url; discover a directly
published service port with
make dev-port service=<service> port=<container-port>. Other common commands
are:
On a trusted private network, VPN/overlay, or appropriately firewalled worker, bind published ports to every host interface by starting the project in host mode:
This exposes development databases, debugger ports, and other unauthenticated
services. To bind the configurable mappings to only one interface instead,
provide its address directly, for example
BIND_ADDR=10.42.0.1 ./bin/dev-compose up -d. The streaming profile's SRS
mappings remain externally bound regardless of BIND_ADDR. Continue to use
make dev-url and make dev-port to discover dynamic ports. If Docker reports
0.0.0.0, remote clients must substitute the worker's hostname or IP address;
0.0.0.0 is not a client destination.
Port bindings are selected when containers are created. docker compose restart
retains existing bindings; running up -d with a different effective bind
address may recreate affected containers.
Normal make dev-down preserves that worktree's project volumes. To enter the
backend container shell, run:
To enter the frontend container shell, run:
Both containers install the necessary development dependencies during build. They intentionally idle after startup; start backend and frontend processes as described below when you need them.
Hardware, host-monitoring, and streaming capabilities are opt-in because they control physical devices, host-global networking, or fixed streaming ports. Enable a profile through the wrapper, for example:
./bin/dev-compose --profile hardware up -d
./bin/dev-compose --profile host-monitoring up -d
./bin/dev-compose --profile streaming up -d
Each of these profiles may be owned by only one development project on a host at a time. The profile-free stack is the supported concurrent-worktree default.
Optional Opencode harness config¶
Contributors who use Opencode can find the shared Whitebox harness config in
whitebox-llm-support.
Follow that repository's README for setup; this guide intentionally does not
duplicate those instructions. Project-specific agent behavior remains defined by
the root AGENTS.md in each Whitebox repository.
To install new dependencies, make sure to use dev container shell. It is also recommended to rebuild the dev container after adding new dependencies to ensure they are cached at the build stage making future builds faster. To rebuild the containers:
Then start the containers:
Running the Django backend development server¶
-
Ensure development environment is set up.
-
Run the Whitebox server:
This starts the Django development server. Use make dev-url for the normal
same-origin browser entrypoint, or
make dev-port service=backend-dev port=8000 to discover its directly
published address. Changes you make to the backend will be automatically
reloaded.
Plugins' JSX files are transpiled only on backend startup. If you make changes to the plugins' JSX code, you will need to restart the backend server for them to get re-transpiled, and then refresh the frontend app.
Running the React frontend development server¶
-
Ensure development environment is set up.
-
Run the frontend development server:
Use make dev-url for the browser-facing nginx URL. If direct Vite access is
needed, run make dev-port service=frontend-dev port=3000 to discover its
published address. The development server has automatic reloading enabled, so
you can see your changes in real-time.
This applies only the frontend project's code. In case you make changes to the plugins' JSX code, you will need to refresh the page for changes to take effect.
Running the RQ workers¶
-
Ensure development environment is set up.
-
Run the RQ worker:
This will start an RQ worker process that is going to process the tasks as they
are added into the queue. If you need to run multiple workers for parallelized
processing, you can run the run-worker command multiple times from multiple
terminals.
Commands¶
Whitebox includes Makefiles with commands you can run inside the development
containers for common development tasks.
Backend Commands¶
Setup Commands¶
These commands are for Whitebox setup, and need to be run inside the whitebox directory.
-
setup-network: Configure network interface naming for Orange Pi.Usage:
- Sets M.2 Wi-Fi interface's name to
wlan-ap - Required for Wi-Fi access point setup
- Sets M.2 Wi-Fi interface's name to
-
setup-sdr-udev: Set up udev rules for SDR devices.Usage:
- Downloads and installs Stratux/SDR device udev rules
- Reloads udev rules automatically
Development Commands¶
First, enter the container's shell:
and then you can use the following Makefile commands (format: make <COMMAND>):
migrate: Apply database migrationsrun: Start the backend server for productionrun-dev: Start the backend server for developmentrun-for-test: Start the backend server in test mode-
test: Run backend tests -
build_federation_modules: Builds federation modules for all the plugins that are available to Whitebox. Useful for quicker iterations during development. -
build_federation_modules_watch: Builds all plugin modules just as above, but also includes tests and watches for their file changes & rebuilds them -
download_external_assets: For whitebox to function offline, it needs to download external assets like videos, external JS libraries, etc. for both plugins and whitebox itself. This command downloads all the external assets -
clean: All the downloaded external assets will be removed. Whitebox will not function without these assets. -
makemigrations: Create migrations for all the plugins -
fmt: Format code using ruff run-mkdocs: Run the MkDocs server for documentation
Frontend Commands¶
First, enter the container's shell:
and then you can use the following Makefile commands (format: make <COMMAND>):
run: Start the frontend server for developmentrun-for-test: Start the frontend server in test modetest: Run all frontend testsunit_test: Run kernel's unit testsintegration_test: Run kernel's integration testsfederation_unit_test: Run plugins' unit tests (requires backend server running in test mode)federation_integration_test: Run plugins' integration tests (requires backend server running in test mode)test_e2e: Run end-to-end tests (requires frontend server running in test mode)
lint: Run lint checkers on the code
Plugin Commands¶
During development, plugins should be placed in the plugins/ directory, which
is mounted into the backend service at /plugins for easy access.
Sometimes, work can span over multiple plugins. As there can be quite a bit of
plugins in there, within /plugins directory, there's a Makefile that exposes
some helper commands:
make [help]- Print a list of available commandsmake check-dirty- List plugin repos that have uncommited changesmake diff-dirty- Show diff of all uncommited changes in all plugin reposmake sync-main- Check and pullmainbranch for all plugin reposmake checkout-if-available branch=BRANCH_NAME- Checkout branch in all repos where it exists and printpoetry addcommand at the end to run in the backend container for convenience
Testing¶
Backend testing¶
Whitebox implements a custom test runner that allows for running tests for whitebox and plugins within a single test suite by discovering all plugin tests and loadin them dynamically.
To run tests, along with plugin tests, you need to make sure your plugin adheres to guidelines outlined in the Plugin Guide.
- Ensure the development environment is set up.
-
Run the backend tests:
Frontend testing¶
Whitebox uses Vitest (with Playwright in Browser Mode) for frontend unit testing, and Playwright for integration testing. To run frontend tests:
- Ensure the development environment is set up.
-
Run the frontend tests:
This will run first the unit testing suite, and then the integration testing suite.
Federation testing¶
Federation modules require both frontend and backend to be running in order to test them - backend to build and serve the modules, and frontend to actually load and render the modules.
To run the federation tests, first run both servers in the testing mode (the two commands need to be run in separate terminals):
./bin/dev-compose exec backend-dev make run-for-test
./bin/dev-compose exec frontend-dev make run-for-test
Then, in a separate terminal, you can run the unit tests for the federation modules:
or, run the integration tests for the federation modules:
End-to-end testing¶
Whitebox uses Playwright for end-to-end testing. The setup steps for end-to-end testing are slightly different from the other tests, as it requires running both the frontend and backend servers in conjunction.
As the frontend and backend are running in separate containers, and the tests will
be run from the frontend container, the target hosts will be different—frontend
will effectively live on localhost, while the backend will be on backend host (if
using production containers), or backend-dev host (if using development containers).
For the tests to run successfully, you will need to ensure that the frontend application is configured to use the correct backend host from within the container.
To run end-to-end tests:
- Ensure development environment is set up.
- Run the backend environment that the frontend will use:
- Run the frontend environment, ensuring that the backend host is set correctly for the frontend build:
- Run the test suite on the frontend container:
Running the tests on LambdaTest¶
Whitebox uses LambdaTest for running frontend integration, and end-to-end tests on multiple browsers and devices.
When ran during CI, the end-to-end tests will be run against the sandbox environment, which is setup as one of the steps before the LambdaTest testing step. You can also run the tests on LambdaTest from localhost, if you have an account.
To run the tests on LambdaTest, you will need the following:
- LambdaTest username, later set as environment variable named
LT_USERNAME - LambdaTest access key, later set as environment variable named
LT_ACCESS_KEY
Similarly to the standard end-to-end test run, you'll need to setup frontend and backend environments, and then run the tests against them:
- Ensure development environment is set up.
-
Run the backend environment that the frontend will use:
-
Run the frontend environment, ensuring that the backend host is set correctly for the frontend build:
-
Run the LambdaTest test suites on the frontend container:
# Enter the frontend container shell make dev-frontend-shell # Set the LambdaTest credentials in the environment export LT_USERNAME=<your_lambdatest_username> export LT_ACCESS_KEY=<your_lambdatest_access_key> # Run the integration tests on LambdaTest yarn run test_integration:lambdatest-tunnel # Run the end-to-end tests on LambdaTest yarn run test_e2e:lambdatest-tunnel
Using *-tunnel commands, the tests will run using the LambdaTest tunnel which is preconfigured in the dev container. This allows for testing on local environments. This is useful when you want to run tests against the dev container running on your local machine.
You may also set environment variables like LT_USERNAME and LT_ACCESS_KEY in the .env file in the root of the project. Refer to the .env.example file for the required variables. This will allow you to run the tests from the host machine without having to set them each time like so:
Ensure you do poetry install at the root of the project to install all the required dependencies for the get-env script to work.
If you want to run the tests without the tunnel, against a sandbox, you can run the integration tests with:
or end-to-end tests with:
Debugging¶
For comprehensive debugging procedures including Insta360 connection troubleshooting, check the Troubleshooting section.
VSCode¶
- Install VSCode and open the
whiteboxproject in VSCode. - Add Python language support by installing the extension.
- JS Language support and chrome debugger support is available by default.
- If using firefox browser, you would need to install this extension.
Backend Debugging¶
- On the host, run
make dev-port service=backend-dev port=5678and updateDebug Backend'sconnect.portin.vscode/launch.jsonwith the reported port. - Enter the backend dev container's shell with
make dev-backend-shell. - Run
make debug(the server waits for the debugger before starting). - In Run & Debug, select
Debug Backendand click the play button.
Frontend Debugging¶
- On the host, run
make dev-port service=frontend-dev port=9229and updateDebug Vite Server'sportin.vscode/launch.jsonwith the reported port. - Run
make dev-urland update theDebug ChromeorDebug FirefoxURL with the reported browser URL. - Enter the frontend dev container's shell with
make dev-frontend-shell, then runmake debug. - In Run & Debug, select
Debug Frontend (Chrome)orDebug Frontend (Firefox)and click the play button.
The checked-in ports and URLs are defaults only; runtime-assigned values are specific to the active worktree and may change after container recreation.
PyCharm¶
Remote debugging on PyCharm works only on the Professional Edition and can take some work to fully set up. Community edition does not support remote debugging in any capacity.
You can find the detailed explanation and setup steps in PyCharm debugging.
Contributing¶
- Fork the repository
- Create a new branch for your feature
- Make your changes
- Run tests and ensure they pass
- Submit a pull request
Google Docstring Conventions should be followed for all code documentation.
Documentation¶
Documentation for Whitebox is generated using MkDocs. To run documentation locally, make sure you have Whitebox repository cloned and set up as per the instructions above.
To run the documentation server:
- Ensure development environment is set up.
-
Enter the backend container shell:
3. Run the documentation server:
Versioning¶
Whitebox uses Semantic Versioning for versioning.
In the CI configuration, the update_version stage is responsible for updating the
version of the project. Backend and frontend versions are kept in sync, with the backend's
version used as a reference point.
When a merge request is merged to main, first, patch version will be bumped in the
pyproject.toml file for backend, and that same version number will then be applied to
package.json for frontend. This is done by the script located in
packaging/scripts/maintenance/whitebox_update_version.py.
Afterward, a commit will be made with the new version, which will then be tagged, and the CI will push these changes to the repository.
Adding temporary dependencies to CI¶
Sometimes you need to add a temporary dependency to the CI environment that you do not want to be included in the project's dependencies upon merge. You may want to do this when you are working on Whitebox core and a plugin in parallel. In these cases, the plugins' changes would only be available on its own branch, which are not published in PyPI, so you have to install them directly from Git.
To do this, you can add the dependency to the plugins-temporary Poetry group.
Tests and sandbox will be run with these temporary dependencies installed (they take
precedence over the "default" ones from the pyproject.toml file), but as it's an
optional group, they won't be included in the final project dependencies. This
change will be safe to merge, as the CI will perform the cleanup (for more info,
take a look how the maintenance CI step works).
You can reference a Git branch directly in the poetry add command, by doing:
For example, to add a temporary dependency with Git URL
https://gitlab.com/whitebox-aero/whitebox-plugin-gps-display.git, with a branch
feature/my-new-feature, you can run:
poetry add --group plugins-temporary git+https://gitlab.com/whitebox-aero/whitebox-plugin-gps-display.git#feature/my-new-feature
During development, dev containers automatically include the temporary dependencies
group, so you can use them right away. However, if you want temporary dependencies in production, you need to set the TEMPORARY_DEPENDENCIES environment variable to 1 in .env file before building the production containers.
Next Steps¶
- Learn more about the Whitebox Architecture
- Check out the Development Guide