{"id":16794,"library":"convex","title":"Convex Client and Backend SDK","description":"Convex is a comprehensive backend application platform offering a real-time database, serverless functions (queries, mutations, actions), and client libraries for JavaScript/TypeScript, with strong support for React. The current stable version is 1.36.0, with frequent precompiled releases indicating rapid development and continuous improvements. A key differentiator is its real-time reactivity, where client-side `useQuery` hooks automatically update whenever the underlying database data changes, eliminating manual subscription management. It provides end-to-end type safety, optional schema definitions, and a TypeScript-first approach for both backend function definitions and client-side consumption. The platform includes SDKs for defining backend logic, integrating with React, and handling authentication with providers like Auth0 and Clerk. Convex aims to simplify full-stack development by unifying the database and backend logic within a single reactive environment.","status":"active","version":"1.36.0","language":"javascript","source_language":"en","source_url":"https://github.com/get-convex/convex-backend","tags":["javascript","convex","database","react","state","serverless","typescript"],"install":[{"cmd":"npm install convex","lang":"bash","label":"npm"},{"cmd":"yarn add convex","lang":"bash","label":"yarn"},{"cmd":"pnpm add convex","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Optional peer dependency for Auth0 authentication integration.","package":"@auth0/auth0-react","optional":true},{"reason":"Optional peer dependency for Clerk authentication integration.","package":"@clerk/clerk-react","optional":true},{"reason":"Optional peer dependency for Clerk authentication integration.","package":"@clerk/react","optional":true},{"reason":"Required for using the React client library and hooks.","package":"react","optional":false}],"imports":[{"note":"The Convex client for React applications. Typically instantiated once and passed to `ConvexProvider`.","wrong":"const ConvexReactClient = require('convex/react');","symbol":"ConvexReactClient","correct":"import { ConvexReactClient } from 'convex/react';"},{"note":"React hook for fetching real-time data from Convex queries. Requires `api` object from `_generated/api`.","wrong":"import useQuery from 'convex/react';","symbol":"useQuery","correct":"import { useQuery } from 'convex/react';"},{"note":"Used in Convex backend files (e.g., `convex/myFunctions.ts`) to define read-only database functions.","wrong":"import { query } from 'convex/react';","symbol":"query","correct":"import { query } from 'convex/server';"},{"note":"Used in Convex backend files to define write operations to the database. These run as transactions.","wrong":"import { mutation } from 'convex';","symbol":"mutation","correct":"import { mutation } from 'convex/server';"},{"note":"Validator object for defining schema and function arguments. Renamed from `s` in `convex/schema` since v0.13.0.","wrong":"import { s } from 'convex/schema';","symbol":"v","correct":"import { v } from 'convex/values';"},{"note":"Generated client-side API object for calling Convex backend functions. Path is relative to your client code.","symbol":"api","correct":"import { api } from '../convex/_generated/api';"}],"quickstart":{"code":"import React from 'react';\nimport { ConvexReactClient, ConvexProvider, useQuery } from 'convex/react';\nimport { api } from '../convex/_generated/api'; // Adjust path as needed\n\n// Initialize the Convex client\nconst convexUrl = process.env.VITE_CONVEX_URL ?? 'https://your-convex-url.convex.cloud'; // Replace with your actual URL or env var\nconst convex = new ConvexReactClient(convexUrl);\n\n// Backend function definition (e.g., in convex/tasks.ts)\n/*\n  import { query } from './_generated/server';\n  import { v } from 'convex/values';\n\n  export const getTasks = query({\n    args: { status: v.optional(v.string()) },\n    handler: async (ctx, args) => {\n      return await ctx.db.query('tasks')\n        .filter(q => args.status ? q.eq(q.field('status'), args.status) : true)\n        .collect();\n    },\n  });\n*/\n\ninterface Task {\n  _id: string;\n  text: string;\n  status: 'todo' | 'done';\n}\n\nfunction TaskList() {\n  // Fetch tasks in real-time. The component re-renders when data changes.\n  const tasks = useQuery(api.tasks.getTasks, { status: 'todo' });\n\n  if (tasks === undefined) {\n    return <div>Loading tasks...</div>;\n  }\n\n  if (tasks.length === 0) {\n    return <div>No tasks to display.</div>;\n  }\n\n  return (\n    <div>\n      <h1>Todo List</h1>\n      <ul>\n        {tasks.map((task: Task) => (\n          <li key={task._id}>{task.text}</li>\n        ))}\n      </ul>\n    </div>\n  );\n}\n\nexport default function App() {\n  return (\n    <ConvexProvider client={convex}>\n      <TaskList />\n    </ConvexProvider>\n  );\n}\n","lang":"typescript","description":"This quickstart demonstrates how to set up the Convex React client, connect to a Convex backend, and display real-time data fetched using the `useQuery` hook within a React component. It assumes a basic backend query `getTasks` is defined."},"warnings":[{"fix":"Update backend functions to accept a single object for arguments. Migrate schema definitions to use `import { v } from 'convex/values;'`. Review client-side API calls for `ConvexReactClient` and `ConvexHttpClient`.","message":"Convex function arguments changed from multiple positional arguments to a single arguments object. Additionally, the schema builder `s` moved from `convex/schema` to `v` in `convex/values`, and several client APIs (`ConvexReactClient`, `ConvexHttpClient`) were updated for consistency.","severity":"breaking","affected_versions":">=0.13.0"},{"fix":"Update database interaction calls in your backend functions to explicitly include the table name as the first argument. Automatic migration tools (ESLint rule, codemod) are available.","message":"The `ctx.db.get`, `patch`, `replace`, and `delete` functions now require the table name as the first argument, e.g., `ctx.db.get(\"tableName\", id)`. While previous syntax is still supported, it will be deprecated.","severity":"breaking","affected_versions":">=1.31.0"},{"fix":"Ensure your development and deployment environments are using Node.js 20 or later to avoid future compatibility issues and take advantage of new features.","message":"Node.js 18 support is being deprecated, with new projects defaulting to Node.js 20. Existing Node.js 18 projects will be automatically migrated to Node.js 20 by October 22, 2025.","severity":"deprecated","affected_versions":">=1.26.0"},{"fix":"Wrap components containing authenticated `useQuery` calls with Convex's `Authenticated` component or explicitly handle `null` results from the query on the client-side, potentially rendering a loading state or fallback UI.","message":"When using `useQuery` within React components, `ctx.auth.getUserIdentity()` can initially return `null` if the Convex client has not yet fully authenticated, even if the user is logged in.","severity":"gotcha","affected_versions":">=0.13.0"},{"fix":"For conditional data fetching, pass the special string `'skip'` as the arguments to `useQuery` when the query should not run, for example: `useQuery(api.myFunc, condition ? { arg: 'value' } : 'skip');`","message":"React Hooks cannot be called conditionally. Using `useQuery` inside an `if` statement or conditional block will lead to runtime errors.","severity":"gotcha","affected_versions":"all"},{"fix":"Refactor your import structure to break circular dependencies. Often, this involves moving common validators or table definitions into a separate file that does not import back from `schema.ts`.","message":"Circular imports in your Convex backend files, especially involving `schema.ts`, can lead to 'Undefined validator' errors at runtime.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Create a `.env` file in your project root with `VITE_CONVEX_URL=https://your-convex-url.convex.cloud` (or `CONVEX_URL` for Node.js environments) and restart your development server.","cause":"The environment variable for the Convex deployment URL is missing or incorrectly named.","error":"Error: VITE_CONVEX_URL is not defined"},{"fix":"Ensure the user is authenticated before calling queries that rely on `ctx.auth.getUserIdentity()`. Use Convex's `Authenticated` React component or handle the `null` identity gracefully within your client-side component, showing a loading or unauthenticated state.","cause":"The client-side authentication process has not completed by the time the `useQuery` hook attempts to fetch data, or the user is not signed in.","error":"ctx.auth.getUserIdentity() returns null in a query"},{"fix":"Run `npx convex dev` (or `npx convex codegen` if not running `dev`) to regenerate the TypeScript types. Ensure your `convex/` directory is properly set up.","cause":"The TypeScript types for your Convex backend functions (located in `convex/_generated/api.d.ts`) are out of sync with your latest backend code.","error":"Type errors in api imports"},{"fix":"Refactor mutations to read less data, use more specific indexed queries, or reduce concurrent writes to the same document. For high-contention scenarios, rethink the data model to spread writes across more documents.","cause":"A Convex mutation failed to commit because the underlying data it read changed due to another concurrent mutation. This leads to retries and can indicate contention on specific documents.","error":"Write conflict: Optimistic concurrency control"}],"ecosystem":"npm","meta_description":null}