A calm, fast, reliable team chat for the web and the phone.
Team chat apps grow into noisy work hubs. Q9 Chat does one job: groups where a team talks, replies that quote, notifications only when something needs you, and nothing a team has to manage. It is built by Q9 Labs on Convex, WorkOS AuthKit, TanStack Start on Cloudflare Workers, and Expo. Read theory.md for what it is and why.
Use Node 24 and pnpm 11. Never commit .env files or credentials.
First-time setup with a local Convex backend and no Convex account:
pnpm install
CONVEX_AGENT_MODE=anonymous pnpm exec convex dev --once
pnpm exec convex env set WORKOS_CLIENT_ID <client id from the WorkOS dashboard>
printf '\nVITE_CONVEX_URL=http://127.0.0.1:3210\n' >> .env.local
pnpm devThe first command starts a local anonymous deployment and writes
CONVEX_DEPLOYMENT into .env.local. Convex refuses to push until
WORKOS_CLIENT_ID is set, because it verifies every access token against that
WorkOS client. Put the server-only WORKOS_API_KEY and WORKOS_CLIENT_ID in
ignored apps/web/.dev.vars. Register /api/auth/callback and
/auth/phone-callback on the local web origin with WorkOS. The web session
contract and route tests are in apps/web/README.md.
The web app runs on the Vite URL printed by pnpm dev. Its health route is
/api/health.
convex/holds the schema and backend functions.convex.jsonand.env.locallive at the repository root.packages/convexexposes the generated Convex API to the apps.apps/webis the TanStack Start web app.
pnpm lint
pnpm format:check
pnpm typecheck
pnpm test
pnpm build
pnpm gatepnpm gate:full runs all configured lanes. Baselines live under
gates/baselines/ and change only through the gate CLI.
See docs/runbooks/deploy.md. Confirm the target environment before every deployment.