--- name: convex-quickstart description: Creates or adds Convex to an app. Use for new Convex projects, npm create convex@latest, frontend setup, env vars, or the first npx convex dev run. --- # Convex Quickstart Set up a working Convex project as fast as possible. ## When to Use - Starting a brand new project with Convex - Adding Convex to an existing React, Next.js, Vue, Svelte, or other app - Scaffolding a Convex app for prototyping ## When Not to Use - The project already has Convex installed and `convex/` exists - just start building - You only need to add auth to an existing Convex app - use the `convex-setup-auth` skill ## Workflow 1. Determine the starting point: new project or existing app 2. If new project, pick a template and scaffold with `npm create convex@latest` 3. If existing app, install `convex` and wire up the provider 4. Run `npx convex dev --once` to provision a local anonymous deployment, push the current `convex/` code, typecheck it, and regenerate types — all in one shot, exiting cleanly. The output tells the agent whether the schema and functions are valid. 5. Ask the user (or, for cloud agents, start in the background) `npm run dev` — Convex templates wire the watcher and the frontend into a single command. If the project has no combined dev script, use `npx convex dev` for the watcher and run the frontend separately. 6. Verify the setup works ## Path 1: New Project (Recommended) Use the official scaffolding tool. It creates a complete project with the frontend framework, Convex backend, and all config wired together. ### Pick a template | Template | Stack | | -------------------------- | ----------------------------------------- | | `react-vite-shadcn` | React + Vite + Tailwind + shadcn/ui | | `nextjs-shadcn` | Next.js App Router + Tailwind + shadcn/ui | | `react-vite-clerk-shadcn` | React + Vite + Clerk auth + shadcn/ui | | `nextjs-clerk` | Next.js + Clerk auth | | `nextjs-convexauth-shadcn` | Next.js + Convex Auth + shadcn/ui | | `nextjs-lucia-shadcn` | Next.js + Lucia auth + shadcn/ui | | `bare` | Convex backend only, no frontend | If the user has not specified a preference, default to `react-vite-shadcn` for simple apps or `nextjs-shadcn` for apps that need SSR or API routes. You can also use any GitHub repo as a template: ```bash npm create convex@latest my-app -- -t owner/repo npm create convex@latest my-app -- -t owner/repo#branch ``` ### Scaffold the project Always pass the project name and template flag to avoid interactive prompts: ```bash npm create convex@latest my-app -- -t react-vite-shadcn cd my-app npm install ``` The scaffolding tool creates files but does not run `npm install`, so you must run it yourself. To scaffold in the current directory (if it is empty): ```bash npm create convex@latest . -- -t react-vite-shadcn npm install ``` ### Provision the deployment and push code Run this yourself — it is a one-shot command that exits cleanly: ```bash npx convex dev --once ``` In a non-TTY environment (which is true for almost every agent run), this: - Provisions an _anonymous_ local Convex backend bound to `127.0.0.1`. No browser login, no team/project prompts. - Writes `CONVEX_DEPLOYMENT` and the framework's `*_CONVEX_URL` variables to `.env.local`. - Generates `convex/_generated/`. - Pushes the current `convex/` code to the deployment, **typechecks it**, and **validates the schema**. The agent reads this output to find out if the code it just wrote is broken. To be explicit (recommended), set `CONVEX_AGENT_MODE=anonymous` so the behavior does not depend on TTY detection: ```bash CONVEX_AGENT_MODE=anonymous npx convex dev --once ``` The deployment lives under `~/.convex/` and persists across runs. Re-running `convex dev --once` after editing `convex/` files is the agent's main feedback loop while the user-launched `npm run dev` is not in use. If the template's `package.json` defines a `predev` script (Convex Auth templates and similar do), `npm run predev` runs `convex init` plus any one-time setup (e.g. minting auth keys). Use it _in addition to_ `convex dev --once` when present — `predev` handles the one-time setup, `convex dev --once` pushes and validates the code. ### Start the dev loop In most Convex templates, `npm run dev` runs both the Convex watcher and the frontend dev server together (typically `convex dev --start 'vite --open'` or the Next.js equivalent). That is what the user should run. ```bash npm run dev ``` If the project does not have a combined `dev` script — e.g. the `bare` template, or an existing app where you haven't wired the frontend dev server into Convex's `--start` flag — the user can run the Convex watcher directly: ```bash npx convex dev ``` `npx convex dev` is the same long-running watcher `npm run dev` invokes under the hood; it just doesn't start the frontend. Use it when there is no frontend, or when the user prefers to run the frontend in a separate terminal. Either way, the agent should not invoke the watcher in the foreground because it does not exit. Two options: - **Local development (user is at the keyboard):** ask the user to run `npm run dev` (or `npx convex dev`) in a terminal. The deployment provisioned by `convex dev --once` above is already selected, so the watcher picks up immediately with no prompts. - **Cloud or headless agents:** start `npm run dev` (or `npx convex dev`) in the background. Vite apps serve on `http://localhost:5173`, Next.js on `http://localhost:3000`. ### What you get After scaffolding, the project structure looks like: ``` my-app/ convex/ # Backend functions and schema _generated/ # Auto-generated types (check this into git) schema.ts # Database schema (if template includes one) src/ # Frontend code (or app/ for Next.js) package.json .env.local # CONVEX_URL / VITE_CONVEX_URL / NEXT_PUBLIC_CONVEX_URL ``` The template already has: - `ConvexProvider` wired into the app root - Correct env var names for the framework - Tailwind and shadcn/ui ready (for shadcn templates) - Auth provider configured (for auth templates) Proceed to adding schema, functions, and UI. ## Path 2: Add Convex to an Existing App Use this when the user already has a frontend project and wants to add Convex as the backend. ### Install ```bash npm install convex ``` ### Provision and push Run `npx convex dev --once` yourself to provision a local anonymous deployment, write `.env.local`, generate types, push the current `convex/` code, and typecheck it. This is one-shot and exits: ```bash npx convex dev --once ``` The output tells you whether the schema and functions are valid — use it as your feedback loop while iterating. Then ask the user to start the watcher (or, for cloud/headless agents, start it in the background). You have two options: - **Wire Convex into `npm run dev`** — change the existing app's `dev` script to `convex dev --start ''`. That's the standard pattern Convex templates use; the user then runs a single `npm run dev` to start both. - **Run them separately** — leave `npm run dev` for the frontend and tell the user to run `npx convex dev` in a second terminal for the Convex watcher. See "Start the dev loop" above for why the agent should not run the watcher in the foreground. ### Wire up the provider The Convex client must wrap the app at the root. The setup varies by framework. Create the `ConvexReactClient` at module scope, not inside a component: ```tsx // Bad: re-creates the client on every render function App() { const convex = new ConvexReactClient( import.meta.env.VITE_CONVEX_URL as string, ); return ...; } // Good: created once at module scope const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string); function App() { return ...; } ``` #### React (Vite) ```tsx // src/main.tsx import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import { ConvexProvider, ConvexReactClient } from "convex/react"; import App from "./App"; const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string); createRoot(document.getElementById("root")!).render( , ); ``` #### Next.js (App Router) ```tsx // app/ConvexClientProvider.tsx "use client"; import { ConvexProvider, ConvexReactClient } from "convex/react"; import { ReactNode } from "react"; const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!); export function ConvexClientProvider({ children }: { children: ReactNode }) { return {children}; } ``` ```tsx // app/layout.tsx import { ConvexClientProvider } from "./ConvexClientProvider"; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( {children} ); } ``` #### Other frameworks For Vue, Svelte, React Native, TanStack Start, Remix, and others, follow the matching quickstart guide: - [Vue](https://docs.convex.dev/quickstart/vue) - [Svelte](https://docs.convex.dev/quickstart/svelte) - [React Native](https://docs.convex.dev/quickstart/react-native) - [TanStack Start](https://docs.convex.dev/quickstart/tanstack-start) - [Remix](https://docs.convex.dev/quickstart/remix) - [Node.js (no frontend)](https://docs.convex.dev/quickstart/nodejs) ### Environment variables The env var name depends on the framework: | Framework | Variable | | ------------ | ------------------------ | | Vite | `VITE_CONVEX_URL` | | Next.js | `NEXT_PUBLIC_CONVEX_URL` | | Remix | `CONVEX_URL` | | React Native | `EXPO_PUBLIC_CONVEX_URL` | `npx convex dev` writes the correct variable to `.env.local` automatically. ## Agent Mode `CONVEX_AGENT_MODE=anonymous` forces an unauthenticated local backend. It is already the implicit default for any non-TTY run of `npx convex init` or `npx convex dev`, but set it explicitly so the behavior does not depend on TTY detection: ```bash CONVEX_AGENT_MODE=anonymous npx convex dev --once ``` Use it for: - Any AI coding agent (local or cloud). - CI-like setup scripts. - Cases where the user is logged in but you do not want to touch their personal dev deployment. The resulting backend runs on `127.0.0.1` and is not associated with any team or project until the user later claims it via `npx convex login` and the `npx convex deployment` commands. ## Verify the Setup After setup, confirm everything is working: 1. `npx convex dev --once` exited without errors (deployment provisioned, code pushed, schema validated, typecheck clean) 2. The `convex/_generated/` directory exists and has `api.ts` and `server.ts` 3. `.env.local` contains a `CONVEX_DEPLOYMENT` value and the framework's `*_CONVEX_URL` variable 4. (If applicable) `npm run dev` (or `npx convex dev` for the watcher alone) is running without errors in another terminal or in the background ## Writing Your First Function Once the project is set up, create a schema and a query to verify the full loop works. `convex/schema.ts`: ```ts import { defineSchema, defineTable } from "convex/server"; import { v } from "convex/values"; export default defineSchema({ tasks: defineTable({ text: v.string(), completed: v.boolean(), }), }); ``` `convex/tasks.ts`: ```ts import { query, mutation } from "./_generated/server"; import { v } from "convex/values"; export const list = query({ args: {}, handler: async (ctx) => { return await ctx.db.query("tasks").collect(); }, }); export const create = mutation({ args: { text: v.string() }, handler: async (ctx, args) => { await ctx.db.insert("tasks", { text: args.text, completed: false }); }, }); ``` Use in a React component (adjust the import path based on your file location relative to `convex/`): ```tsx import { useQuery, useMutation } from "convex/react"; import { api } from "../convex/_generated/api"; function Tasks() { const tasks = useQuery(api.tasks.list); const create = useMutation(api.tasks.create); return (
{tasks?.map((t) => (
{t.text}
))}
); } ``` ## Development vs Production Always use `npx convex dev` during development. It runs against your personal dev deployment and syncs code on save. When ready to ship, deploy to production: ```bash npx convex deploy ``` This pushes to the production deployment, which is separate from dev. Do not use `deploy` during development. ## Next Steps - Add authentication: use the `convex-setup-auth` skill - Design your schema: see [Schema docs](https://docs.convex.dev/database/schemas) - Build components: use the `convex-create-component` skill - Plan a migration: use the `convex-migration-helper` skill - Add file storage: see [File Storage docs](https://docs.convex.dev/file-storage) - Set up cron jobs: see [Scheduling docs](https://docs.convex.dev/scheduling) ## Checklist - [ ] Determined starting point: new project or existing app - [ ] If new project: scaffolded with `npm create convex@latest` using appropriate template - [ ] If existing app: installed `convex` and wired up the provider - [ ] Agent ran `npx convex dev --once`: deployment provisioned, code pushed, typecheck clean - [ ] `npm run dev` (or `npx convex dev` for the watcher alone) is running — user-launched terminal, or background for cloud agents - [ ] `convex/_generated/` directory exists with types - [ ] `.env.local` has the deployment URL - [ ] Verified a basic query/mutation round-trip works