convex

Expert Convex development assistant. Use when users want to build full-stack TypeScript apps with Convex - including setup, server functions (queries/mutations/actions), database schema, auth, file storage, real-time features, frontend integration (React, Next.js, Vue), testing, or deployment.

16 stars

Best use case

convex is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Expert Convex development assistant. Use when users want to build full-stack TypeScript apps with Convex - including setup, server functions (queries/mutations/actions), database schema, auth, file storage, real-time features, frontend integration (React, Next.js, Vue), testing, or deployment.

Teams using convex should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/convex/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/development/convex/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/convex/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How convex Compares

Feature / AgentconvexStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Expert Convex development assistant. Use when users want to build full-stack TypeScript apps with Convex - including setup, server functions (queries/mutations/actions), database schema, auth, file storage, real-time features, frontend integration (React, Next.js, Vue), testing, or deployment.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

This skill provides expert guidance for building applications with Convex - the full-stack reactive database platform.

## Quick Start

When a user wants to start with Convex:

1. **New project:**
   ```bash
   npm create convex@latest
   npx convex dev
   ```

2. **Add to existing project:**
   ```bash
   npm install convex
   npx convex dev
   ```

3. **Verify:** Check dashboard at https://dashboard.convex.dev

## Core Concepts

### Three Function Types

**Queries** - Read-only, auto-reactive:
```typescript
import { query } from "./_generated/server";

export const list = query({
  args: { channelId: v.id("channels") },
  handler: async ({ db }, { channelId }) => {
    return await db.query("messages")
      .withIndex("by_channel", (q) => q.eq("channel", channelId))
      .collect();
  }
});
```

**Mutations** - Write operations, transactions:
```typescript
import { mutation } from "./_generated/server";

export const send = mutation({
  args: { body: v.string(), channel: v.id("channels") },
  handler: async ({ db }, { body, channel }) => {
    await db.insert("messages", { body, channel, createdAt: Date.now() });
  }
});
```

**Actions** - External API calls:
```typescript
import { action } from "./_generated/server";

export const summarize = action({
  args: { postId: v.id("posts") },
  handler: async (ctx, { postId }) => {
    const post = await ctx.runQuery(api.posts.get, { postId });
    const summary = await fetchLLM(post);
    await ctx.runMutation(api.posts.update, { postId, summary });
  }
});
```

### Database Operations

```typescript
// CRUD
await db.insert("table", { field: value });
const doc = await db.get(id);
await db.patch(id, { field: newValue });
await db.delete(id);

// Query methods
.collect()  // All results
.first()   // First or null
.unique()  // Exactly one (throws if not)
.paginate({ numItems: 50 })  // Pagination
```

### Schema Definition

**File:** `convex/schema.ts`

```typescript
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";

export default defineSchema({
  messages: defineTable({
    body: v.string(),
    author: v.id("users"),
    channel: v.id("channels"),
    createdAt: v.number()
  })
  .index("by_channel", ["channel"])
  .index("by_channel_created", ["channel", "createdAt"])
});
```

**Common types:**
- `v.string()`, `v.number()`, `v.boolean()`
- `v.id("table")` - Foreign key
- `v.array(T)`, `v.object({})`
- `v.optional(T)`, `v.union(...)`

## Frontend Integration

### React

```typescript
import { ConvexProvider, ConvexReactClient } from "convex/react";

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

<ConvexProvider client={convex}>
  <App />
</ConvexProvider>
```

**Usage:**
```typescript
import { useQuery, useMutation } from "convex/react";
import { api } from "../convex/_generated/api";

const messages = useQuery(api.messages.list, { channelId });
const sendMessage = useMutation(api.messages.send);
```

### Next.js App Router

**Server-side preloading:**
```typescript
import { preloadQuery } from "convex/nextjs";

const preloaded = await preloadQuery(api.posts.list);
return <ClientPage preloaded={preloaded} />;
```

**Client component:**
```typescript
"use client";
import { usePreloadedQuery } from "convex/react";

const posts = usePreloadedQuery(preloaded);
```

## Authentication

### Clerk (Recommended)

**Install:** `npm install @clerk/clerk-react`

**File:** `convex/auth.config.ts`
```typescript
import { AuthConfig } from "convex/server";

export default {
  providers: [{ domain: process.env.CLERK_JWT_ISSUER_DOMAIN!, applicationID: "convex" }]
} satisfies AuthConfig;
```

**Frontend:**
```typescript
import { ConvexProviderWithClerk } from "convex/react-clerk";

<ConvexProviderWithClerk client={convex} useAuth={useAuth}>
  <App />
</ConvexProviderWithClerk>
```

**In functions:**
```typescript
const identity = await ctx.auth.getUserIdentity();
if (!identity) throw new Error("Unauthorized");
```

## File Storage

```typescript
// Upload
const storageId = await ctx.storage.store(fileBlob);
await db.insert("files", { storageId, name });

// Download
const url = await ctx.storage.getUrl(storageId);

// Delete
await ctx.storage.delete(storageId);
```

## HTTP Endpoints

**File:** `convex/http.ts`

```typescript
import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";

const http = httpRouter();

http.route({
  path: "/webhooks/stripe",
  method: "POST",
  handler: httpAction(async (ctx, request) => {
    const payload = await request.json();
    await ctx.runMutation(internal.payments.process, { payload });
    return new Response(null, { status: 200 });
  }),
});

export default http;
```

**URL:** `https://<deployment>.convex.site`

## Scheduled Tasks

**Cron Jobs (File: `convex/crons.ts`):**
```typescript
import { cronJobs } from "convex/server";

const crons = cronJobs();
crons.interval("cleanup", { hours: 1 }, internal.tasks.cleanup);
crons.daily("digest", { hourUTC: 9 }, internal.notifications.send);
export default crons;
```

**Scheduler API (in mutations/actions):**
```typescript
// Schedule for later
await ctx.scheduler.runAfter(delayMs, internal.tasks.process, { id });

// Schedule at specific time
await ctx.scheduler.runAt(timestamp, internal.tasks.remind, { userId });
```

## Best Practices

### ✅ DO
- Use indexes for queried fields
- Filter in application code, not with `.filter()` on queries
- Validate auth in protected functions
- Use pagination for large datasets
- Use `ConvexError` for structured errors clients can handle
- Direct function calls, not multiple sequential `ctx.runQuery`

### ❌ DON'T
- Use `.filter()` on queries (use indexes or filter in code)
- Make multiple sequential `runQuery/runMutation` calls (consolidate)
- Forget to validate authentication
- Fetch entire tables without pagination

### Error Handling

```typescript
import { ConvexError } from "convex/values";

// Throw structured errors
if (!identity) {
  throw new ConvexError({ code: "UNAUTHORIZED", message: "Login required" });
}

// Client catches and handles
if (error instanceof ConvexError) {
  console.error(error.data.code, error.data.message);
}
```

## Deployment

**Production:**
```bash
npx convex deploy
```

**With frontend build:**
```bash
npx convex deploy --cmd 'npm run build'
```

**Environment:** Set `CONVEX_DEPLOY_KEY` for production

## Testing

**Install:** `npm install convex-test vitest --save-dev`

```typescript
import { convexTest } from "convex-test";

const t = convexTest(schema);

// Test mutations
await t.mutation(api.posts.create, { title: "Test" });

// Test queries
const posts = await t.query(api.posts.list);
expect(posts).toHaveLength(1);
```

## Common Issues

| Problem | Solution |
|---------|----------|
| Function not found | Run `npx convex dev` to regenerate types |
| Real-time not working | Check ConvexProvider wraps app |
| Type errors | Restart TypeScript server, regenerate types |
| Deploy fails | Verify `CONVEX_DEPLOY_KEY` is set |

## Progressive Disclosure

**Advanced topics in references:**
- **Complete setup**: [QUICK_START.md](references/QUICK_START.md)
- **Deep dive on functions**: [CORE_CONCEPTS.md](references/CORE_CONCEPTS.md)
- **Auth patterns**: [AUTH.md](references/AUTH.md)
- **Framework integration**: [FRONTEND.md](references/FRONTEND.md)
- **Performance patterns**: [BEST_PRACTICES.md](references/BEST_PRACTICES.md)
- **Production deployment**: [DEPLOYMENT.md](references/DEPLOYMENT.md)
- **Troubleshooting**: [TROUBLESHOOTING.md](references/TROUBLESHOOTING.md)
- **HTTP endpoints, cron, vector search, Convex Auth**: [ADVANCED.md](references/ADVANCED.md)

## Your Approach

1. **Assess first:** New project or existing? Framework? Goals?
2. **Start simple:** Quick start → add complexity progressively
3. **Embrace reactivity:** Leverage automatic real-time updates
4. **Type safety:** Use TypeScript validation throughout
5. **Index for performance:** Always use indexes on queried fields
6. **Validate auth:** Check authentication in protected functions
7. **Test before deploying:** Use convex-test for unit tests

Related Skills

convex-development-general

16
from diegosouzapw/awesome-omni-skill

Applies general rules for Convex development, emphasizing schema design, validator usage, and correct handling of system fields.

convex-core

16
from diegosouzapw/awesome-omni-skill

Core Convex development guidelines - functions, validators, schema, queries, mutations, and database patterns

convex-component-authoring

16
from diegosouzapw/awesome-omni-skill

How to create, structure, and publish self-contained Convex components with proper isolation, exports, and dependency management

convex-ai

16
from diegosouzapw/awesome-omni-skill

Convex AI Integration - OpenAI, actions, streaming, and AI patterns with database integration

bgo

10
from diegosouzapw/awesome-omni-skill

Automates the complete Blender build-go workflow, from building and packaging your extension/add-on to removing old versions, installing, enabling, and launching Blender for quick testing and iteration.

Coding & Development

database-architect

16
from diegosouzapw/awesome-omni-skill

Expert database architect specializing in data layer design from scratch, technology selection, schema modeling, and scalable database architectures. Masters SQL/NoSQL/TimeSeries database selection, normalization strategies, migration planning, and performance-first design. Handles both greenfield architectures and re-architecture of existing systems. Use PROACTIVELY for database architecture, technology selection, or data modeling decisions.

data-transform-gen

16
from diegosouzapw/awesome-omni-skill

Generate ETL and data transformation scripts. Use when migrating data between systems.

data-sql-optimization

16
from diegosouzapw/awesome-omni-skill

Production-grade SQL optimization for OLTP systems: EXPLAIN/plan analysis, balanced indexing, schema and query design, migrations, backup/recovery, HA, security, and safe performance tuning across PostgreSQL, MySQL, SQL Server, Oracle, SQLite.

data-engineering-backend-architect

16
from diegosouzapw/awesome-omni-skill

Expert backend architect specializing in scalable API design, microservices architecture, and distributed systems. Masters REST/GraphQL/gRPC APIs, event-driven architectures, service mesh patterns, and modern backend frameworks. Handles service boundary definition, inter-service communication, resilience patterns, and observability. Use PROACTIVELY when creating new backend services or APIs. Use when: the task directly matches backend architect responsibilities within plugin data-engineering. Do not use when: a more specific framework or task-focused skill is clearly a better match.

data-client-setup

16
from diegosouzapw/awesome-omni-skill

Install and set up @data-client/react or @data-client/vue in a project. Detects project type (NextJS, Expo, React Native, Vue, plain React) and protocol (REST, GraphQL, custom), then hands off to protocol-specific setup skills.

data-architect

16
from diegosouzapw/awesome-omni-skill

**Master Skill**: Data Architect for PayU. Expert in PostgreSQL design, Performance Tuning (Indexing/Locking), Flyway migrations, CQRS/Event-Sourcing, TimescaleDB, and high-scale JSONB patterns.

darpan-gemini

16
from diegosouzapw/awesome-omni-skill

Use when coding or reviewing the Moqui-based Darpan component to follow local conventions, documentation practices, and verification steps; keep work inside runtime/component/darpan/** and apply both AGENTS files.