Skip to main content
This guide is for changes to Druks itself. The backend and Vite development server operate on the host. Compose supplies isolated Postgres and Redis.

Set up

From the repository root:
Paste the generated value into secrets.secrets_key in druks.toml, then initialize the development database:
Settings reads ./druks.toml from the current directory. The example uses [identity].mode = "none". The loopback dashboard has no authentication and exactly one operator account. Your first harness connection creates this account. To use header mode with the development server, set identity.mode = "header" in druks.toml. Set identity.header in the same file. Then send the header with a browser add-on or curl -H 'X-Edge-Email: you@example.com'. The dev Compose project creates two databases:
  • Development: druks_dev for the host-run server.
  • Tests: druks_test for pytest. The suite rebuilds this schema.
.env.example points the server at druks_dev. The suite reaches druks_test and Redis index 15 through DRUKS_TEST_DATABASE_URL and DRUKS_TEST_REDIS_URL. It does not use the server settings. Thus, the two databases cannot be confused. Start the backend:
In another terminal:
Vite proxies API traffic to the backend. The production backend image instead contains the built SPA and serves it from FastAPI.

Architecture map

The API process embeds DBOS and executes workflows. App modules register capabilities during boot, after DBOS initialization and before launch.

App test surface

The main package registers bundled apps through pyproject.toml. CI also installs backend/tests/druks-field_notes as a real editable distribution and runs the proof-app tests. Those tests are the executable contract for:
  • Headless and boot-time entry-point loading
  • Role-module discovery
  • Route and subject read-side mounting
  • Independent migrations and table-prefix enforcement
  • Workflow start, settings, and feed formatting.
If you change the author API, update the scaffold, proof app, author guide, and tests together.

Database changes

Core and bundled historical tables use the core Alembic history:
For an independently packaged app:
The app owns its migration directory and version table. Review every autogenerated revision before applying it.

Verification

Backend checks:
The suite builds its subjects from field_notes, the proof app. This standalone distribution depends on Druks. It installs like an author app, not as a Druks dependency. Install it one time for the full suite. The pull-request backend workflow does the same. Pyright is available for local and editor use. It is not a CI gate. Frontend checks:
The frontend CI workflow runs those three commands on Node 22. For documentation-only changes, also run these commands:
Mintlify builds docs/ directly. Its GitHub App owns deployments and pull-request previews. The repository does not require a documentation-specific GitHub Actions workflow.

Working with sandboxes

Backend tests mock most provider boundaries. For a real local sandbox, run Drukbox on the host from its own checkout (DOCKER_SSH_USERNAME=druks make dev in czpython/drukbox) and set:
uv run druks doctor --sandbox creates a real host. If you require a real sandbox test, run this command. It is not part of the normal test suite.

Frontend ownership

Backend app entry points and shared-shell React routes have different delivery mechanisms. Python discovery can load an installed app at runtime. An app can ship a standalone static frontend in its package’s dist/, served at /app/<name>. React code that joins the bundled dashboard shell must already be in the SPA and register through frontend/src/apps/index.ts. A wheel cannot put routes into that existing JavaScript bundle. See the frontend guide before adding dashboard pages.