RealtimeKeep your app up to date
AuthenticationOver 80+ OAuth integrations
Convex Components
ComponentsIndependent, modular, TypeScript building blocks for your backend.
Open sourceSelf host and develop locally
AI CodingGenerate high quality Convex code with AI
Compare
Convex vs. Firebase
Convex vs. Supabase
Convex vs. SQL
DocumentationGet started with your favorite frameworks
SearchSearch across Docs, Stack, and Discord
TemplatesUse a recipe to get started quickly
Convex ChampionsAmbassadors that support our thriving community
Convex for StartupsStart and scale your company with Convex
Convex for Open SourceSupport for open source projects
Convex CommunityShare ideas and ask for help in our community Discord
Stack
Stack

Stack is the Convex developer portal and blog, sharing bright ideas and techniques for building with Convex.

Explore Stack
BlogChangelogDocsPricing
npm1.3M weekly
GitHub21,342 stars
Log inStart building

Try Convex

Edit the code and watch the app and data update in real time. These demos run against an in-browser Convex test runtime, so you can try queries, mutations, and scheduled functions without creating an account.

Open on a larger display

These live demos are available in browser windows 1024px wide or larger. Widen this window or open this page on a larger display to try them.

Everything is code

From database schemas to queries, from auth to APIs, express every part of your backend in pure TypeScript. Your backend code lives next to your app code, is typechecked and autocompleted, and is generated by AI with exceptional accuracy.

import { mutation, query } from "./_generated/server";
import { v } from "convex/values";
export const setComplete = mutation({
args: { id: v.id("todos") },
handler: async (ctx, args) => {
await ctx.db.patch("todos", args.id, {
// Try checking a todo--nothing happens!
// Change this to `true` and try again.
completed: false,
});
},
});
export const list = query({…});
export const add = mutation({…});
export const setIncomplete = mutation({…});
Try it out!
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
export default defineSchema({
todos: defineTable({
text: v.string(),
category: v.optional(v.string()),
completed: v.boolean(),
}).index("by_completed", ["completed"]),
});

Always in sync

Convex libraries guarantee that your app always reflects changes to your frontend code, backend code, and database state in real time. No need for state managers, cache invalidation policies, or websockets.

import { api } from "../../convex/_generated/api";
import { TodoList } from "./TodoList";
import { useQuery } from "convex/react";
export function TodoApp() {
// Load more by changing `count` to 10.
// Everything updates reactively.
const todos = useQuery(api.todos.list, { count: 5 });
return <TodoList todos={todos} />;
}
Try it out!
import { mutation, query } from "./_generated/server";
import { v } from "convex/values";
export const setComplete = mutation({…});
export const list = query({
args: { count: v.number() },
handler: async (ctx, args) => {
return await ctx.db.query("todos").order("desc").take(args.count);
},
});
export const add = mutation({…});
export const setIncomplete = mutation({…});

Backend built-ins

Create cron jobs, kick off backend AI workflows, leverage built-in auth, and tap into a growing ecosystem of components that solve common backend needs with just an npm i.

import { cronJobs } from "convex/server";
import { internal } from "./_generated/api";
const crons = cronJobs();
crons.interval(
"categorize todos",
{ seconds: 5 },
internal.categorize.categorize,
{
// Add categories "Sports" and "Health"
// to see the todos categorized on the
// next cron job run.
categories: ["Chores", "Work"],
},
);
export default crons;
Try it out!
import { v } from "convex/values";
import { api, internal } from "./_generated/api";
import { Doc, Id } from "./_generated/dataModel";
import { internalAction, internalMutation } from "./_generated/server";
import Anthropic from "@anthropic-ai/sdk";
type AiCategorizeResponse = {
id: Id<"todos">;
category: string;
};
export const categorize = internalAction({
args: { categories: v.array(v.string()) },
handler: async (ctx, args) => {
const todos = await ctx.runQuery(api.todos.list, { count: 100 });
const response = await categorizeTodos(todos, args.categories);
await ctx.runMutation(internal.categorize.setCategories, {
categories: response,
});
},
});
export const setCategories = internalMutation({
args: {
categories: v.array(v.object({ id: v.id("todos"), category: v.string() })),
},
handler: async (ctx, args) => {
for (const category of args.categories) {
await ctx.db.patch("todos", category.id, {
category: category.category,
});
}
},
});
async function categorizeTodos(
todos: Doc<"todos">[],
categories: string[],
): Promise<AiCategorizeResponse[]> {…}
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
export default defineSchema({
todos: defineTable({
text: v.string(),
category: v.optional(v.string()),
completed: v.boolean(),
}).index("by_completed", ["completed"]),
});
Get your app up and running in minutes
Start building
Convex logo
ProductSyncRealtimeAuthOpen sourceAI codingFAQMerchEnterprisePricing
DevelopersDocsBlogComponentsTemplatesConvex for StartupsConvex for Open SourceChampionsPodcastsLLMs.txt
CompanyAbout usBrandInvestorsBecome a partnerJobsNewsEventsSecurityLegal
SocialX (Twitter)DiscordYouTubeLumaLinkedInGitHub
A Trusted Solution
  • SOC 2 Type II Compliant
  • HIPAA Compliant
  • GDPR Verified
©2026 Convex, Inc.