- For public listing/browse pages, use
ConvexHttpClient.query()(one-shot fetch), notuseQuery/usePaginatedQuery(reactive subscription). Reserve reactive queries for data the user needs to see update in real time. - Denormalize hot read paths into a single lightweight "digest" table. Every
ctx.db.get()join adds a table to the reactive invalidation scope. - When a
skillSearchDigestrow is available, usedigestToOwnerInfo(digest)to resolve owner data. NEVER callctx.db.get(ownerUserId)when digest owner fields (ownerHandle,ownerName,ownerDisplayName,ownerImage) are already present. Reading fromusersadds the entire table to the reactive read set and wastes bandwidth. - Use
convex-helpersTriggers to sync denormalized tables automatically. Always add change detection — skip the write if no fields actually changed. - Use compound indexes instead of JS filtering. If you're filtering docs after the query, you're scanning documents you'll throw away.
- For search results scored by computed values (vector + lexical + popularity), fetch all results once and paginate client-side. Don't re-run the full search pipeline on "load more."
- Backfills on reactively-subscribed tables need
delayMsbetween batches. - Mutations that read >8 MB should use the Action → Query → Mutation pattern to split reads across transactions.
- All mutations import from
convex/functions.ts(notconvex/_generated/server) to get trigger wrapping. Type imports still come fromconvex/_generated/server. - NEVER use
--typecheck=disableonnpx convex deploy. - Use
npx convex dev --onceto push functions once (not long-running watcher).
- Production deploys are manual-only. Merging to
maindoes not deploy. - Start the GitHub Actions
Deployworkflow frommainwithgh workflow run deploy.yml --repo openclaw/clawhub --ref main. - The workflow supports
full,backend, andfrontendtargets. frontendcurrently waits for the Vercel production deploy on the selectedmainSHA and then runs smoke checks. It does not trigger Vercel directly yet.- The workflow uses the
Productionenvironment for deploy secrets, but it does not wait for a separate approval. - Required prod secret:
CONVEX_DEPLOY_KEYon theProductionenvironment. Optional smoke secret:PLAYWRIGHT_AUTH_STORAGE_STATE_JSON. - CLI npm releases are manual-only and tag-based through
ClawHub CLI NPM Release. Stable tags only:vX.Y.Z. Run apreflight_only=truepass first, then rerun with the same tag pluspreflight_run_idfor the real publish. - Real CLI publishes wait at
npm-releaseand rely on npm trusted publishing foropenclaw/clawhub+clawhub-cli-npm-release.yml+npm-release.
- Tests use
._handlerto call mutation handlers directly with mockdbobjects. - Mock
dbobjects MUST includenormalizeId: vi.fn()for trigger wrapper compatibility.
This project uses Convex as its backend.
When working on Convex code, always read convex/_generated/ai/guidelines.md first for important guidelines on how to correctly use Convex APIs and patterns. The file contains rules that override what you may have learned about Convex from training data.
Convex agent skills for common tasks can be installed by running npx convex ai-files install.