452 lines
14 KiB
Markdown
452 lines
14 KiB
Markdown
---
|
|
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 '<existing dev command>'`. 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 <ConvexProvider client={convex}>...</ConvexProvider>;
|
|
}
|
|
|
|
// Good: created once at module scope
|
|
const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string);
|
|
function App() {
|
|
return <ConvexProvider client={convex}>...</ConvexProvider>;
|
|
}
|
|
```
|
|
|
|
#### 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(
|
|
<StrictMode>
|
|
<ConvexProvider client={convex}>
|
|
<App />
|
|
</ConvexProvider>
|
|
</StrictMode>,
|
|
);
|
|
```
|
|
|
|
#### 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 <ConvexProvider client={convex}>{children}</ConvexProvider>;
|
|
}
|
|
```
|
|
|
|
```tsx
|
|
// app/layout.tsx
|
|
import { ConvexClientProvider } from "./ConvexClientProvider";
|
|
|
|
export default function RootLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode;
|
|
}) {
|
|
return (
|
|
<html lang="en">
|
|
<body>
|
|
<ConvexClientProvider>{children}</ConvexClientProvider>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|
|
```
|
|
|
|
#### 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 (
|
|
<div>
|
|
<button onClick={() => create({ text: "New task" })}>Add</button>
|
|
{tasks?.map((t) => (
|
|
<div key={t._id}>{t.text}</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
```
|
|
|
|
## 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
|