Agent skill

Convex

by davila7 in davila7/claude-code-templates

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

MITAuto-check: notesDatabases

Install Convex

skills CLI
$ npx skills add davila7/claude-code-templates --skill convex -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install davila7/claude-code-templates convex --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/davila7/claude-code-templates.git skills-src && mkdir -p .claude/skills && cp -r skills-src/cli-tool/components/skills/development/convex .claude/skills/convex && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
convex
GitHub stars
32k
Used in
3 other repos
Token cost
~6.4k tokens
SKILL.md length
1,096 words
Files
1
Skills in repo
478
Repo updated
First seen
Licence
MIT

At a glance

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

  • Works in 5 steps: Prompts you to log in (GitHub) → Creates a project and deployment → Generates convex/ folder for backend… → …
  • Tasks that involve Database schema design
  • SKILL.md covers When to Use, Core Concepts, Project Setup and Schema Design, plus 9 more sections
  • Calls npx and npm; reaches api.sendgrid.com and api.openai.com; needs OPENAI_API_KEY and SENDGRID_API_KEY

What it does

Convex is an agent skill from davila7/claude-code-templates. Convex reactive backend expert: schema design, TypeScript functions, real-time subscriptions, auth, file storage, scheduling, and deployment.

Its SKILL.md is about 6.4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Databases, covering Database schema design and File uploads and storage. It works with TypeScript and Next.js. The repository describes itself as: CLI tool for configuring and monitoring Claude Code. The licence is MIT.

When your agent uses it

  • Tasks that involve Database schema design
  • Tasks that involve File uploads and storage

Example prompts

  • “/convex”

Requirements

  • Node.js
  • A credential in SENDGRID_API_KEY
  • A credential in OPENAI_API_KEY

Workflow steps

5 steps, taken from the first numbered list in SKILL.md.

  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

What it can do on your machine

Read from SKILL.md and the folder at commit 46b4d8b. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • npx
    • npm

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • api.sendgrid.com
    • api.openai.com

    Also links to:

    • docs.convex.dev
    • stack.convex.dev
    • github.com
    • convex.dev
    • chef.convex.dev

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • OPENAI_API_KEY
    • SENDGRID_API_KEY
    • NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
    • BETTER_AUTH_SECRET

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Convex loads about 6.4k tokens when it runs. Until then it costs about 37 tokens; SKILL.md has 1,096 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~37
When it runs · the whole SKILL.md, loaded when a task matches
~6.4k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NoteMentions a .env fileSKILL.md:65
    5. Creates `.env.local` with `CONVEX_DEPLOYMENT` and `NEXT_PUBLIC_CONVEX_URL`
  • NoteMentions a .env fileSKILL.md:79
    ├── .env.local             ← CONVEX_DEPLOYMENT, NEXT_PUBLIC_CONVEX_URL

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from davila7/claude-code-templates at commit 46b4d8b, republished under its MIT licence (© davila7). 1,096 words, ~6,377 tokens.

Download SKILL.mdSave it as .claude/skills/convex/SKILL.md (or your agent's skills folder).
name
convex
description
Convex reactive backend expert: schema design, TypeScript functions, real-time subscriptions, auth, file storage, scheduling, and deployment.
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
TypePurposeCan Read DBCan Write DBCan Call External APIsCached/Reactive
QueryRead data✅❌❌✅
MutationWrite data✅✅❌❌
ActionSide effectsvia runQueryvia runMutation✅❌
HTTP ActionWebhooks/custom endpointsvia runQueryvia 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
ValidatorTypeScript TypeNotes
v.string()string
v.number()numberIEEE 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()ArrayBufferBinary data
v.float64()numberExplicit 64-bit float (used in vector indexes)
v.any()anyEscape 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(),
    });
  },
});

// Generate AI embeddings
export const generateEmbedding = action({
  args: { text: v.string(), documentId: v.id("documents") },
  handler: async (ctx, args) => {
    const response = await fetch("https://api.openai.com/v1/embeddings", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        model: "text-embedding-3-small",
        input: args.text,
      }),
    });

    const { data } = await response.json();
    await ctx.runMutation(api.documents.saveEmbedding, {
      documentId: args.documentId,
      embedding: data[0].embedding,
    });
  },
});
HTTP Actions (Webhooks)
typescript
import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";
import { api } from "./_generated/api";

const http = httpRouter();

http.route({
  path: "/webhooks/stripe",
  method: "POST",
  handler: httpAction(async (ctx, request) => {
    const body = await request.text();
    const signature = request.headers.get("stripe-signature");

    // Verify webhook signature here...

    const event = JSON.parse(body);
    await ctx.runMutation(api.payments.handleWebhook, { event });

    return new Response("OK", { status: 200 });
  }),
});

export default http;

Client-Side Integration

React / Next.js
typescript
// app/ConvexClientProvider.tsx
"use client";
import { ConvexProvider, ConvexReactClient } from "convex/react";
import { ReactNode } from "react";

const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);

export function ConvexClientProvider({ children }: { children: ReactNode }) {
  return <ConvexProvider client={convex}>{children}</ConvexProvider>;
}
typescript
// app/layout.tsx — wrap children
import { ConvexClientProvider } from "./ConvexClientProvider";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <ConvexClientProvider>{children}</ConvexClientProvider>
      </body>
    </html>
  );
}
typescript
// Component using Convex hooks
"use client";
import { useQuery, useMutation } from "convex/react";
import { api } from "@/convex/_generated/api";

export function TaskList() {
  // Reactive query — auto-updates when data changes
  const tasks = useQuery(api.tasks.list);
  const addTask = useMutation(api.tasks.create);
  const toggleTask = useMutation(api.tasks.update);

  if (tasks === undefined) return <p>Loading...</p>;

  return (
    <div>
      {tasks.map((task) => (
        <div key={task._id}>
          <input
            type="checkbox"
            checked={task.isCompleted}
            onChange={() =>
              toggleTask({ id: task._id, isCompleted: !task.isCompleted })
            }
          />
          {task.text}
        </div>
      ))}
      <button onClick={() => addTask({ text: "New task", isCompleted: false })}>
        Add Task
      </button>
    </div>
  );
}
typescript
// Component using Paginated Queries
"use client";
import { usePaginatedQuery } from "convex/react";
import { api } from "@/convex/_generated/api";

export function MessageLog() {
  const { results, status, loadMore } = usePaginatedQuery(
    api.messages.listPaginated,
    {}, // args
    { initialNumItems: 20 }
  );

  return (
    <div>
      {results.map((msg) => (
        <div key={msg._id}>{msg.body}</div>
      ))}

      {status === "LoadingFirstPage" && <p>Loading...</p>}

      {status === "CanLoadMore" && (
        <button onClick={() => loadMore(20)}>Load More</button>
      )}
    </div>
  );
}
With Auth (First-Party Convex Auth)

Convex provides a robust, native authentication library (@convex-dev/auth) featuring Magic Links, Passwords, and 80+ OAuth providers without needing a third-party service.

typescript
// app/ConvexClientProvider.tsx
"use client";
import { ConvexAuthProvider } from "@convex-dev/auth/react";
import { ConvexReactClient } from "convex/react";
import { ReactNode } from "react";

const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);

export function ConvexClientProvider({ children }: { children: ReactNode }) {
  return (
    <ConvexAuthProvider client={convex}>
      {children}
    </ConvexAuthProvider>
  );
}
typescript
// Client-side sign in
import { useAuthActions } from "@convex-dev/auth/react";

export function Login() {
  const { signIn } = useAuthActions();
  return <button onClick={() => signIn("github")}>Sign in with GitHub</button>;
}
With Auth (Third-Party Clerk Example)

If you prefer a hosted third-party solution like Clerk:

typescript
// app/ConvexClientProvider.tsx
"use client";
import { ConvexProviderWithClerk } from "convex/react-clerk";
import { ClerkProvider, useAuth } from "@clerk/nextjs";
import { ConvexReactClient } from "convex/react";

const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);

export function ConvexClientProvider({ children }: { children: ReactNode }) {
  return (
    <ClerkProvider publishableKey={process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY!}>
      <ConvexProviderWithClerk client={convex} useAuth={useAuth}>
        {children}
      </ConvexProviderWithClerk>
    </ClerkProvider>
  );
}
With Auth (Better Auth Component)

Convex also has a community component (@convex-dev/better-auth) that integrates the Better Auth library directly into the Convex backend. This is currently in early alpha.

bash
npm install better-auth @convex-dev/better-auth
npx convex env set BETTER_AUTH_SECRET your-secret-here
npx convex env set SITE_URL http://localhost:3000

Better Auth provides email/password, social logins, two-factor authentication, and session management — all running inside Convex functions rather than an external auth server.

Angular Integration

Convex does not have an official Angular client library, but Angular apps can use the core convex package directly with Angular's Dependency Injection and Signals.

typescript
// services/convex.service.ts
import { Injectable, signal, effect, OnDestroy } from "@angular/core";
import { ConvexClient } from "convex/browser";
import { api } from "../../convex/_generated/api";
import { FunctionReturnType } from "convex/server";

@Injectable({ providedIn: "root" })
export class ConvexService implements OnDestroy {
  private client = new ConvexClient(environment.convexUrl);

  // Reactive signal — updates automatically when data changes
  tasks = signal<FunctionReturnType<typeof api.tasks.list> | undefined>(
    undefined,
  );

  constructor() {
    // Subscribe to a reactive query
    this.client.onUpdate(api.tasks.list, {}, (result) => {
      this.tasks.set(result);
    });
  }

  async addTask(text: string) {
    await this.client.mutation(api.tasks.create, {
      text,
      isCompleted: false,
    });
  }

  ngOnDestroy() {
    this.client.close();
  }
}
typescript
// Component usage
import { Component, inject } from "@angular/core";
import { ConvexService } from "./services/convex.service";

@Component({
  selector: "app-task-list",
  template: `
    @if (convex.tasks(); as tasks) {
      @for (task of tasks; track task._id) {
        <div>{{ task.text }}</div>
      }
    } @else {
      <p>Loading...</p>
    }
    <button (click)="convex.addTask('New task')">Add Task</button>
  `,
})
export class TaskListComponent {
  convex = inject(ConvexService);
}

Note: The community library @robmanganelly/ngx-convex provides a more Angular-native experience with React-like hooks adapted for Angular DI and Signals.

Scheduling & Cron Jobs

One-off Scheduled Functions
typescript
import { mutation } from "./_generated/server";
import { api } from "./_generated/api";

export const sendReminder = mutation({
  args: { userId: v.id("users"), message: v.string(), delayMs: v.number() },
  handler: async (ctx, args) => {
    await ctx.scheduler.runAfter(args.delayMs, api.notifications.send, {
      userId: args.userId,
      message: args.message,
    });
  },
});
Cron Jobs
typescript
// convex/crons.ts
import { cronJobs } from "convex/server";
import { api } from "./_generated/api";

const crons = cronJobs();

crons.interval("clear old logs", { hours: 24 }, api.logs.clearOld);

crons.cron(
  "weekly digest",
  "0 9 * * 1", // Every Monday at 9 AM
  api.emails.sendWeeklyDigest,
);

export default crons;

File Storage

typescript
// Generate an upload URL (mutation)
export const generateUploadUrl = mutation({
  args: {},
  handler: async (ctx) => {
    return await ctx.storage.generateUploadUrl();
  },
});

// Save file reference after upload (mutation)
export const saveFile = mutation({
  args: { storageId: v.id("_storage"), name: v.string() },
  handler: async (ctx, args) => {
    await ctx.db.insert("files", {
      storageId: args.storageId,
      name: args.name,
    });
  },
});

// Get a URL to serve a file (query)
export const getFileUrl = query({
  args: { storageId: v.id("_storage") },
  handler: async (ctx, args) => {
    return await ctx.storage.getUrl(args.storageId);
  },
});

Environment Variables

bash
# Set environment variables for your deployment
npx convex env set OPENAI_API_KEY sk-...
npx convex env set SENDGRID_API_KEY SG...

# List current env vars
npx convex env list

# Remove an env var
npx convex env unset OPENAI_API_KEY

Access in actions (NOT in queries or mutations):

typescript
// Only available in actions
const apiKey = process.env.OPENAI_API_KEY;

Deployment & CLI

bash
# Development (watches for changes, syncs to dev deployment)
npx convex dev

# Deploy to production
npx convex deploy

# Import data
npx convex import --table tasks data.jsonl

# Export data
npx convex export --path ./backup

# Open Convex dashboard
npx convex dashboard

# Run a function from CLI
npx convex run tasks:list

# View logs
npx convex logs

Best Practices

  • ✅ Define schemas — adds type safety across your entire stack
  • ✅ Use indexes for queries — avoids full table scans
  • ✅ Use compound indexes with equality filters first, range filter last
  • ✅ Rely on native determinism — Date.now() and Math.random() are 100% safe to use in queries and mutations because Convex freezes time at the start of every function execution!
  • ✅ Use v.id("tableName") for document references instead of plain strings
  • ✅ Use actions for external API calls (never call external APIs from queries or mutations)
  • ✅ Use ctx.runQuery / ctx.runMutation from actions — never access ctx.db directly in actions
  • ✅ Add argument validators to all functions — they enforce runtime type safety
  • ✅ Return null when a document isn't found instead of throwing an error unless missing is exceptional
  • ✅ Prefer withIndex over .filter() for query performance
Show full SKILL.md (404 more words)Show less

Anti-Patterns to Avoid

  1. ❌ External API calls in queries/mutations: Only actions can call external services. Queries and mutations run in the Convex transaction engine.
  2. ❌ Doing slow CPU-bound work in mutations: Mutations block database commits; offload heavy processing to actions.
  3. ❌ Using .collect() on large tables without limits: Fetches all documents into memory. Use .take(N) or .paginate().
  4. ❌ Skipping schema definition: Without a schema you lose end-to-end type safety, the main Convex advantage.
  5. ❌ Using .filter() instead of indexes: .filter() does a full table scan. Define an index and use .withIndex().
  6. ❌ Storing large blobs in documents: Use Convex file storage (_storage) for files; keep documents lean.
  7. ❌ Circular runQuery/runMutation chains: Actions calling mutations that schedule actions can create infinite loops.

Common Pitfalls

  • Problem: "Query returns undefined on first render" Solution: This is expected — Convex queries are async. Check for undefined before rendering (this means loading, not empty).

  • Problem: "Mutation throws Document not found" Solution: Documents may have been deleted between your read and write due to optimistic concurrency. Re-read inside the mutation.

  • Problem: "process.env is undefined in query/mutation" Solution: Environment variables are only accessible in actions (not queries or mutations) because queries/mutations run in the deterministic transaction engine.

  • Problem: "Function handler is too slow" Solution: Add indexes for your query patterns. Use withIndex() instead of .filter(). For complex operations, break into smaller mutations.

  • Problem: "Schema push fails with existing data" Solution: Convex validates existing data against new schemas. Either migrate existing documents first, or use v.optional() for new fields.

Limitations

  • Queries and mutations cannot call external HTTP APIs (use actions instead)
  • No raw SQL — you work with the Convex query builder API
  • Environment variables only available in actions, not in queries or mutations
  • Document size limit of 1MB
  • Maximum function execution time limits apply
  • No server-side rendering of Convex data without specific SSR patterns (use preloading)
  • Schemas are enforced at write-time; changing schemas requires data migration for existing documents
  • @firebase — Alternative BaaS with Firestore (compare: Convex is TypeScript-first with ACID transactions)
  • @supabase-automation — Alternative with PostgreSQL backend (compare: Convex is document-relational with built-in reactivity)
  • @prisma-expert — ORM for traditional databases (Convex replaces both ORM and database)
  • @react-patterns — Frontend patterns that pair well with Convex React hooks
  • @nextjs-app-router — Next.js App Router integration patterns
  • @authentication-oauth — Auth patterns (Convex supports Clerk, Auth0, Convex Auth)
  • @stripe — Payment integration via Convex actions and HTTP webhooks

Resources

© davila7, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in cli-tool/components/skills/development/convex of davila7/claude-code-templates.

Open the folder on GitHubat commit 46b4d8b

Used in 3 other repositories

We found 12 copies of this SKILL.md (exact, near-identical or edited) in other folders, from 3 other GitHub owners. This page covers the copy in davila7/claude-code-templates, which our catalogue first saw on October 7, 2026.

Compare with similar skills

Convex next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Convex compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Convex this skilldavila7/claude-code-templates32k3 repos~6.4kAutomated safety check: NotesMIT
SaaS Scaffolderalirezarezvani/claude-skills28k1 repos~2.6kAutomated safety check: PassMIT
SaaS Scaffolderborghei/Claude-Skills886—~1.8kAutomated safety check: PassMIT
Fullstack DevHHU3637kr/skills1453 repos~8.6kAutomated safety check: NotesMIT
Javascript SDKaiskillstore/marketplace4301 repos~3.3kAutomated safety check: PassNone
Amplify Workflowawslabs/agent-plugins915—~3.2kAutomated safety check: PassApache-2.0

Similar skills

  • SaaS Scaffolder

    alirezarezvani/claude-skills

    Generates complete, production-ready SaaS project boilerplate including authentication, database schemas, billing integration, API routes, and a working dashboard using Next.js 14+ App Router…

    28k GitHub starsUsed in 1 repo~2.6k tokens
    DatabasesAuto-check passed
  • SaaS Scaffolder

    borghei/Claude-Skills

    Generate SaaS boilerplate with auth, database schemas, Stripe billing, multi-tenancy, API routes, and dashboard UI on a Next.js/TypeScript/Tailwind stack.

    886 GitHub stars~1.8k tokensUpdated 2 days ago
    Backend & APIsAuto-check passed
  • Fullstack Dev

    HHU3637kr/skills

    Full-stack backend architecture and frontend-backend integration guide.

    145 GitHub starsUsed in 3 repos~8.6k tokens
    Backend & APIsAuto-check: notes
  • Javascript SDK

    aiskillstore/marketplace

    JavaScript/TypeScript SDK for inference.sh - run AI apps, build agents, integrate with all models.

    430 GitHub starsUsed in 1 repo~3.3k tokens
    Backend & APIsAuto-check passed
  • Amplify Workflow

    awslabs/agent-plugins

    Official

    Build and deploy full-stack web and mobile apps with AWS Amplify Gen2 (TypeScript code-first).

    915 GitHub stars~3.2k tokensUpdated yesterday
    MobileAuto-check passed
  • AWS Amplify

    aws/agent-toolkit-for-aws

    Official

    Build and deploy full-stack web and mobile apps with AWS Amplify Gen2 (TypeScript code-first).

    2.8k GitHub stars~3.9k tokensUpdated today
    MobileAuto-check passed

More from davila7/claude-code-templates

All 478 skills in this repo
  • Perplexity Web Search

    davila7/claude-code-templates

    Runs web-grounded searches through Perplexity's Sonar models over OpenRouter for current events, recent literature and cited facts beyond the model's training cutoff.

    32k GitHub starsUsed in 11 repos~3.5k tokens
    Auto-check: notes
  • Neuropixels Data Analysis

    davila7/claude-code-templates

    Analyzes Neuropixels recordings from SpikeGLX or Open Ephys through preprocessing, drift correction, Kilosort4 spike sorting, quality metrics and curation.

    32k GitHub starsUsed in 9 repos~2.8k tokens
    Auto-check passed
  • Scientific Venue Templates

    davila7/claude-code-templates

    Supplies LaTeX templates and formatting rules for journals, conferences, posters, and grant proposals, then can check a draft against them.

    32k GitHub starsUsed in 9 repos~5.1k tokens
    Auto-check: notes
  • Brand Voice Content Creator

    davila7/claude-code-templates

    Analyzes a brand's existing writing to lock in a consistent voice, then builds SEO blog posts and platform-specific social content around it.

    32k GitHub starsUsed in 3 repos~1.9k tokens
    Auto-check passed
  • CAPA Officer

    davila7/claude-code-templates

    Guides corrective and preventive action (CAPA) work in a quality management system, from initiation and root cause analysis through effectiveness verification.

    32k GitHub starsUsed in 1 repo~2k tokens
    Auto-check passed
  • Fda Consultant Specialist

    davila7/claude-code-templates

    Senior FDA consultant and specialist for medical device companies including HIPAA compliance and requirement management.

    32k GitHub starsUsed in 1 repo~2.7k tokens
    Auto-check passed

Questions about Convex

What does Convex do?

Convex reactive backend expert: schema design, TypeScript functions, real-time subscriptions, auth, file storage, scheduling, and deployment. Convex is an agent skill from davila7/claude-code-templates. Convex reactive backend expert: schema design, TypeScript functions, real-time subscriptions, auth, file storage, scheduling, and deployment.

When should I use Convex?

Convex fits situations like: tasks that involve Database schema design; tasks that involve File uploads and storage.

How do I install Convex in Claude Code?

Run `npx skills add davila7/claude-code-templates --skill convex -a claude-code`. Or copy the skill folder (cli-tool/components/skills/development/convex in davila7/claude-code-templates) into .claude/skills/convex in your project. Claude Code loads it when a task matches its description.

How do I install Convex in Codex?

Run `npx skills add davila7/claude-code-templates --skill convex -a codex`. Or copy the skill folder (cli-tool/components/skills/development/convex in davila7/claude-code-templates) into .agents/skills/convex in your project. Codex loads it when a task matches its description.

Can I use Convex in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add davila7/claude-code-templates --skill convex -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/convex, .gemini/skills/convex, .github/skills/convex and .opencode/skills/convex in your project.

What does Convex need to run?

Going by SKILL.md and its folder, Convex needs the command-line tools its instructions call (npx and npm) and credentials named OPENAI_API_KEY, SENDGRID_API_KEY, NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and BETTER_AUTH_SECRET. Our summary lists: Node.js; A credential in SENDGRID_API_KEY; A credential in OPENAI_API_KEY.

Does Convex access the network?

SKILL.md names 7 domains. In commands or code: api.sendgrid.com and api.openai.com; the agent is likely to contact these when it follows the instructions. As links in the text: docs.convex.dev, stack.convex.dev, github.com, convex.dev and chef.convex.dev. This is read from the text; nothing was executed.

Is Convex safe to install?

Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Convex use?

Convex is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Convex use?

About 6.4k tokens (SKILL.md is roughly 26k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Convex?

Skills that share tags, products or a category with Convex: SaaS Scaffolder (alirezarezvani/claude-skills, 28k stars), SaaS Scaffolder (borghei/Claude-Skills, 886 stars), Fullstack Dev (HHU3637kr/skills, 145 stars) and Javascript SDK (aiskillstore/marketplace, 430 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Convex?

davila7 (a GitHub user) maintains it in davila7/claude-code-templates, which has 32,483 GitHub stars. The repository holds 478 skills in this directory. The repository was last updated on October 9, 2026.

Source: davila7/claude-code-templates on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.