
Convex Best Practices
Install this skill when you are writing or reviewing Convex functions so queries, validators, and TypeScript patterns stay production-ready in a solo SaaS or agent-backed app.
Overview
Convex Best Practices is an agent skill most often used in Build (also Ship review) that teaches production-ready patterns for Convex function organization, queries, validation, TypeScript, and error handling.
Install
npx skills add https://github.com/waynesutton/convexskills --skill convex-best-practicesWhat is this skill?
- Covers function organization and naming so Convex modules stay navigable as the schema grows
- Documents query and mutation patterns that avoid N+1 reads, racey writes, and accidental full-table scans
- Requires argument and return validation aligned with Convex validators and TypeScript types
- Spells out error handling and failure modes so clients and agents get actionable messages
- Applies TypeScript usage conventions for generated types, helpers, and shared server utilities
Adoption & trust: 3.3k installs on skills.sh; 402 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You are shipping Convex backend code but lack a consistent checklist for validators, query shape, TypeScript typing, and error handling before users hit production.
Who is it for?
Solo builders using Convex for a SaaS or agent product who want their coding agent to apply backend conventions during implementation and pre-ship review.
Skip if: Teams not using Convex, greenfield tutorials with no existing functions, or pure infrastructure-only work with no Convex server code to inspect.
When should I use this skill?
When building or reviewing a Convex app and you need production-oriented guidance on function organization, queries, validation, TypeScript, or error handling.
What do I get? / Deliverables
Your Convex modules follow documented organization, validated IO, safer query patterns, and clearer errors so the backend is easier for you and your agent to extend and review before deploy.
- Convex functions aligned to documented organization and naming conventions
- Validators and TypeScript types applied consistently on public server entrypoints
- Documented error-handling patterns applied across queries, mutations, and actions
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Convex logic lives in the backend layer of the product, so the canonical shelf is Build → backend even though production-readiness guidance also applies during ship-time review. Function organization, query patterns, validation, and error handling are core Convex server/API concerns, not frontend or launch distribution work.
Where it fits
Refactor a growing convex/ tree so queries, mutations, and shared helpers follow one organization scheme the agent can reuse.
Harden Convex actions that call external APIs with consistent validation and error surfacing back to the client.
Run a pre-launch pass on Convex functions for validator coverage and query efficiency before turning on paid users.
Check that sensitive mutations validate auth context and fail closed instead of leaking data through permissive handlers.
How it compares
Use as a Convex-focused backend checklist skill instead of generic TypeScript lint rules or one-off chat reminders about database patterns.
Common Questions / FAQ
Who is convex-best-practices for?
It is for solo and indie builders who already chose Convex and want an agent skill that steers function layout, queries, validation, TypeScript, and errors toward production habits.
When should I use convex-best-practices?
Use it in Build while writing or refactoring Convex queries and mutations, and again in Ship during review or hardening before launch; also when an agent is auditing an existing convex/ folder for consistency.
Is convex-best-practices safe to install?
Treat it like any third-party skill: review the Security Audits panel on this Prism page and skim SKILL.md before granting broad filesystem or shell access to your agent.
SKILL.md
READMESKILL.md - Convex Best Practices
interface: icon_small: "./assets/small-logo.svg" icon_large: "./assets/large-logo.png" <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <g clip-path="url(#clip0_3_23)"> <g clip-path="url(#clip1_3_23)"> <path d="M10.0643 12.5735C12.3769 12.3166 14.5572 11.0843 15.7577 9.02756C15.1892 14.1148 9.62646 17.3302 5.08583 15.356C4.66743 15.1746 4.30728 14.8728 4.06013 14.4848C3.03973 12.8825 2.7043 10.8437 3.18626 8.99344C4.56327 11.37 7.3632 12.8267 10.0643 12.5735Z" fill="#F3B01C"/> <path d="M3.1018 7.50072C2.16436 9.66714 2.12376 12.2034 3.27303 14.2907C-0.771507 11.2479 -0.72737 4.7362 3.2236 1.72378C3.58904 1.44535 4.02333 1.2801 4.47881 1.25494C6.3519 1.15614 8.25501 1.88006 9.58963 3.22909C6.87799 3.25604 4.23695 4.99308 3.1018 7.50072Z" fill="#8D2676"/> <path d="M10.8974 3.89562C9.52924 1.98794 7.38779 0.68921 5.04156 0.649695C9.57686 -1.40888 15.1555 1.92867 15.7629 6.86314C15.8194 7.32119 15.7452 7.78824 15.5421 8.20138C14.6948 9.92223 13.1236 11.2569 11.2876 11.7508C12.6328 9.25579 12.4668 6.20748 10.8974 3.89562Z" fill="#EE342F"/> </g> </g> <defs> <clipPath id="clip0_3_23"> <rect width="16" height="16" fill="white"/> </clipPath> <clipPath id="clip1_3_23"> <rect width="16" height="16" fill="white"/> </clipPath> </defs> </svg> --- name: convex-best-practices description: Guidelines for building production-ready Convex apps covering function organization, query patterns, validation, TypeScript usage, error handling, and the Zen of Convex design philosophy --- # Convex Best Practices Build production-ready Convex applications by following established patterns for function organization, query optimization, validation, TypeScript usage, and error handling. ## Code Quality All patterns in this skill comply with `@convex-dev/eslint-plugin`. Install it for build-time validation: ```bash npm i @convex-dev/eslint-plugin --save-dev ``` ```js // eslint.config.js import { defineConfig } from "eslint/config"; import convexPlugin from "@convex-dev/eslint-plugin"; export default defineConfig([ ...convexPlugin.configs.recommended, ]); ``` The plugin enforces four rules: | Rule | What it enforces | | ----------------------------------- | --------------------------------- | | `no-old-registered-function-syntax` | Object syntax with `handler` | | `require-argument-validators` | `args: {}` on all functions | | `explicit-table-ids` | Table name in db operations | | `import-wrong-runtime` | No Node imports in Convex runtime | Docs: https://docs.convex.dev/eslint ## Documentation Sources Before implementing, do not assume; fetch the latest documentation: - Primary: https://docs.convex.dev/understanding/best-practices/ - Error Handling: https://docs.convex.dev/functions/error-handling - Write Conflicts: https://docs.convex.dev/error#1 - For broader context: https://docs.convex.dev/llms.txt ## Instructions ### The Zen of Convex 1. **Convex manages the hard parts** - Let Convex handle caching, real-time sync, and consistency 2. **Functions are the API** - Design your functions as your application's interface 3. **Schema is truth** - Define your data model explicitly in schema.ts 4. **TypeScript everywhere** - Leverage end-to-end type safety 5. **Queries are reactive** - Think in terms of subscriptions, not requests ### Function Organization Organize your Convex functions by domain: ```typescript // convex/users.ts - User-related functions import { query, mutation } from "./_generated/server"; import { v } from "convex/values"; export const get = query({ args: { userId: v.id("users") }, returns: v.union( v.object({ _id: v.id("users"), _creationTime: v.number(), name: v.string(), email: v.string(), }), v.null(), ), handler: async (ctx, args) => { return await ctx.db.get("users", args.userId); }, }); ``` ### Argument and Return Va