Menu

Installation

Set up your development environment and run Oxidt Teams locally

Prerequisites

Make sure you have the following installed:

  • Rust (latest stable) — rustup.rs
  • Topcoat CLI — cargo install topcoat-cli --version 0.9.0 --locked
  • Bun — bun.sh (for Tailwind CSS)
  • Docker — for PostgreSQL and Mailpit

Quick Start

1

Clone the repository

bash
cd templates/teams-topcoat
2

Bootstrap your env file

bash
just bootstrap

This copies .env.example to .env and generates a fresh SESSION_SECRET for you.

The defaults sign you in by email code (Mailpit catches the mail) with no identity provider to set up. Edit .env if you need to change:

  • DATABASE_URL — PostgreSQL connection string (default: postgres://oxidt_teams:oxidt_teams@localhost:5496/oxidt_teams)
  • BASE_URL — Your app's base URL (default: http://localhost:8080)
  • COMING_SOON — off by default; set true to enable the pre-launch waitlist
3

Start infrastructure

bash
docker compose up -d

This starts:

  • PostgreSQL 18 on port 5496
  • Mailpit with SMTP on 1096 and web UI on 8096, where the sign-in codes arrive

Schema migrations in migrations/ are embedded in the binary and applied automatically on first boot.

FerrisKey is optional. just ferriskey starts one on port 8090 and creates the realm and client the app expects; see Authentication.

4

Install frontend dependencies

bash
bun install
5

Run the development server

bash
just serve

The app will be available at http://localhost:8080. just serve builds Tailwind CSS, then topcoat dev rebuilds, bundles assets and restarts on code changes.

Project Commands

just ferriskey is the one optional extra: it starts FerrisKey from the ferriskey compose profile and runs scripts/ferriskey-bootstrap.sh against it.

Command Description
just serve Start the development server with reload
cargo build --release && topcoat asset bundle --release Production build
bunx @tailwindcss/cli -i tailwind.css -o ./assets/tailwind.css Build Tailwind CSS manually
cargo fmt --all -- --check Check formatting
cargo clippy --workspace --all-targets -- -D warnings Lint
cargo machete Detect unused dependencies

Environment Variables

Core Settings
  • DATABASE_URL — PostgreSQL connection string
  • BASE_URL — Public URL of your application
  • SESSION_SECRET — Hex-encoded session signing key (64+ bytes)
  • SECURE_COOKIES — Set to true in production (HTTPS)
  • COMING_SOON — true replaces the landing page with a coming-soon page and waitlist (see the Waitlist accordion)
Registration & Waitlist
  • OPEN_REGISTRATION — true lets any address sign up; see Authentication for the allowlist alternative
  • CAPTCHA_URL / CAPTCHA_SITE_KEY / CAPTCHA_SECRET_KEY — Bollwark captcha in front of registration and the waitlist form
  • COMING_SOON — while true, / is a coming-soon page whose form writes to the waitlist table (SELECT count(*) FROM waitlist to see how many are waiting); login, docs and the dashboard stay reachable
Authentication
  • AUTH_MODE — local (default: email OTP + passkeys, nothing else to run) or ferriskey
  • TOS_VERSION — terms version users must accept on login; unset disables the step
  • TRUST_PROXY_HEADERS — Set to true when behind a reverse proxy
  • FerrisKey mode only: FERRISKEY_URL (local instance: http://localhost:8090/api), FERRISKEY_ISSUER_URL (optional), FERRISKEY_REALM, FERRISKEY_CLIENT_ID, FERRISKEY_CLIENT_SECRET — just ferriskey produces all of these
Email (SMTP)
  • SMTP_HOST — SMTP server host
  • SMTP_PORT — SMTP port (default: 1025 for Mailpit)
  • SMTP_USER — SMTP username (optional for Mailpit)
  • SMTP_PASSWORD — SMTP password (optional for Mailpit)
  • SMTP_FROM — Sender email address
Billing (Polar)
  • POLAR_ACCESS_TOKEN — Polar API access token
  • POLAR_WEBHOOK_SECRET — Webhook verification secret
Sentry (optional)

Requires building with --features sentry.

  • SENTRY_DSN — Sentry project DSN
  • ENVIRONMENT — environment tag (e.g., development, production)

Changing the database schema

Queries use sqlx's compile-time-checked macros, so column names and types are verified against the schema when you build. The metadata lives in .sqlx/ and is committed, which is what lets a fresh clone build with no database running.

Renaming the project

After cloning, give the project its own name:

bash
just rename my-new-project

This rewrites the package name, Postgres database/user name, tracing filter, Dockerfile binary path, and docs in one shot. Run cargo build afterwards to regenerate Cargo.lock.