Connor Holly

← AI Skills

Convex Database Bootstrap

Productivity

convexdatabasesetup

What it does

Initializes a Convex real-time database project from scratch with schema, queries, mutations, and environment wiring. Follows Convex conventions so the project works correctly with real-time subscriptions out of the box.

The pattern

Workflow (6 steps):

  1. Confirm mode. Is this a new project or adding Convex to an existing one? New projects get a fresh convex/ directory. Existing projects get Convex files appended without overwriting anything.

  2. Bootstrap. Initialize the Convex project: install the npm package, run npx convex dev to create the project and generate the deployment URL. Store the URL in .env.local.

  3. Define schema. Create convex/schema.ts with domain tables. Each table gets:

    • Field definitions using Convex validators (v.string(), v.number(), v.optional())
    • Indexes for common query patterns (always index fields you filter or sort by)
    • A _creationTime field is automatically included
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";

export default defineSchema({
  tasks: defineTable({
    title: v.string(),
    status: v.union(v.literal("pending"), v.literal("done")),
    assignee: v.optional(v.id("users")),
  }).index("by_status", ["status"])
    .index("by_assignee", ["assignee"]),
});
  1. Scaffold functions. Create query, mutation, and action files following Convex's three-function-type separation:

    • Queries read data. They are cached and reactive (subscribers get automatic updates).
    • Mutations write data. They are transactional and trigger reactive updates.
    • Actions call external APIs or do non-deterministic work. They cannot directly read or write the database (call mutations from actions for writes).
  2. Wire environment. Set environment variables via the Convex dashboard or npx convex env set KEY VALUE. Common variables: API keys for actions, webhook secrets, feature flags.

  3. Deploy and smoke test. Push the schema with npx convex dev (development) or npx convex deploy (production). Verify by running a mutation, then a query, and confirming the data round-trips.

Non-destructive by design. The bootstrap process appends missing configuration. It checks for existing convex/ directories, existing schema files, and existing function files before writing anything. If files exist, it reports what it found and asks how to proceed.

Key decisions

Validators in schema, not at runtime. Convex schemas enforce types at write time. If a mutation tries to insert invalid data, it fails immediately. This eliminates bugs where bad data enters the database and causes errors downstream.

Query/mutation/action separation is non-negotiable. Queries are pure reads (cached, reactive). Mutations are pure writes (transactional). Actions are side-effectful (external API calls). Mixing concerns produces functions that Convex cannot optimize.

Index everything you query by. Convex rejects queries that require full table scans at scale. Define indexes at schema time, not as an afterthought.

When to use it

When starting a new project that needs real-time data (collaborative apps, dashboards, chat, live feeds). When adding a real-time backend to an existing React or Next.js application. When you want a database that handles subscriptions natively instead of bolting on WebSocket layers. Not the right choice for projects that need raw SQL, complex joins, or traditional relational modeling.