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