Convex backend development guidelines. Use when writing Convex functions, schemas, queries, mutations, actions, or any backend code in a Convex project. Triggers on tasks involving Convex database operations, real-time subscriptions, file storage, or serverless functions.
Comprehensive guide for building Convex backends with TypeScript. Covers function syntax, validators, schemas, queries, mutations, actions, scheduling, and file storage.
Reference these guidelines when:
| Category | Impact | Description | | ----------------- | -------- | --------------------------------------------- | | Function Syntax | CRITICAL | New function syntax with args/returns/handler | | Validators | CRITICAL | Type-safe argument and return validation | | Schema Design | HIGH | Table definitions, indexes, system fields | | Query Patterns | HIGH | Efficient data fetching with indexes | | Mutation Patterns | MEDIUM | Database writes, patch vs replace | | Action Patterns | MEDIUM | External API calls, Node.js runtime | | Scheduling | MEDIUM | Crons and delayed function execution | | File Storage | LOW | Blob storage and metadata |
// Public functions (exposed to clients)
import { query, mutation, action } from "./_generated/server";
// Internal functions (only callable from other Convex functions)
import {
internalQuery,
internalMutation,
internalAction,
} from "./_generated/server";
export const myFunction = query({
args: { name: v.string() },
returns: v.string(),
handler: async (ctx, args) => {
return "Hello " + args.name;
},
});
| Type | Validator | Example |
| -------- | --------------------------------- | ------------- |
| String | v.string() | "hello" |
| Number | v.number() | 3.14 |
| Boolean | v.boolean() | true |
| ID | v.id("tableName") | doc._id |
| Array | v.array(v.string()) | ["a", "b"] |
| Object | v.object({...}) | {name: "x"} |
| Optional | v.optional(v.string()) | undefined |
| Union | v.union(v.string(), v.number()) | "x" or 1 |
| Literal | v.literal("status") | "status" |
| Null | v.null() | null |
// Public functions
import { api } from "./_generated/api";
api.example.myQuery; // convex/example.ts → myQuery
// Internal functions
import { internal } from "./_generated/api";
internal.example.myInternalMutation;
// Schema
messages: defineTable({...}).index("by_channel", ["channelId"])
// Query
await ctx.db
.query("messages")
.withIndex("by_channel", (q) => q.eq("channelId", channelId))
.order("desc")
.take(10);
args and returns validators on all functionsv.null() for void returns - never omit return validatorwithIndex() not filter() - define indexes in schemainternalQuery/Mutation/Action for private functionsctx.db - use runQuery/runMutation insteadFor the complete guide with all rules and detailed code examples, see AGENTS.md.
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer