Self-hosting
Run the Zowar server and dashboard separately from the websites they measure.
Requirements
Use Python 3.11, Node.js 22 or newer, and npm. The pinned Python dependencies have been verified with 3.11; do not use Python 3.14 with the pinned psycopg2 package. SQLite is supported for local development. Use PostgreSQL for a hosted deployment.
Prepare your local workspace
From the repository root, run the helper below. It creates a Python virtual environment, installs dependencies, generates missing local configuration, runs Alembic migrations and installs the web app. Existing environment files are preserved. The helper only migrates a local file-backed SQLite database.
bash scripts/setup-local.sh
api/.venv/bin/python scripts/bootstrap-local.pyBootstrap prompts for a workspace name, email and password. It creates a tenant login without enabling public signup and refuses to replace an existing account. Keep the generated secrets local.
Start both services
API terminal
cd api .venv/bin/uvicorn app.main:app --reload --port 8000Dashboard terminal
cd web npm run dev
Open http://localhost:3000/app/login and sign in with your new account. Use localhost consistently; 127.0.0.1 is a different browser origin. Add a site and follow its installation wizard. To measure a local website, map a development domain such as demo.test to 127.0.0.1 and register that domain.
Manual setup
The repository README documents the equivalent virtual environment, dependency installation, secret generation, environment files and Alembic commands. Run API commands from api/ so settings can read api/.env. The local database defaults to sqlite:///./dev.db; tables are created by migrations, not by starting the server.
python3.11 -m venv api/.venv
api/.venv/bin/python -m pip install -r api/requirements.txt
# Create api/.env and web/.env.local as documented in README.md.
# From api/:
.venv/bin/alembic upgrade head
# From web/:
npm installConfiguration
- DATABASE_URL
- Local SQLite file or hosted PostgreSQL URL.
- SECRET_KEY
- A long random secret for session cookies and OAuth state.
- FERNET_KEY
- A generated Fernet key used to encrypt stored integration credentials.
- APP_BASE_URL
- Public API URL, used by the tracker and API redirects.
- WEB_BASE_URL
- Dashboard origin for browser CORS and redirects.
- NEXT_PUBLIC_API_BASE_URL
- Frontend API URL at build time; http://localhost:8000 locally and empty for same-origin hosted proxying.
- COOKIE_SECURE
- false for local HTTP; true behind hosted HTTPS.
- SIGNUPS_OPEN
- false by default; account creation remains operator-controlled.
- GOOGLE_REPORTING_ENABLED
- false by default. Enables optional reporting connections and conversion uploads when true. Google sign-in is separate.
- SMTP settings
- SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD and NOTIFY_FROM_EMAIL configure delivery. Each site's notify_email chooses the recipient.
Checks
# From api/
.venv/bin/python -m pytest -q
# From web/
npm run lint
npx tsc --noEmit
npm run buildUse a temporary local database to test migrations. Verify a real collected visit and lead submission in the browser before considering an installation complete.
Hosted deployment
Build Dockerfile.api and Dockerfile.web from the repository root. Run the API on port 8000 and web app on 3000 behind an HTTPS reverse proxy. Route /api/ and /t.js to the API; all other paths go to the web app. A missing /t.js route prevents websites from loading the tracker.
Use dedicated database credentials, strong secrets and reviewed migrations. Configure SUPERADMIN_EMAIL and SUPERADMIN_PASSWORD_HASH to use the /admin account-management flow. Generate the hash with app.auth.hash_password; a plaintext password does not belong in that setting.
The local setup scripts do not deploy anything. Do not point a development migration command at a hosted production database.