Found a bug? Open an issue. Docs out of date? Update them. Hit a rough edge in the dev setup? Smooth it out for the next person.
Take ownership. Make it better. Ship it.
This doc has two halves:
- Part 1 — Day one: get the app running on your machine. Do this once.
- Part 2 — Working here: how we write and ship code, every day.
| Tool | Why | Install |
|---|---|---|
| Bun | Runtime and package manager (1.3.9) | bun.sh |
| Node | v22 or newer — runs CLI tools | nodejs.org |
| Just | Command runner | mac brew install just · win winget install Casey.Just · other |
Important
On Windows, run everything from Git Bash, not PowerShell or cmd. just executes
recipes with sh, which Git for Windows provides. Everything below works identically on
macOS, Linux, and Windows-in-Git-Bash.
git clone https://github.com/GenerateNU/tomoji.git
cd tomoji
just setupjust setup installs dependencies and creates .env.local from the template.
Ask a TL for these two and paste them into .env.local.
WORKOS_API_KEY
WORKOS_CLIENT_ID
Then generate your own cookie password — this one is not shared:
bun -e 'console.log(crypto.randomUUID()+crypto.randomUUID())'Paste it as WORKOS_COOKIE_PASSWORD. It isn't a WorkOS credential; the SDK uses it to
encrypt your local session cookie, so every developer should have a different one. It must
be at least 32 characters.
Leave the rest of the file alone — the Convex values fill themselves in next.
just bdThe very first time, this opens your browser to sign in to Convex — create a free account there if you don't have one, then come back to the terminal.
It then creates a Convex dev deployment that is yours alone and writes
CONVEX_DEPLOYMENT and NEXT_PUBLIC_CONVEX_URL into your .env.local.
It will then fail with WORKOS_CLIENT_ID is not set on this Convex deployment. That's
expected — step 4 fixes it.
Note
There is no localhost URL for the backend. Convex runs your convex/ code in the cloud;
just bd is a file watcher that pushes changes up and streams logs back. Use
just dashboard to browse data and read logs.
just convex-envconvex/auth.config.ts reads WORKOS_CLIENT_ID from the Convex deployment, not from
.env.local. This copies it across. Restart just bd — it should now print
Convex functions ready!.
Two terminals:
just bd # leave running — Convex logs appear herejust fd # http://localhost:3000- Open http://localhost:3000 and click Sign in. You should land on a real WorkOS page.
- After signing in, your email should appear in the header.
just test— 5 tests should pass.just ci— should exit clean.
If all four work, you're set up.
WORKOS_CLIENT_ID is not set on this Convex deployment — you skipped step 4. Run
just convex-env.
Signed in, but the app can't read your identity — the token's iss doesn't match
convex/auth.config.ts. Paste the access token into jwt.io and compare
iss against https://api.workos.com/user_management/<WORKOS_CLIENT_ID>. Convex fails this
check silently, returning null rather than raising.
Module has no exported member from convex/_generated — generated types are stale.
Make sure just bd is running.
"invalid redirect URI" — NEXT_PUBLIC_WORKOS_REDIRECT_URI must match a Redirect URI in
the WorkOS dashboard character for character, including the port.
CI passes locally but fails on GitHub — usually a stale bun.lock, since CI installs
with --frozen-lockfile. Run bun install and commit the lockfile.
feat: add creator application form
fix: correct org scoping on campaign list
docs: document convex env workflow
chore: upgrade convex to 1.46
test: cover requireIdentity deny case
Branch from main, open a PR, get one approval, squash merge. CI must pass before merge —
it runs bun run ci on every PR, the same script just ci wraps. See
.github/workflows/ci.yml.
Important
Keep PRs small and focused. If a ticket looks like more than one to two weeks of work, the scope or the requirements probably need another conversation first.
just on its own lists all available commands. The five you'll use daily:
just fd # frontend — localhost:3000
just bd # Convex — watches convex/, streams logs
just ci # typecheck + lint + format + test. Run before you push.
just test # tests once
just format # format everything in place