SKILL.md
Convex conventions
These are house-style defaults, not a Convex manual. Use current official Convex skills for scaffolding, auth, migrations, performance work, components, and API mechanics; this skill adds project policy. Apply only what the requested change touches.
Authority
Verify each touched API against live Convex docs and the installed version. Read release notes before a major or minor upgrade. Live docs win over this skill; memory and prior turns do not establish current API behavior.
Layout and shared shapes
- Keep
convex/at root and never edit_generated/. schema.tsownsdefineSchemaand table declarations.auth.config.tsowns the Clerk JWT provider.- Keep one module each for reusable table validators, semantic validation, auth
helpers, and rate-limit configuration.
- Add
crons.tsandhttp.tsonly when used. - Public feature surfaces and their tests are co-located.
- Define table validators once and compose them into schema,
args, and
returns; do not redeclare an existing shape inline.
Auth and public functions
- Clerk is the identity provider. Server code derives identity from
ctx.auth.getUserIdentity() through one helper; clients never submit userId.
- Every public function authenticates at the top and declares both
argsand
returns validators.
- Use internal functions for scheduling, sensitive side effects, and
cross-function reuse that must not be public.
- Keep structural validation in validators and semantic checks such as date
correctness, length caps, and sanitization in the handler.
Reads, writes, and effects
- Indexes narrow candidates; further filtering happens in code. Give indexes
semantic names and avoid redundant ones.
- Cap every otherwise unbounded query with
.take(); comment only when the cap
is load-bearing.
- Queries are pure and deterministic: no
Date.now()inside them. - Mutations write. Actions call external systems. An action persists through an
internal mutation rather than mixing the roles.
- Rate-limit every public mutation with the current
@convex-dev/rate-limiter API. Token bucket suits high-frequency operations; fixed window suits low-frequency operations.
Stored data
- User-created rows use soft deletion with optional numeric
deletedAt; public
mutations do not hard-delete them.
- Audit trails are append-only records.
- Server metadata such as identity and timestamps comes from handler context,
never client args.
- Data-at-rest schema changes use widen, migrate, then narrow through the
official migration workflow.
- Aggregate additions include a backfill. Aggregate synchronization failure
must not block the primary write.
Client types and components
- Derive client types from generated
Doc<...>andId<...>. - One dedicated module re-exports semantic client aliases; app code imports
there, never directly from convex/_generated, and never manually copies table shapes.
- Prefer official Convex components for existing capabilities and verify each
component README. Use the official component workflow when authoring a new reusable component.
Completion
- Codegen and typecheck pass.
- Relevant function tests and the project gate pass.
- Any schema migration ran against the development deployment and its result is
recorded.
- No public function lacks auth,
args, orreturns; no public mutation lacks
rate limiting; no unbounded query lacks a cap.