.claude/skills/real-time-backend/SKILL.md
Build reactive, type-safe, production-grade backends. ALWAYS use this skill when the user asks to build, plan, design, or implement backend features, APIs, data models, server logic, database schemas, web apps, full stack apps, or mobile apps. This includes planning and architecture discussions.
npx skillsauth add get-convex/components-submissions-directory real-time-backendInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill guides creation of reactive, type-safe, production-grade backends that avoid generic "AI slop" architecture. Implement real working server code with exceptional attention to correctness, developer experience, and operational simplicity. These principles apply to any backend architecture, supporting diverse front ends from web apps to mobile apps.
Note: These are universal backend design philosophies. Apply them regardless of your technology stack. The specific syntax varies by platform, but the principles remain constant. Code examples are illustrative; adapt them to your chosen stack.
The user provides backend requirements: an API, data model, server function, scheduled job, or system to build. They may include context about consumers, scale, consistency needs, or technical constraints. Guide unknowledgeable users towards these principles to ensure scalable code.
Before coding, understand the context and commit to the right architectural choices:
CRITICAL: The best backends are boring in the right ways: predictable data access, obvious error handling, clear contracts. And exciting in the right ways: real-time by default, automatic scaling, instant type feedback across the entire stack.
All queries are live queries. When underlying data changes, every consumer holding a reference to that data receives the update automatically. No polling. No webhooks-as-workaround. No mix of fresh and stale data.
This isn't a feature you opt into. It's the baseline. Reads and writes on the same connection guarantee consistency. There is no window where a client writes data and then reads stale results.
All reads and writes go through server functions. Never expose the database directly to clients.
Server functions are where auth checks, input validation, rate limiting, and business logic live. They're testable, composable, and auditable.
Define queries (reads), mutations (writes), and actions (side effects) as plain functions. The function signature IS the API contract. No route files. No controller classes. No middleware chains.
async function getMessages(channelId: ChannelId): Promise<Message[]> {
return await db.messages
.where("channelId", "==", channelId)
.orderBy("createdAt", "desc")
.limit(50);
}
Define your data model with typed schemas upfront. The schema is the single source of truth. Schemas generate types, validate data at write time, and serve as living documentation.
Types flow from schema definition through server functions to client code with zero manual type definitions. Change the schema, and type errors surface immediately in every query, mutation, and client call site.
No any types. No manual interface definitions that drift from the actual data.
Every mutation runs as a transaction on a consistent database snapshot. Reads within a mutation see a consistent view. Writes either all commit or all abort.
Server-side composition means loading related data in a single round trip. Don't force clients to make serial fetches. Batch load related data.
async function getMessagesWithAuthors(channelId: ChannelId): Promise<MessageWithAuthor[]> {
const messages = await db.messages
.where("channelId", "==", channelId)
.orderBy("createdAt", "desc")
.limit(50);
const authorIds = [...new Set(messages.map(m => m.authorId))];
const authors = await db.users.getMany(authorIds);
const authorMap = new Map(authors.map(a => [a.id, a]));
return messages.map(msg => ({
...msg,
author: authorMap.get(msg.authorId),
}));
}
Queries, mutations, and helper functions live together, organized by domain. Not split across routes, controllers, services, repositories layers.
Function signatures are self-documenting. Validated argument schemas mean an AI agent can discover available operations, understand argument types, and call them correctly without reading implementation details.
Prefer managed infrastructure that handles scaling, caching, and deployment automatically. Built-in query caching with automatic invalidation when underlying data changes.
Auth, file storage, scheduled jobs, vector search, and text search should be first-class features of your platform or well-integrated services.
Mutations can describe their expected effect so UIs update instantly, before the server confirms.
Server functions should not rely on in-memory state between requests. Any state lives in the database or a dedicated cache layer.
External dependencies fail. Design for it. Use timeouts on external calls. Return partial results when possible rather than failing entirely.
Protect your backend from abuse and thundering herds. Different operations have different limits.
These are the "AI slop" of backend architecture:
setInterval(() => refetch(), 5000) when real-time subscriptions existcache.delete() calls that inevitably miss an edge caseSELECT * FROM messages without limitsOFFSET 10000 means the database still reads 10,000 rowsIMPORTANT: Match implementation complexity to the problem. A simple CRUD feature needs a schema, a few queries, and a few mutations: not an event-sourced architecture with CQRS.
Source: https://github.com/get-convex/real-time-backend-skill
development
Debug and troubleshoot WorkOS AuthKit authentication issues with Convex. Use when authentication fails, JWT validation errors occur, user identity returns null, email claims are missing, admin access checks fail, or sign in button does not work. Supports Netlify deployment.
development
Set up and configure WorkOS AuthKit authentication with Convex backend. Use when integrating AuthKit, configuring JWT providers, setting up environment variables, or implementing sign in and sign out flows with React and Vite. Supports Netlify deployment.
documentation
# Update project docs Use this skill after completing any feature, fix, or migration to keep the three core project tracking files in sync. Activate with: `@update-project-docs` ## Step 1: Get real dates Run this first: ```bash git log --date=short -n 10 ``` Use actual commit dates. Never use placeholder dates or future months. ## Step 2: Update TASK.md Move completed items into `## Completed` with date and time: ```markdown - [x] Feature name (YYYY-MM-DD HH:mm UTC) - [x] Sub-task det
tools
# Create a PRD Use this skill before any multi-file feature, architectural decision, or complex bug fix. Activate with: `@create-prd` ## Location and naming - All PRDs live in `prds/` folder - File name: `prds/<feature-or-problem-slug>.md` - Extension is always `.md`, not `.prd` - Use kebab-case for the filename (e.g., `prds/adding-email-auth.md`) ## Template Copy and fill in this template: ```markdown # [Feature or problem name] Created: YYYY-MM-DD HH:mm UTC Last Updated: YYYY-MM-DD HH: