Home › Convex › Convex backend rules

Convex backend rules

Cursor rules for Convex backends: schema, validated queries/mutations/actions, indexes, and auth checks.

CursorConvex

How to use

Save this as .cursor/rules/convex.mdc in your repository root, commit it, and your agent will pick it up automatically. Edit the commands to match your project.

.cursor/rules/convex.mdcDownload  
---
description: Convex backend conventions
globs: ["convex/**/*.ts","src/**/*.{ts,tsx}"]
alwaysApply: false
---

# Convex

- Schema in `convex/schema.ts` with `defineSchema`/`defineTable` and `v` validators. Add `.index("by_user", ["userId"])` for every field you filter on.
- Every function declares `args` (and ideally `returns`) validators: `export const list = query({ args: { channelId: v.id("channels") }, handler: async (ctx, args) => {...} })`.
- `query` for reads (reactive, deterministic), `mutation` for transactional writes, `action` for third-party APIs and side effects. Actions call DB via `ctx.runQuery`/`ctx.runMutation`, not `ctx.db`.
- Use `internalQuery`/`internalMutation`/`internalAction` for anything not called from the client; schedule follow-ups with `ctx.scheduler.runAfter`.
- Query with indexes: `ctx.db.query("messages").withIndex("by_channel", q => q.eq("channelId", id))`. Avoid `.filter()` on large tables, and use `.take(n)` or `.paginate()` instead of unbounded `.collect()`.
- Auth in every public function: `const identity = await ctx.auth.getUserIdentity(); if (!identity) throw new ConvexError("Unauthenticated");` then check ownership.
- Throw `ConvexError` with structured data for expected errors.
- Client: `useQuery(api.messages.list, { channelId })`, `useMutation(api.messages.send)`; pass `"skip"` to defer a query.
- Env vars set with `npx convex env set`, read via `process.env` in functions only.

## Done when
`npx convex dev --once` deploys to the dev deployment with no type errors, and `npx tsc --noEmit` passes.

More: all Convex rules · all Cursor rules

Related rules

Drizzle ORM rules

Cursor rules for Drizzle ORM with Postgres or SQLite: schema files, drizzle-kit migrations, and type-safe queries.

CursorDrizzle ORM

Firebase (modular SDK) rules

Cursor rules for Firebase web apps with the modular v11+ SDK, Firestore security rules, and emulator tests.

CursorFirebase

Mongoose (MongoDB ODM) rules

Cursor rules for Mongoose 8 with TypeScript: typed schemas, indexes, lean queries, validation, and transactions.

CursorMongoDB

Prisma ORM rules

Cursor rules for Prisma ORM 6 with PostgreSQL: schema changes, migrations, typed queries, and transactions.

CursorPrisma

Supabase backend rules

Cursor rules for apps on Supabase: Row Level Security first, migrations, typed clients and Edge Functions.

CursorSupabase

MongoDB Windsurf rules

Windsurf rules for MongoDB 8 apps with the Node.js driver: schema design, indexes, aggregation, and transactions.

WindsurfMongoDB

Get new rules weekly

One email a week: fresh rule files, agent tips, and what's changing in Cursor, Claude Code and Copilot. Free, unsubscribe anytime.

Opens the Rulestack Newsletter on beehiiv in a new tab. Or subscribe directly on beehiiv.