Skip to main content

convex

Convex reactive backend expert: schema design, TypeScript functions, real-time subscriptions, auth, file storage, scheduling, and deployment.

معلومات المصدر

المستودع
davila7/claude-code-templates
آخر نشاط في المصدر
٢٤ أكتوبر ٢٠٢٦ في ٠٢:١٩
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٣٢٬٨٩٣
التفرعات
٣٬٧٩٢

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
convex
description
Convex reactive backend expert: schema design, TypeScript functions, real-time subscriptions, auth, file storage, scheduling, and deployment.
metadata
{"risk":"safe","source":"https://docs.convex.dev","date_added":"2026-02-27"}
# Convex You are an expert in Convex — the open-source, reactive backend platform where queries are TypeScript code. You have deep knowledge of schema design, function authoring (queries, mutations, actions), real-time data subscriptions, authentication, file storage, scheduling, and deployment workflows across React, Next.js, Angular, Vue, Svelte, React Native, and server-side environments. ## When to Use - Use when building a new project with Convex as the backend - Use when adding Convex to an existing React, Next.js, Angular, Vue, Svelte, or React Native app - Use when designing schemas for a Convex document-relational database - Use when writing or debugging Convex functions (queries, mutations, actions) - Use when implementing real-time/reactive data patterns - Use when setting up authentication with Convex Auth or third-party providers (Clerk, Auth0, etc.) - Use when working with Convex file storage, scheduled functions, or cron jobs - Use when deploying or managing Convex projects ## Core Concepts Convex is a **document-relational** database with a fully managed backend. Key differentiators: - **Reactive by default**: Queries automatically re-run and push updates to all connected clients when underlying data changes - **TypeScript-first**: All backend logic — queries, mutations, actions, schemas — is written in TypeScript - **ACID transactions**: Serializable isolation with optimistic concurrency control - **No infrastructure to manage**: Serverless, scales automatically, zero config - **End-to-end type safety**: Types flow from schema → backend functions → client hooks ### Function Types | Type | Purpose | Can Read DB | Can Write DB | Can Call External APIs | Cached/Reactive | | :-------------- | :------------------------ | :------------- | :---------------- | :--------------------- | :-------------- | | **Query** | Read data | ✅ | ❌ | ❌ | ✅ | | **Mutation** | Write data | ✅ | ✅ | ❌ | ❌ | | **Action** | Side effects | via `runQuery` | via `runMutation` | ✅ | ❌ | | **HTTP Action** | Webhooks/custom endpoints | via `runQuery` | via `runMutation` | ✅ | ❌ | ## Project Setup ### New Project (Next.js) ```bash npx create-next-app@latest my-app cd my-app && npm install convex npx convex dev ``` ### Add to Existing Project ```bash npm install convex npx convex dev ``` The `npx convex dev` command: 1. Prompts you to log in (GitHub) 2. Creates a project and deployment 3. Generates `convex/` folder for backend functions 4. Syncs functions to your dev deployment in real-time 5. Creates `.env.local` with `CONVEX_DEPLOYMENT` and `NEXT_PUBLIC_CONVEX_URL` ### Folder Structure ``` my-app/ ├── convex/ │ ├── _generated/ ← Auto-generated (DO NOT EDIT) │ │ ├── api.d.ts │ │ ├── dataModel.d.ts │ │ └── server.d.ts │ ├── schema.ts ← Database schema definition │ ├── tasks.ts ← Query/mutation functions │ └── http.ts ← HTTP actions (optional) ├── .env.local ← CONVEX_DEPLOYMENT, NEXT_PUBLIC_CONVEX_URL └── convex.json ← Project config (optional) ``` ## Schema Design Define your schema in `convex/schema.ts` using the validator library: ```typescript import { defineSchema, defineTable } from "convex/server"; import { v } from "convex/values"; export default defineSchema({ users: defineTable({ name: v.string(), email: v.string(), avatarUrl: v.optional(v.string()), tokenIdentifier: v.string(), }) .index("by_token", ["tokenIdentifier"]) .index("by_email", ["email"]), messages: defineTable({ authorId: v.id("users"), channelId: v.id("channels"), body: v.string(), attachmentId: v.optional(v.id("_storage")), }) .index("by_channel", ["channelId"]) .searchIndex("search_body", { searchField: "body" }), channels: defineTable({ name: v.string(), description: v.optional(v.string()), isPrivate: v.boolean(), }), }); ``` ### Validator Types | Validator | TypeScript Type | Notes | | :-------------------------------- | :-------------------- | :--------------------------------------------- | | `v.string()` | `string` | | | `v.number()` | `number` | IEEE 754 float | | `v.bigint()` | `bigint` | | | `v.boolean()` | `boolean` | | | `v.null()` | `null` | | | `v.id("tableName")` | `Id<"tableName">` | Document reference | | `v.array(v.string())` | `string[]` | | | `v.object({...})` | `{...}` | Nested objects | | `v.optional(v.string())` | `string \| undefined` | | | `v.union(v.string(), v.number())` | `string \| number` | | | `v.literal("active")` | `"active"` | Literal types | | `v.bytes()` | `ArrayBuffer` | Binary data | | `v.float64()` | `number` | Explicit 64-bit float (used in vector indexes) | | `v.any()` | `any` | Escape hatch | ### Indexes ```typescript // Single-field index defineTable({ email: v.string() }).index("by_email", ["email"]); // Compound index (order matters for range queries) defineTable({ orgId: v.string(), createdAt: v.number(), }).index("by_org_and_date", ["orgId", "createdAt"]); // Full-text search index defineTable({ body: v.string(), channelId: v.id("channels") }).searchIndex( "search_body", { searchField: "body", filterFields: ["channelId"], }, ); // Vector search index (for AI/embeddings) defineTable({ embedding: v.array(v.float64()), text: v.string() }).vectorIndex( "by_embedding", { vectorField: "embedding", dimensions: 1536, }, ); ``` ## Writing Functions ### Queries (Read Data) Queries are reactive — clients automatically get updates when data changes. ````typescript import { query } from "./_generated/server"; import { v } from "convex/values"; // Simple query — list all tasks export const list = query({ args: {}, handler: async (ctx) => { return await ctx.db.query("tasks").collect(); }, }); // Query with arguments and filtering export const getByChannel = query({ args: { channelId: v.id("channels") }, handler: async (ctx, args) => { return await ctx.db .query("messages") .withIndex("by_channel", (q) => q.eq("channelId", args.channelId)) .order("desc") .take(50); }, }); // Query with auth check export const getMyProfile = query({ args: {}, handler: async (ctx) => { const identity = await ctx.auth.getUserIdentity(); if (!identity) return null; return await ctx.db .query("users") .withIndex("by_token", (q) => q.eq("tokenIdentifier", identity.tokenIdentifier), ) .unique(); }, }); ### Paginated Queries Use cursor-based pagination for lists or infinite scroll UIs. ```typescript import { query } from "./_generated/server"; import { paginationOptsValidator } from "convex/server"; export const listPaginated = query({ args: { paginationOpts: paginationOptsValidator }, handler: async (ctx, args) => { return await ctx.db .query("messages") .order("desc") .paginate(args.paginationOpts); }, }); ``` ### Mutations (Write Data) Mutations run as ACID transactions with serializable isolation. ```typescript import { mutation } from "./_generated/server"; import { v } from "convex/values"; // Insert a document export const create = mutation({ args: { text: v.string(), isCompleted: v.boolean() }, handler: async (ctx, args) => { const taskId = await ctx.db.insert("tasks", { text: args.text, isCompleted: args.isCompleted, }); return taskId; }, }); // Update a document export const update = mutation({ args: { id: v.id("tasks"), isCompleted: v.boolean() }, handler: async (ctx, args) => { await ctx.db.patch(args.id, { isCompleted: args.isCompleted }); }, }); // Delete a document export const remove = mutation({ args: { id: v.id("tasks") }, handler: async (ctx, args) => { await ctx.db.delete(args.id); }, }); // Multi-document transaction (automatically atomic) export const transferCredits = mutation({ args: { fromUserId: v.id("users"), toUserId: v.id("users"), amount: v.number(), }, handler: async (ctx, args) => { const fromUser = await ctx.db.get(args.fromUserId); const toUser = await ctx.db.get(args.toUserId); if (!fromUser || !toUser) throw new Error("User not found"); if (fromUser.credits < args.amount) throw new Error("Insufficient credits"); await ctx.db.patch(args.fromUserId, { credits: fromUser.credits - args.amount, }); await ctx.db.patch(args.toUserId, { credits: toUser.credits + args.amount, }); }, }); ```` ### Actions (External APIs & Side Effects) Actions can call third-party services but cannot directly access the database — they must use `ctx.runQuery` and `ctx.runMutation`. ```typescript import { action } from "./_generated/server"; import { v } from "convex/values"; import { api } from "./_generated/api"; export const sendEmail = action({ args: { to: v.string(), subject: v.string(), body: v.string() }, handler: async (ctx, args) => { // Call external API const response = await fetch("https://api.sendgrid.com/v3/mail/send", { method: "POST", headers: { Authorization: `Bearer ${process.env.SENDGRID_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ personalizations: [{ to: [{ email: args.to }] }], from: { email: "noreply@example.com" }, subject: args.subject, content: [{ type: "text/plain", value: args.body }], }), }); if (!response.ok) throw new Error("Failed to send email"); // Write result back to database via mutation await ctx.runMutation(api.emails.recordSent, { to: args.to, subject: args.subject, sentAt: Date.now(), });
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub