Agent Skills: 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.

UncategorizedID: violabg/dev-quiz-battle/convex-backend-development

Install this agent skill to your local

pnpm dlx add-skill https://github.com/violabg/dev-quiz-battle/tree/HEAD/skills/convex-backend-development

Skill Files

Browse the full folder contents for convex-backend-development.

Download Skill

Loading file tree…

skills/convex-backend-development/SKILL.md

Skill Metadata

Name
convex-backend-development
Description
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.

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:

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:

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:

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:

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:

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 for complete schema definition.