Skip to content

Development Startup ​

This page describes the most common local development setup with three processes: EMQX started by Docker, the FastAPI backend started on the host machine, and the Vite frontend started on the host machine. For full Docker deployment, see Docker Deploy.

Version Requirements ​

Local development should stay aligned with the repository and Docker build environment:

ComponentVersion / ConstraintNotes
Python>=3.12Required by backend src/pyproject.toml. The recommended local setup is a conda environment such as wfm.
Node.js22.xFrontend Docker build uses node:22-alpine.
pnpm10.33.0Docker build pins this version.
EMQX5.8.5Docker Compose uses emqx/emqx:5.8.5.

Dependency installation changes the local environment and should be done manually by the maintainer. Automation helpers must not install, upgrade, or remove dependencies on behalf of the maintainer.

Startup Order ​

Start the development environment in this order:

  1. Start EMQX with Docker.
  2. Start the backend with uvicorn.
  3. Start the frontend with pnpm run dev.

1. Start EMQX ​

Reuse the EMQX configuration from the SQLite deployment directory:

bash
cd docker/sqlite
cp .env.example .env

Change the callback URL to the host machine:

dotenv
WFM_EMQX_AUTHZ_URL=http://host.docker.internal:8000/api/internal/emqx/authz

Uncomment the EMQX Dashboard/API port 18083 in the compose file, otherwise EMQX callback and management features cannot work correctly during local development.

Start only EMQX:

bash
docker compose up -d emqx

2. Start the Backend ​

The backend is started from src/ and reads src/.env.

Enter the backend directory:

bash
cd src
python -m pip install -e .[dev]
cp .env.example .env

Notes:

  • WFM_ENABLE_DEV_TEST_API=true registers /api/v0 and relaxes production source checks. Use it only for development.
  • WFM_EXTRA_ALLOWED_ORIGINS must include the Vite frontend origin, otherwise browser requests from 5173 are rejected by source checks.
  • WFM_MQTT_URL is the broker URL used by the backend. When the backend runs on the host and EMQX runs in Docker, use 127.0.0.1:1883.
  • WFM_EMQX_API_BASE_URL is the EMQX Dashboard/API URL used by the backend. This requires port 18083 to be exposed for development.
  • WFM_PUBLIC_ORIGIN affects client downloads, bind commands, and some public URLs. For frontend local development, it usually points to the backend address.

Start with uvicorn:

bash
python -m uvicorn app.main:app --host 127.0.0.1 --port 8000 --reload --reload-exclude data --timeout-graceful-shutdown 1

Common backend URLs:

  • API docs: http://127.0.0.1:8000/docs
  • Health check: http://127.0.0.1:8000/api/v1/system/health
  • SSE: http://127.0.0.1:8000/api/v1/events/stream

3. Start the Frontend ​

The frontend uses Vite:

bash
cd front
pnpm run dev

Open:

text
http://127.0.0.1:5173

When the frontend runs on 5173, API and SSE requests default to the same host on port 8000:

text
http://127.0.0.1:8000

If you need to explicitly set the backend URL before starting the frontend:

bash
export VITE_API_BASE_URL='http://127.0.0.1:8000'
pnpm run dev

The frontend does not use Vite proxy. Cross-origin access during development is controlled by backend source settings.

Common Issues ​

The frontend opens, but API requests are rejected ​

Check src/.env first:

dotenv
WFM_ENABLE_DEV_TEST_API=true
WFM_EXTRA_ALLOWED_ORIGINS=["http://127.0.0.1:5173","http://localhost:5173"]

If you access the frontend from a phone or another LAN device, add that origin to WFM_EXTRA_ALLOWED_ORIGINS and make sure the backend Host restriction allows that access path.

The backend reports MQTT or EMQX errors ​

Check in order:

  1. Whether the EMQX container is running.
  2. Whether 1883 is mapped to the host.
  3. Whether 18083 is temporarily exposed for development.
  4. Whether src/.env and docker/sqlite/.env use the same EMQX username, password, and AuthZ shared key.
  5. Whether docker/sqlite/.env points WFM_EMQX_AUTHZ_URL to http://host.docker.internal:8000/api/internal/emqx/authz.

Backend reload keeps restarting ​

Confirm the startup command includes:

bash
--reload-exclude data

src/data is the local runtime data directory. It stores the database, download artifacts, bulk config packages, and snapshots. Changes there should not trigger backend reloads.