Set Up Convex

Let’s add Convex to our project. There are three steps: installing the package, initializing a Convex project, and connecting the provider to our React app.

Install Convex

pnpm add convex

Initialize the Project

Run the Convex development command:

npx convex dev

The first time you run this, it:

  1. Asks you to log in. Convex uses your GitHub account. A browser window opens for authentication.
  2. Asks you to create a project. Choose “create a new project” and give it a name (e.g., kanban).
  3. Asks about deployment. Choose “cloud deployment”.
  4. Creates files. It generates a convex/ directory and a .env.local file with your deployment URL.

After setup, you will see a message like:

✔ Convex functions ready!

Leave npx convex dev running in the terminal. It watches for changes in your convex/ directory and automatically syncs them to the cloud, similar to how pnpm dev watches for changes in your React code.

What Was Created

The convex/ directory holds all your backend code:

convex/
├── _generated/         ← auto-generated, don't edit
│   ├── api.d.ts
│   ├── api.js
│   ├── dataModel.d.ts
│   ├── server.d.ts
│   └── server.js
├── tsconfig.json
└── README.md

The _generated/ folder contains typed helpers that Convex creates for you:

  • api: a typed object for calling your functions from the React client. As you add functions to the convex/ directory, they appear here automatically.
  • server: typed constructors like query and mutation that you will use to define your backend functions.
  • dataModel: TypeScript types generated from your schema (once you define one).

You never edit these files. They update automatically when you change your backend code.

The .env.local file contains the URL of your Convex deployment:

VITE_CONVEX_URL=https://your-deployment.convex.cloud

Vite makes any variable starting with VITE_ available in your client code via import.meta.env.

Add the Convex Provider

Just like TanStack Query needs a QueryClientProvider, Convex needs a ConvexProvider that establishes the connection to the backend. This provider maintains a persistent WebSocket connection to the Convex cloud.

Update src/main.tsx:

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { ConvexProvider, ConvexReactClient } from "convex/react";
import App from "./App";
import "./index.css";

const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string);

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <ConvexProvider client={convex}>
      <App />
    </ConvexProvider>
  </StrictMode>,
);

ConvexReactClient creates a client that connects to your backend via WebSocket. Wrapping the app in <ConvexProvider> makes this connection available to every component, so they can call queries and mutations.

The app still works exactly the same. We have not changed any data flow yet. In the next section, we will define a schema for the tasks table.

Checkpoint: Commit your progress.

git add .
git commit -m "kanban-02: Set up Convex with provider"
git push