Files
Stalwart-webui/DEVELOPMENT.md
T
Steven RYDELL f4c8f8f21c feat(dev): add one-command local Stalwart test server + workflow docs
Add docker-compose.yml: a disposable Stalwart instance with a fixed dev
admin account (STALWART_RECOVERY_ADMIN), matching the credentials
scripts/dev-token.ps1 already expected. Wired up via new npm scripts
(dev:server, dev:server:down, dev:server:logs).

scripts/dev-token.ps1 was previously untracked (the whole scripts/
directory was gitignored) even though it's part of the documented dev
workflow — un-ignored it, and added scripts/dev-token.sh, a POSIX
equivalent for non-Windows shells and AI agents without PowerShell.

New DEVELOPMENT.md documents the full loop end-to-end (start server,
get a token, run the dev server, verify), written so it's actionable by
both humans and AI coding agents without needing a browser. Linked from
AGENTS.md (Commands) and README.md (Getting started).

Verified manually: docker compose up brings the server to a healthy
state, /api/auth + /auth/token issue a working bearer token, and
/jmap/session returns 200 with it end-to-end.
2026-08-01 18:05:43 +02:00

3.6 KiB
Raw Blame History

Development

How to run a local Stalwart test server and develop this WebUI against it. This file is meant to be read by humans and AI coding agents alike — see AGENTS.md for the rules that also apply while doing this.

Prerequisites

  • Node.js 18+
  • Docker (with the docker compose CLI plugin)

1. Start a local test server

npm run dev:server

This runs docker compose up -d, which starts a disposable Stalwart instance (docker-compose.yml) with:

  • The management/JMAP HTTP API on http://localhost:8080 (the only port the WebUI dev proxy needs — see server.proxy in vite.config.ts).
  • Mail protocol ports (SMTP/IMAP/POP3/ManageSieve) exposed too, only needed if you're testing actual mail flows, not just admin UI screens.
  • A fixed admin account baked in via STALWART_RECOVERY_ADMIN: admin@example.org / c8321iEscHDy0GWV. Disposable dev credentials only — never reuse them for anything real.
  • Named Docker volumes (stalwart-etc, stalwart-data) so data survives a restart. Data persists until you tear the volumes down.

Useful companions:

npm run dev:server:logs   # tail the container's logs
npm run dev:server:down   # stop it (add `-v` via `docker compose down -v` to also wipe data)

The server takes a couple of seconds to come up; docker compose logs stalwart will show Network listener started ... localPort = 8080 once it's ready.

2. Get an access token

The WebUI normally authenticates through an OAuth flow in the browser, but for local development it's simpler to skip that and use a bearer token directly via VITE_ACCESS_TOKEN (see .env.development).

# Windows / PowerShell
pwsh ./scripts/dev-token.ps1

# Linux / macOS / any POSIX shell (including most AI agent sandboxes)
bash ./scripts/dev-token.sh

Both scripts log in as the dev container's admin account, run the full OAuth PKCE flow against it, and write the resulting token to .env.development.local (gitignored, never committed). Tokens expire after 1 hour — re-run the script and restart npm run dev if the UI starts returning 401s.

3. Run the WebUI

npm install   # first time only
npm run dev

Open http://localhost:5173. You should land directly in the admin panel (no login screen) since VITE_ACCESS_TOKEN is set.

4. Verify your change

npm run typecheck
npm run lint
npm test
npm run build

For UI changes, actually look at the running app (browser or a browser automation tool) — passing typecheck/lint/tests proves the code compiles and existing behavior didn't regress, it doesn't prove the new UI works.

Resetting the test server

To start from a completely clean server (e.g. to re-test first-run behavior):

npm run dev:server:down
docker compose down -v   # also removes the stalwart-etc/stalwart-data volumes
npm run dev:server

Notes for AI agents

  • This whole workflow (steps 13) is scriptable end-to-end without a browser: npm run dev:server, then bash scripts/dev-token.sh, then the app is reachable at http://localhost:5173 with VITE_ACCESS_TOKEN already set. Verify backend connectivity directly with curl, e.g. curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/jmap/session.
  • Read AGENTS.md before touching anything under src/ — the schema-fidelity rule applies to all development, local test server or not.
  • Don't commit .env.development.local (it holds a live token) or leave the dev container running unexpectedly — npm run dev:server:down when you're done.