Imported from sapo-foundation/sapo (
AGENTS.md). Install upstream withnpx skills add sapo-foundation/sapo. Copyright stays with the author.
AGENTS.md
Compact guidance for future OpenCode sessions in this repo.
Project Shape
- Expo + React Native + TypeScript app using Expo Router (
package.jsonmainisexpo-router/entry). Keepapp/limited to routes and layouts; feature screens and reusable UI live incomponents/. app/_layout.tsxwires the global providers: Convex, Better Auth, auth gating, RevenueCat identity sync, and keyboard handling.- App state is in Zustand stores under
stores/; reusable React behavior is inhooks/; app-wide lifecycle components are inproviders/; external and native integrations are inlib/. convex/is both backend code and a configured git submodule (.gitmodules); edits there are in the nested repo and root git status only shows the submodule pointer. If it is missing after clone, rungit submodule update --init --recursive.- Convex is componentized: root
convex/convex.config.tsusesbetterAuth,operations,subscriptions, and@convex-dev/resendcomponents.
Commands
- Use npm scripts from repo root. The repo has
bun.lockbut nopackage-lock.json; avoid introducing a new lockfile unless requested. - Install:
npm install - Start Expo:
npm run start - Native runs:
npm run ios,npm run android - Web:
npm run web - Lint default Expo paths:
npm run lint - Lint non-default dirs when touched:
npm run lint -- convex stores hooks lib providers utils constants types - Run all tests once:
npm exec jest -- --watchAll=false - Run one test file:
npm exec jest -- convex/__tests__/sapopinguinoInput.test.ts --watchAll=false - Type-check:
npm exec tsc -- --noEmit(there is notypecheckscript). - Convex dev/codegen:
npm run convex:dev(regenerates Markdown AI prompt bundle first). - Convex deploy:
npm run convex:deploy. - AI prompt edits: edit
convex/prompts/*.md, runnpm run prompts:generate, and commit the generated bundle with the Markdown.npm run prompts:checkverifies freshness.
Verification Notes
npm testruns Jest in watch mode (jest --watchAll); do not use it for one-shot verification.- Jest uses the
jest-expopreset frompackage.json. Tests live beside their modules in__tests__/directories. expo lintonly targets Expo’s default directories unless paths are supplied; include backend, store, hook, provider, and integration directories explicitly when touched.
Generated And Integration Files
- Do not hand-edit Convex generated output:
convex/_generated/,convex/betterAuth/_generated/,convex/operations/_generated/, orconvex/subscriptions/_generated/. Regenerate withnpm exec convex dev. - Do not hand-edit
expo-env.d.ts; Expo owns it. - SVGs are imported as React components;
metro.config.jsremovessvgfrom asset extensions and usesreact-native-svg-transformer/expo.
Environment Gotchas
- Client startup requires
EXPO_PUBLIC_CONVEX_URL; auth, SSE, and subscription reconciliation calls useEXPO_PUBLIC_CONVEX_SITE_URL. - RevenueCat client config is optional but platform-specific:
EXPO_PUBLIC_REVENUE_CAT_APPLE_API_KEY,EXPO_PUBLIC_REVENUE_CAT_GOOGLE_API_KEY, product IDs, and entitlement ID. - Convex server env is separate from Expo public env; backend code reads Cloudflare AI, Better Auth, Apple/Google auth, RevenueCat webhook/API, Resend, and
CLIENT_ORIGINvalues. Cloudflare setup and required variables are documented inconvex/prompts/README.md. - Never expose server-only env values by adding an
EXPO_PUBLIC_prefix.