# Convex Backend Development

> Develop and maintain Convex backend functions including queries, mutations, and actions. Use when working with database operations, authentication, game management, scoring logic, and real-time data updates in the dev-quiz-battle app.

- Skill: `aibot88/convex-backend-development` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add aibot88/convex-backend-development`
- Raw SKILL.md: https://api.skillmd.com/api/skills/aibot88/convex-backend-development/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: aibot88 (https://skillmd.com/u/aibot88)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/aibot88/convex-backend-development

---


# Convex Backend Development

This skill covers building and maintaining Convex backend functions for the dev-quiz-battle application.

## Step-by-step instructions

### 1. Understanding the Project Structure

The Convex backend is located in the `convex/` directory with:

- `queries/` - Read-only functions (games, users, answers, leaderboard)
- `mutations/` - Write operations (creating games, submitting answers, updating user scores)
- `actions/` - Long-running operations (AI question generation)
- `schema.ts` - Database schema definition
- `auth.ts` - Authentication configuration

### 2. Creating Queries

Queries fetch data from the database without modifying it. Common patterns:

```typescript
import { query } from "convex/server";
import { v } from "convex/values";

export const getGameData = query({
  args: { gameCode: v.string() },
  handler: async (ctx, args) => {
    const game = await ctx.db
      .query("games")
      .filter((q) => q.eq(q.field("code"), args.gameCode))
      .first();
    return game;
  },
});
```

### 3. Creating Mutations

Mutations modify the database state. Always validate input:

```typescript
import { mutation } from "convex/server";
import { v } from "convex/values";

export const createGame = mutation({
  args: { creatorId: v.id("users"), language: v.string() },
  handler: async (ctx, args) => {
    const gameId = await ctx.db.insert("games", {
      creatorId: args.creatorId,
      language: args.language,
      code: generateUniqueCode(),
      status: "waiting",
      createdAt: Date.now(),
    });
    return gameId;
  },
});
```

### 4. Creating Actions

Actions handle async operations like API calls:

```typescript
import { action } from "convex/server";
import { v } from "convex/values";

export const generateQuestion = action({
  args: { language: v.string(), difficulty: v.string() },
  handler: async (ctx, args) => {
    // Call external API or perform async work
    const response = await fetch("https://api.example.com/questions");
    return response.json();
  },
});
```

### 5. Using Authentication

Access the authenticated user:

```typescript
const identity = await ctx.auth.getUserIdentity();
if (!identity) {
  throw new Error("Not authenticated");
}
const userId = identity.subject;
```

### 6. Validation Patterns

Always validate arguments using Convex validators:

```typescript
args: {
  email: v.string(),
  password: v.string(),
  language: v.string(),
}
```

## Common Edge Cases

- **Invalid game codes**: Check if game exists before operations
- **Concurrent submissions**: Use game status to prevent duplicate answers
- **User authentication**: Always verify identity for sensitive mutations
- **Score calculations**: Account for time-based bonuses and difficulty multipliers

## Key Files to Reference

See [Convex Schema Reference](references/CONVEX_SCHEMA.md) for complete schema definition.

