Claude-skill-registry 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.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/convex-backend-development" ~/.claude/skills/majiayu000-claude-skill-registry-convex-backend-development && rm -rf "$T"
manifest:
skills/data/convex-backend-development/SKILL.mdsource content
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:
- Read-only functions (games, users, answers, leaderboard)queries/
- Write operations (creating games, submitting answers, updating user scores)mutations/
- Long-running operations (AI question generation)actions/
- Database schema definitionschema.ts
- Authentication configurationauth.ts
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.