Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/convex-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Deploy Convex backend
# The recurring outage (M6.2, M7, and the FunctionPathNotFound storm) all came
# from the same gap: backend code was merged but never deployed, so the client
# called functions the deployment didn't have. This couples a backend deploy to
# every merge into main, so code and deployment can never drift again.
#
# Setup (one-time): create a PROD deploy key at
# dashboard.convex.dev → khata → prod (formal-dove-357) → Settings → Deploy Keys
# and add it as the repo secret CONVEX_DEPLOY_KEY
# (Settings → Secrets and variables → Actions → New repository secret).
on:
push:
branches:
- main
paths:
- "convex/**"
- ".github/workflows/convex-deploy.yml"
jobs:
deploy:
name: convex deploy (prod)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Deploy functions to the prod deployment
env:
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
run: bunx convex deploy -y
14 changes: 14 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@
- `better-auth` session storage uses the browser's default cookie/localStorage — no SecureStore or in-memory hydration needed on web.
- Tailwind CSS v4 — use `@import "tailwindcss"` in CSS, no `tailwind.config.js`. Theme tokens live in `src/index.css` as CSS custom properties.

## Convex deployments (dev vs prod) — read this before touching the backend

There are **two** Convex backends:

- **dev** — `tangible-finch-68` (`.env.local` → `CONVEX_DEPLOYMENT=dev:tangible-finch-68`). Used by local `bun run dev`. Deploy to it with `bunx convex dev --once`.
- **prod** — `formal-dove-357`. Used by the released app. The APK build pins it (`build-apk.yml` sets `VITE_CONVEX_URL`). The web app should also point here in production via `VITE_CONVEX_URL`.

**Code in `convex/` does not run until it is deployed to a deployment.** The frontend's `_generated/api` reflects local code; if the client calls a function the *deployment* hasn't received, the WebSocket drops with `FunctionPathNotFound` and every live query stalls through reconnect backoff. This has bitten the project repeatedly (M6.2, M7, the June 2026 outage where M11 functions were merged but never deployed, so the website — silently on dev — broke).

**Rules:**
- A merge to `main` auto-deploys the backend to **prod** via `.github/workflows/convex-deploy.yml` (needs repo secret `CONVEX_DEPLOY_KEY`). Don't rely on remembering to deploy by hand.
- The production web build **must** set `VITE_CONVEX_URL` to the prod URL. `deployment.ts` falls back to dev only as a last resort and logs a loud error in prod builds if it has to.
- After changing `convex/` and testing on dev, the durable path is to merge → auto-deploy. For a hotfix you can `bunx convex deploy` (prod) manually, but that's the exception.

## Release and versioning

- Release automation is managed by `release-please` via `.github/workflows/release-please.yml`.
Expand Down
24 changes: 22 additions & 2 deletions apps/web/src/lib/deployment.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
// Which Convex backend this build talks to.
//
// IMPORTANT: a *production* build must set VITE_CONVEX_URL to the production
// deployment. If it doesn't, we fall back to the DEV deployment below — which is
// how the live website silently ended up talking to the dev backend (and hit
// FunctionPathNotFound when dev was behind on deploys). So in a prod build with
// no explicit URL we now scream in the console instead of failing silently.
//
// Local dev (`bun run dev`) reads VITE_CONVEX_URL from apps/web/.env.local, or
// falls back to dev here — which is correct for local work.
const DEV_URL = "https://tangible-finch-68.convex.cloud";
const DEV_SITE_URL = "https://tangible-finch-68.convex.site";

export const CONVEX_URL =
(import.meta.env.VITE_CONVEX_URL as string | undefined) ?? DEV_URL;
const explicitUrl = import.meta.env.VITE_CONVEX_URL as string | undefined;

if (import.meta.env.PROD && !explicitUrl) {
// eslint-disable-next-line no-console
console.error(
"[khata] VITE_CONVEX_URL is not set in this PRODUCTION build — falling back " +
"to the DEV Convex deployment. Set VITE_CONVEX_URL to the prod deployment " +
"(formal-dove-357) in the hosting environment so the live app uses prod."
);
}

export const CONVEX_URL = explicitUrl ?? DEV_URL;

export const CONVEX_SITE_URL =
(import.meta.env.VITE_CONVEX_SITE_URL as string | undefined) ??
Expand Down
Loading