Convex Patterns
Design your schema
Define Convex tables, validators, and indexes that support the queries and mutations used from Nuxt or Vue.
Your frontend API is only as predictable as the schema behind it. Use this page to shape the tables and indexes that the shared runtime will query.
Start with the fields you actually read
convex/schema.ts
import { defineSchema, defineTable } from 'convex/server'
import { v } from 'convex/values'
export default defineSchema({
tasks: defineTable({
title: v.string(),
userId: v.optional(v.string()),
isCompleted: v.boolean(),
createdAt: v.number(),
}).index('by_user', ['userId']),
})
Run npx convex dev after schema changes so the generated API stays in sync with the docs examples and your app code.
Add indexes for the queries you expect
The frontend helpers do not hide slow query design. If your UI filters or sorts by a field, design the index for that access pattern.
ctx.db
.query('tasks')
.withIndex('by_user', q => q.eq('userId', userId))
.order('desc')
.take(20)
For compound filters, define a compound index in the same order as the equality filters you apply before the range or sort behavior.
Add related tables deliberately
Use v.id('tableName') for document relationships and keep the shape consistent with the mutations and queries you plan to expose.
Next steps
- Read Design your functions to expose the schema through queries, mutations, and actions
- Read Realtime and SSR to understand how those reads behave in the frontend