Template
CI reads Infisical staging as the read-only convexmonorepo-base-ci machine identity, runs the quality gate, and builds and pushes the image. The template is not deployed, so there is no Convex or VPS deploy step. The local stack moves to its own Compose name and ports so it runs beside the Payload template's, and it syncs the Convex runtime env. The scripts pick up Infisical account switching, dev-kill and a cache-safe CI install.
4.3 KiB
4.3 KiB
AGENTS.md
Architecture
apps/next: Next.js 16 frontend.apps/expo: Expo scaffold; only work here when explicitly requested.packages/backend/convex: self-hosted Convex functions, schema, and auth.packages/ui: shared shadcn-based UI components.tools: shared ESLint, Prettier, Tailwind, TypeScript, and Vitest config.- Local development uses host-run apps, local Convex on ports 3250/3251, and
its own data volume. Convex does not use Postgres unless a cloned project
explicitly enables the commented optional
POSTGRES_URLexample.
Protected and generated files
- Never edit
packages/backend/convex/_generated/**orpackages/backend/convex/http.ts. - Do not rename
apps/next/next.config.jsorapps/next/src/proxy.ts. - Preserve
typescript.ignoreBuildErrorsin Next config. - Do not modify Sentry config or
tools/tailwind/theme.cssunless requested. - Generated
.cache,.turbo,.local, and environment files are ignored.
Environment rules
- Local
devandstagingcome only from Infisical viascripts/with-env; it never falls back to.env*. - Run
infisical loginandinfisical initbefore local development. - Machine-generated values belong in
.local/<env>.generated.env; never put the generated Convex admin key in shared Infisical. - CI reads
stagingthroughscripts/ci-export-env.mjs, logged in as the read-onlyconvexmonorepo-base-cimachine identity (Gitea secretsINFISICAL_CLIENT_IDandINFISICAL_CLIENT_SECRET).scripts/export-envrefuses to run in CI. - This template's
staginghas no Convex admin key, so nothing here can deploy to a real backend. A cloned app gets its own Infisical project. - If you are logged in to more than one Infisical account, put
INFISICAL_EMAIL=...inscripts/flags/infisical.env(gitignored) and the scripts switch the CLI to that account before exporting. - Server code imports validated variables from
@/env. Client components andinstrumentation-client.tsimport from@/publicEnv, which keeps zod out of the browser bundle. Never readprocess.envelsewhere. - Add cache-relevant variables to
turbo.jsonglobalEnv.
Code and dependency rules
- Use
constarrow functions instead of function declarations. - Add
.jsextensions to Convex generated-file imports. - Put custom frontend routes directly in
apps/next/src/appor normal route groups such asapps/next/src/app/(auth). - Extend the Convex
userstable for application user data; do not add a profile table by default. Authenticate protected functions. - Manage shared versions in root catalogs. Never run
bun updatein a package. - Run root
bun installand verify withbun lint:ws. - Update this guide when architecture or workflows change.
Local stack
bun db:up # start Convex and dashboard
bun dev:next # host Next + deploy/watch local Convex functions
bun db:down # stop and preserve Convex data
bun db:down:wipe # remove Convex volume and generated admin key
bun db:sync-env # re-push Infisical dev values into the local Convex env
bun dev:kill # stop dev servers that survived a Ctrl-C
Local URLs: app http://localhost:3000, Convex http://localhost:3250,
dashboard http://localhost:6795. The Compose project and containers are named
convexmonorepo-base-local* so this stack can run beside the Payload template's.
Use INFISICAL_ENV=staging bun dev:next for staging services. Normal db:up
never connects to staging and does not start Postgres.
Analytics and bundle size
- Plausible (
NEXT_PUBLIC_PLAUSIBLE_SRC, the per-site script URL) loads through a same-origin proxy under/pa. PostHog (NEXT_PUBLIC_POSTHOG_KEY,NEXT_PUBLIC_POSTHOG_HOST) loads after the page is idle through/ingest. Both stay off when their env is unset. - Session replay comes from PostHog. Sentry carries errors and traces only.
packages/ui/src/index.tsxholds re-exports only (cnandccnlive inutils.ts). WithoptimizePackageImportsinnext.config.js, each page loads only the UI modules it imports. Declaring anything in the index breaks that.
Validation
Use bun typecheck, never a production build for routine validation. The full
gate is SKIP_E2E=1 bun run ci:check; local-stack smoke e2e is bun test:e2e.
Pre-commit runs lint-staged serially and pre-push runs the bounded full gate.