mit einem Klick
schema-builder
// Design and generate Convex database schemas with proper validation, indexes, and relationships. Use when creating schema.ts or modifying table definitions.
// Design and generate Convex database schemas with proper validation, indexes, and relationships. Use when creating schema.ts or modifying table definitions.
| name | schema-builder |
| description | Design and generate Convex database schemas with proper validation, indexes, and relationships. Use when creating schema.ts or modifying table definitions. |
Build well-structured Convex schemas following best practices for relationships, indexes, and validators.
convex/schema.ts filev.* typesimport { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
export default defineSchema({
tableName: defineTable({
// Required fields
field: v.string(),
// Optional fields
optional: v.optional(v.number()),
// Relations (use IDs)
userId: v.id("users"),
// Enums with union + literal
status: v.union(
v.literal("active"),
v.literal("pending"),
v.literal("archived")
),
// Timestamps
createdAt: v.number(),
updatedAt: v.optional(v.number()),
})
// Index for queries by this field
.index("by_user", ["userId"])
// Compound index for common query patterns
.index("by_user_and_status", ["userId", "status"])
// Index for time-based queries
.index("by_created", ["createdAt"]),
});
export default defineSchema({
users: defineTable({
name: v.string(),
email: v.string(),
}).index("by_email", ["email"]),
posts: defineTable({
userId: v.id("users"),
title: v.string(),
content: v.string(),
}).index("by_user", ["userId"]),
});
export default defineSchema({
users: defineTable({
name: v.string(),
}),
projects: defineTable({
name: v.string(),
}),
projectMembers: defineTable({
userId: v.id("users"),
projectId: v.id("projects"),
role: v.union(v.literal("owner"), v.literal("member")),
})
.index("by_user", ["userId"])
.index("by_project", ["projectId"])
.index("by_project_and_user", ["projectId", "userId"]),
});
export default defineSchema({
comments: defineTable({
postId: v.id("posts"),
parentId: v.optional(v.id("comments")), // null for top-level
userId: v.id("users"),
text: v.string(),
})
.index("by_post", ["postId"])
.index("by_parent", ["parentId"]),
});
export default defineSchema({
users: defineTable({
name: v.string(),
// Small, bounded collections are fine
roles: v.array(v.union(
v.literal("admin"),
v.literal("editor"),
v.literal("viewer")
)),
tags: v.array(v.string()), // e.g., max 10 tags
}),
});
// Primitives
v.string()
v.number()
v.boolean()
v.null()
v.id("tableName")
// Optional
v.optional(v.string())
// Union types (enums)
v.union(v.literal("a"), v.literal("b"))
// Objects
v.object({
key: v.string(),
nested: v.number(),
})
// Arrays
v.array(v.string())
// Records (arbitrary keys)
v.record(v.string(), v.boolean())
// Any (avoid if possible)
v.any()
Single-field indexes: For simple lookups
by_user: ["userId"]by_email: ["email"]Compound indexes: For filtered queries
by_user_and_status: ["userId", "status"]by_team_and_created: ["teamId", "createdAt"]Remove redundant: by_a_and_b usually covers by_a
v.union(v.literal(...)) patternv.number() (milliseconds since epoch)If converting from nested structures:
Before:
users: defineTable({
posts: v.array(v.object({
title: v.string(),
comments: v.array(v.object({ text: v.string() })),
})),
})
After:
users: defineTable({
name: v.string(),
}),
posts: defineTable({
userId: v.id("users"),
title: v.string(),
}).index("by_user", ["userId"]),
comments: defineTable({
postId: v.id("posts"),
text: v.string(),
}).index("by_post", ["postId"]),
Set up Convex authentication with proper user management, identity mapping, and access control patterns. Use when implementing auth flows.
Guide to using Convex components for feature encapsulation. Learn about sibling components, creating your own, and when to use components vs monolithic code.
Discover and use convex-helpers utilities for relationships, filtering, sessions, custom functions, and more. Use when you need pre-built Convex patterns.
Initialize a new Convex backend from scratch with schema, auth, and basic CRUD operations. Use when starting a new project or adding Convex to an existing app.
Create Convex queries, mutations, and actions with proper validation, authentication, and error handling. Use when implementing new API endpoints.
Plan and execute Convex schema migrations safely, including adding fields, creating tables, and data transformations. Use when schema changes affect existing data.