Documentation Index
Fetch the complete documentation index at: https://mintlify.com/davidG97/qa-flow/llms.txt
Use this file to discover all available pages before exploring further.
QA Flow ships as a self-contained Docker image that bundles the React frontend, Express backend, and a Chromium browser for running Playwright tests. You can be up and running in seconds with a single docker run command, and scale to a full Compose stack with PostgreSQL or Turso when you’re ready for production.
Quick Start
The fastest way to launch QA Flow is a single Docker command. It starts the server on port 3001 and uses named volumes to persist your SQLite database, screenshots, and recordings across container restarts.
docker run -it --rm \
-p 3001:3001 \
-e JWT_SECRET="your-secret-min-32-chars" \
-v qa-flow-data:/app/data \
-v qa-flow-screenshots:/app/server/screenshots \
-v qa-flow-recordings:/app/server/recordings \
davidg1997/qa-flow
Once the container starts, open http://localhost:3001 in your browser. Log in with the default credentials (admin@qaflow.com / admin123) and change the password immediately.
The default admin credentials are admin@qaflow.com / admin123. You must change them immediately after your first login — never leave the defaults in place in any environment that is accessible from outside your machine.
Named Volumes
QA Flow uses three named Docker volumes to keep your data safe across container lifecycle events:
| Volume | Mount path | Purpose |
|---|
qa-flow-data | /app/data | SQLite database file (qa-flow.db) |
qa-flow-screenshots | /app/server/screenshots | Test run screenshots |
qa-flow-recordings | /app/server/recordings | Browser session recordings |
Docker manages these volumes automatically. To back up your data, run docker run --rm -v qa-flow-data:/data busybox tar czf - /data and redirect the output to a file.
Environment Variables
All runtime configuration is passed via environment variables:
| Variable | Description | Default |
|---|
PORT | HTTP port the server listens on | 3001 |
JWT_SECRET | Secret used to sign JWT tokens — required in production | change-me-in-production |
DATABASE_URL | Database connection string | file:/app/data/qa-flow.db (SQLite) |
TURSO_AUTH_TOKEN | Auth token when using Turso cloud database | — |
CDP_URL | Remote Chrome DevTools Protocol URL (optional) | — |
Never leave JWT_SECRET as the default value in production. Generate a cryptographically random string of at least 32 characters before deploying. See the Security guide for instructions.
Docker Compose
Docker Compose lets you manage the container alongside its volumes and environment variables in a single file. QA Flow ships with separate Compose files for standard use and production use with PostgreSQL.
The default docker-compose.yml uses the pre-built image from Docker Hub with SQLite for local persistence. This is the recommended starting point for most users.# docker-compose.yml
services:
qa-flow:
image: davidg1997/qa-flow:latest
container_name: qa-flow
ports:
- "${PORT:-3001}:3001"
environment:
- NODE_ENV=${NODE_ENV:-production}
- PORT=3001
- DATABASE_URL=${DATABASE_URL:-file:/app/data/qa-flow.db}
- JWT_SECRET=${JWT_SECRET:-change-me-in-production}
volumes:
# Persist SQLite database
- qa-flow-data:/app/data
# Persist screenshots and recordings
- qa-flow-screenshots:/app/server/screenshots
- qa-flow-recordings:/app/server/recordings
restart: unless-stopped
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3001/api/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
volumes:
qa-flow-data:
name: qa-flow-data
qa-flow-screenshots:
name: qa-flow-screenshots
qa-flow-recordings:
name: qa-flow-recordings
Start it with: The docker-compose.prod.yml overlay extends the standard file with a PostgreSQL service. Compose merges both files at startup — QA Flow waits for Postgres to pass its health check before starting.# docker-compose.prod.yml
services:
qa-flow:
depends_on:
postgres:
condition: service_healthy
environment:
- DATABASE_URL=postgresql://qaflow:${POSTGRES_PASSWORD:-qaflow_secret}@postgres:5432/qaflow?schema=public
- JWT_SECRET=${JWT_SECRET:?JWT_SECRET is required in production}
postgres:
image: postgres:16-alpine
container_name: qa-flow-postgres
environment:
- POSTGRES_USER=qaflow
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-qaflow_secret}
- POSTGRES_DB=qaflow
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U qaflow -d qaflow"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
postgres-data:
name: qa-flow-postgres-data
Start the combined stack with:docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
The production overlay requires JWT_SECRET to be set as an environment variable or in a .env file. The :? syntax in the Compose file causes the startup to fail fast with a clear error message if it is missing.
The docker-compose.dev.yml file is intended for contributors who want to test the production image built from their local source. It builds from the Dockerfile in the repository root instead of pulling from Docker Hub.# docker-compose.dev.yml
services:
qa-flow:
build:
context: .
dockerfile: Dockerfile
container_name: qa-flow-dev
ports:
- "${PORT:-3001}:3001"
environment:
- NODE_ENV=development
- PORT=3001
- DATABASE_URL=file:/app/data/qa-flow.db
- JWT_SECRET=dev-secret-not-for-production
volumes:
- qa-flow-dev-data:/app/data
- qa-flow-dev-screenshots:/app/server/screenshots
- qa-flow-dev-recordings:/app/server/recordings
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3001/api/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
volumes:
qa-flow-dev-data:
name: qa-flow-dev-data
qa-flow-dev-screenshots:
name: qa-flow-dev-screenshots
qa-flow-dev-recordings:
name: qa-flow-dev-recordings
Build and start with:docker compose -f docker-compose.dev.yml up --build
Cloud Database with Turso
For teams who want a lightweight cloud database without managing a Postgres instance, QA Flow supports Turso via the libsql driver. Pass your Turso database URL and auth token as environment variables — no volumes are needed for database persistence.
docker run -it --rm \
-p 3001:3001 \
-e DATABASE_URL="libsql://your-db.turso.io" \
-e TURSO_AUTH_TOKEN="your-token" \
-e JWT_SECRET="your-secret-min-32-chars" \
davidg1997/qa-flow
You still need the screenshot and recording volumes even when using Turso, since those files are stored on the container filesystem rather than in the database. Add -v qa-flow-screenshots:/app/server/screenshots -v qa-flow-recordings:/app/server/recordings to the command above.
Port Mapping
By default QA Flow binds to port 3001 inside the container. The -p 3001:3001 flag in the examples above maps that to port 3001 on your host. To use a different host port, change the left-hand side of the mapping:
# Serve on host port 8080 instead
docker run -it --rm -p 8080:3001 davidg1997/qa-flow
When using Docker Compose, set the PORT environment variable in a .env file:
PORT=8080
JWT_SECRET=your-secret-here
Health Check
The container exposes a health endpoint at GET /api/health. Docker’s built-in health check polls this endpoint every 30 seconds. You can also query it manually to verify the service is ready:
curl http://localhost:3001/api/health
A healthy response returns HTTP 200. The Docker health check is configured with the following parameters:
| Parameter | Value |
|---|
| Interval | 30 seconds |
| Timeout | 10 seconds |
| Retries | 3 |
| Start period | 10 seconds (grace period on startup) |