.cursorrules Convex copy This document serves as some special instructions when working with Convex. # Schemas When designing the schema please see this page on built in System fields and data types available: https://docs.convex.dev/database/types Here are some specifics that are often mishandled: ## v (https://docs.convex.dev/api/modules/values#v) The validator builder. This builder allows you to build validators for Convex values. Validators can be used in schema definitions and as input validators for Convex functions. Type declaration Name Type id (tableName: TableName) => VId<GenericId, "required"> null () => VNull number () => VFloat64 float64 () => VFloat64 bigint () => VInt64 int64 () => VInt64 boolean () => VBoolean string () => VString bytes () => VBytes literal (literal: T) => VLiteral array (element: T) => VArray object (fields: T) => VObject<Expand<{ [Property in string | number | symbol]?: Exclude<Infer, undefined> } & { [Property in string | number | symbol]: Infer }>, T, "required", { [Property in string | number | symbol]: Property | `${Property & string}.${T[Property]["fieldPaths"]}` }[keyof T] & string> record (keys: Key, values: Value) => VRecord<Record<Infer, Value["type"]>, Key, Value, "required", string> union (...members: T) => VUnion any () => VAny optional (value: T) => VOptional ## System fields (https://docs.convex.dev/database/types#system-fields) Every document in Convex has two automatically-generated system fields: _id: The document ID of the document. _creationTime: The time this document was created, in milliseconds since the Unix epoch. You do not need to add indices as these are added automatically. ## Example Schema This is an example of a well crafted schema. ```ts import { defineSchema, defineTable } from "convex/server"; import { v } from "convex/values"; export default defineSchema( { users: defineTable({ name: v.string(), }), sessions: defineTable({ userId: v.id("users"), sessionId: v.string(), }).index("sessionId", ["sessionId"]), threads: defineTable({ uuid: v.string(), summary: v.optional(v.string()), summarizer: v.optional(v.id("_scheduled_functions")), }).index("uuid", ["uuid"]), messages: defineTable({ message: v.string(), threadId: v.id("threads"), author: v.union( v.object({ role: v.literal("system"), }), v.object({ role: v.literal("assistant"), context: v.array(v.id("messages")), model: v.optional(v.string()), }), v.object({ role: v.literal("user"), userId: v.id("users"), }), ), }) .index("threadId", ["threadId"]), }, ); Cursor AI by @PatrickJS