convex-js
IndexedCommit: e9a01980 pullsUpdated Jan 31, 2026
TypeScript backend SDK and client libraries for the Convex cloud platform, providing a fully managed backend with database, file storage, authentication, and reactive real-time updates.
Install this reference
Reference
Convex
TypeScript backend SDK and client libraries for the Convex cloud platform, providing a fully managed backend with database, file storage, authentication, and reactive real-time updates.
Quick References
| File | Purpose |
|---|---|
src/server/index.ts | Server-side SDK entry point |
src/react/index.ts | React integration entry point |
src/browser/index.ts | Browser client entry point |
src/nextjs/index.ts | Next.js SSR helpers |
README.md | Official documentation |
src/values/index.ts | Value utilities for Convex data |
When to Use
- Building full-stack applications with a managed backend without DevOps
- Need reactive real-time data synchronization between server and client
- Integrating with React applications for live query subscriptions
- Server-side rendering with Next.js or other frameworks
- Custom authentication flows with Auth0 or Clerk
- Vector search for AI-powered features
Installation
npm install convex
Best Practices
- Always use the generated API after running
npx convex devfor type safety instead of manual function references - Separate read and write operations - use queries for data fetching, mutations for writes
- Prefer pagination for large datasets using
paginate()instead of loading all results - Validate function arguments using validators from
convex/valuesto ensure type safety - Set up proper authentication using Auth0 or Clerk integrations for secure apps
Common Patterns
Defining a Database Schema:
// convex/schema.ts
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
export default defineSchema({
users: defineTable({
name: v.string(),
email: v.string(),
emailVerified: v.optional(v.boolean()),
}).index("by_email", ["email"]),
messages: defineTable({
body: v.string(),
userId: v.id("users"),
}).searchIndex("search_body", {
searchField: "body",
filterFields: ["userId"],
}),
});
Server Query and Mutation Functions:
// convex/myFile.ts
import { query, mutation } from "./_generated/server";
export const getUser = query({
args: { id: v.id("users") },
handler: async ({ db }, { id }) => {
return await db.get(id);
},
});
export const createUser = mutation({
args: { name: v.string(), email: v.string() },
handler: async ({ db }, { name, email }) => {
const userId = await db.insert("users", { name, email });
return userId;
},
});
React Client Setup and Hooks:
// _app.tsx or layout.tsx
import { ConvexProvider, ConvexReactClient } from "convex/react";
const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL);
export default function App() {
return (
<ConvexProvider client={convex}>
<YourComponent />
</ConvexProvider>
);
}
Using React Hooks:
import { useQuery, useMutation } from "convex/react";
import { api } from "../convex/_generated/api";
function MessagesList() {
const messages = useQuery(api.messages.list);
const addMessage = useMutation(api.messages.create);
if (messages === undefined) return null;
return (
<div>
{messages.map(msg => <div key={msg._id}>{msg.body}</div>)}
</div>
);
}
Paginated Queries:
export const listMessages = query({
args: { paginationOpts: paginationOptsValidator },
handler: async ({ db }, { paginationOpts }) => {
return await db.query("messages")
.order("desc")
.paginate(paginationOpts);
},
});
// React usage
const { results, status, loadMore } = usePaginatedQuery(
api.messages.list,
{ paginationOpts: { numItems: 10, cursor: null } },
);
Vector Search:
export const searchEmbeddings = query({
args: {
query: v.array(v.float64()),
limit: v.optional(v.number()),
},
handler: async ({ vectorSearch }, { query, limit }) => {
return await vectorSearch(
"documents",
"byEmbedding",
{ vector: query, limit: limit ?? 10 }
);
},
});
Browser HTTP Client:
import { ConvexHttpClient } from "convex/browser";
import { api } from "../convex/_generated/api";
const client = new ConvexHttpClient(process.env.CONVEX_URL);
// In a serverless function or API route
export async function GET() {
const data = await client.query(api.users.list);
return Response.json(data);
}
Next.js SSR with Preloading:
// app/page.tsx (Server Component)
import { preloadQuery } from "convex/nextjs";
import { api } from "@/convex/_generated/api";
export default async function Page() {
const preloaded = await preloadQuery(api.counter.get, {});
return <Counter preloaded={preloaded} />;
}
// components/Counter.tsx (Client Component)
import { usePreloadedQuery } from "convex/react";
import { Preloaded } from "convex/react";
export default function Counter({ preloaded }: { preloaded: Preloaded<typeof api.counter.get> }) {
const count = usePreloadedQuery(preloaded);
return <div>{count}</div>;
}
Authentication with Clerk:
import { ConvexProviderWithClerk } from "convex/react-clerk";
import { ClerkProvider, useAuth } from "@clerk/clerk-react";
export default function App() {
return (
<ClerkProvider publishableKey={import.meta.env.VITE_CLERK_PUB_KEY}>
<ConvexProviderWithClerk client={convex} useAuth={useAuth}>
<YourApp />
</ConvexProviderWithClerk>
</ClerkProvider>
);
}
File Storage:
import { mutation } from "./_generated/server";
export const uploadUrl = mutation({
handler: async ({ storage }) => {
return await storage.generateUploadUrl();
},
});
export const finalizeUpload = mutation({
args: { storageId: v.id("_storage") },
handler: async ({ storage }, { storageId }) => {
return await storage.getUrl(storageId);
},
});
Scheduled Functions:
import { cronJobs } from "convex/server";
export default cronJobs()
.daily({
hour: 2,
minute: 0,
handler: async ({ db }) => {
// Run cleanup tasks
},
});
HTTP Actions:
import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";
const http = httpRouter();
http.route({
path: "/webhook",
method: "POST",
handler: httpAction(async ({ request }, action) => {
const { data } = await request.json();
await action(api.webhooks.process, { data });
return new Response(null, { status: 200 });
}),
});
export default http;
API Quick Reference
| Export | Type | Description |
|---|---|---|
query | Function builder | Define read-only server functions |
mutation | Function builder | Define server functions that write data |
action | Function builder | Define server functions with external I/O access |
defineSchema | Function | Define your database schema with tables and indexes |
defineTable | Function | Define a single table with validators and indexes |
v | Validator builder | Define value validators for function arguments |
ConvexReactClient | Class | WebSocket-based client for React with real-time sync |
ConvexProvider | Component | Provider to store ConvexReactClient in React context |
useQuery | Hook | Subscribe to query results in React components |
useMutation | Hook | Execute mutations from React components |
useAction | Hook | Execute actions from React components |
usePaginatedQuery | Hook | Handle paginated queries in React |
useQueries | Hook | Execute multiple queries in a single React render |
ConvexHttpClient | Class | HTTP-based client for server-side code or non-React apps |
preloadQuery | Function | Preload query data for Next.js SSR |
fetchQuery | Function | Fetch query data in Next.js server components |
vectorSearch | Function | Perform vector similarity search |
cronJobs | Function | Define scheduled functions |
httpRouter | Function | Define HTTP endpoints for webhooks |
ConvexProviderWithClerk | Component | Convex provider integrated with Clerk auth |
ConvexProviderWithAuth0 | Component | Convex provider integrated with Auth0 |