CLI reference¶
reflex-django adds two Django management commands. Plus the rest of manage.py keeps working as you'd expect. This page is a tour of what each command does and the flags that matter.
The two new commands¶
| Command | What it does |
|---|---|
python manage.py run_reflex |
Dev server: build the SPA, run uvicorn, watch for changes, restart on edit. |
python manage.py export_reflex |
Build the SPA bundle for production (CI). |
Plus everything you already use:
python manage.py migrate
python manage.py makemigrations
python manage.py createsuperuser
python manage.py shell
python manage.py collectstatic
Nothing changes about those.
manage.py run_reflex — the dev server¶
This is the one you'll run all day. It does three things:
- Build the SPA. Auto-runs
export_reflex(frontend-only, no zip, staged toSTATIC_ROOT/_reflex/) before starting. - Start uvicorn as a subprocess on port 8000 (or wherever you set
backend_port), pointed atreflex_django.asgi_entry:application. - Watch the project for
.pychanges. Each change cleanly stops uvicorn, re-runs the build, and starts a fresh uvicorn.
That's the default. Open http://localhost:8000/ and you have your admin at /admin/, the SPA at /, and the Reflex WebSocket on /_event.
Flags¶
| Flag | Effect |
|---|---|
--skip-rebuild |
Skip the SPA build before starting. Good for "I only edited a Django model" iterations. |
--no-reload |
Don't watch for changes. The server runs once and exits when you Ctrl+C. |
--env prod |
Set REFLEX_ENV to prod (changes a few default toggles — see Reflex's docs). |
--frontend-only |
Only build the SPA frontend; don't start the server. |
--backend-only |
Only run uvicorn; don't build the SPA. (Assumes the bundle is already on disk.) |
--with-vite |
Use the Vite hot-reload dev server proxied through Django. Hot-module reload on Reflex page edits. |
--port N |
Override the backend port. |
Common combos:
# Fast iteration on Django code only (skip SPA rebuilds)
python manage.py run_reflex --skip-rebuild
# Hot-module reload for Reflex page edits
python manage.py run_reflex --with-vite
# Build only, don't serve (useful in CI to verify)
python manage.py run_reflex --frontend-only
What it boots, in order¶
1. install_reflex_django_integration()
- configures Django, patches reflex.config.get_config, builds in-memory rxconfig
2. (unless --skip-rebuild)
export_reflex --frontend-only --no-zip --stage-to-static-root
3. uvicorn subprocess
reflex_django.asgi_entry:application on port 8000
4. parent process: watchfiles loop
- on .py change: stop uvicorn, re-export, start fresh uvicorn
Open the browser, the page loads, the WebSocket connects, you're in.
Common warnings, easily fixed¶
"DJANGO_SETTINGS_MODULE not set"
Set it in your shell: export DJANGO_SETTINGS_MODULE=config.settings. The auto-discovery via manage.py usually catches this, but if it can't, set it explicitly.
"Could not find compiled SPA"
The build hasn't run yet, or STATIC_ROOT isn't writable. Run python manage.py run_reflex once without --skip-rebuild.
Restart loop on every file
You're probably saving files in a watched directory that gets modified by the rebuild itself (.web/). Make sure your editor's "save" doesn't also touch generated files.
manage.py export_reflex — build the SPA bundle¶
For CI and production. Builds the compiled SPA and stages it where the runtime needs it.
That's the canonical invocation for a one-process production deploy.
Flags¶
| Flag | Effect |
|---|---|
--frontend-only |
Only build the React/Vite frontend. Skip the backend bundle. |
--backend-only |
The opposite. Rare. |
--no-zip |
Don't zip the output. (Zipping is the old Reflex deploy format; you don't want it here.) |
--stage-to-static-root |
Copy the build into STATIC_ROOT/_reflex/, where ReflexMountView serves it from. |
--zip-dest PATH |
If you do want a zip, where to put it. |
Typical CI sequence¶
uv sync --frozen
python manage.py migrate --noinput
python manage.py export_reflex --frontend-only --no-zip --stage-to-static-root
python manage.py collectstatic --noinput
# now start the ASGI server pointed at reflex_django.asgi_entry:application
The first two are standard Django. The third builds the SPA. The fourth picks up the SPA assets (plus your admin static files) into STATIC_ROOT. Your reverse proxy then serves /static/ directly from disk.
Reload precedence¶
When you save a file in dev:
watchfilesnotices the change.- If it's a
.pyfile inside the project (not in.web/,.venv/, etc.), the watcher triggers a restart. - The watcher sends SIGTERM to uvicorn; uvicorn shuts down its workers.
- The watcher re-runs the export (unless
--skip-rebuild). - The watcher starts a fresh uvicorn subprocess.
If you used --with-vite, edits to Reflex components hot-reload through Vite without restarting the Python process. Edits to states or non-page code still trigger a restart.
Customizing what's watched¶
By default, run_reflex watches BASE_DIR/**/*.py. To restrict or extend:
# settings.py
REFLEX_DJANGO_WATCH_PATHS = [
BASE_DIR / "config",
BASE_DIR / "shop",
BASE_DIR / "blog",
]
Or to ignore specific directories:
(These setting names are illustrative — check your installed version. The defaults usually work.)
The reflex django ... CLI entry point¶
There's also a reflex django command-line entry point that mirrors manage.py:
uv run reflex django migrate
uv run reflex django run_reflex
uv run reflex django collectstatic --noinput
It's a thin proxy that auto-discovers DJANGO_SETTINGS_MODULE from manage.py. Use whichever feels natural. For Django-first projects, python manage.py ... reads more naturally to most teams.
Troubleshooting matrix¶
| Symptom | Likely cause | Fix |
|---|---|---|
| Port already in use | Old uvicorn from a previous run still listening | pkill -f uvicorn or use --port N |
| Hot-reload stops working | Watcher process died silently | Restart run_reflex |
AppRegistryNotReady on start |
Model import at module top level | Move the import inside event handlers |
ModuleNotFoundError: rxconfig |
Old stub file present | Delete rxconfig.py; reflex_mount() is the only config |
| Browser shows white page | SPA bundle missing | Run without --skip-rebuild, or run export_reflex --frontend-only --stage-to-static-root |
Vite manifest not found (under --with-vite) |
Vite didn't start | Check the parent process logs; try without --with-vite |
Next: Testing →