create-convex-monorepo 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +306 -59
- package/assets/backend-better-auth/PROVENANCE.md +3 -0
- package/assets/backend-better-auth/convex/_generated/api.d.ts +57 -0
- package/assets/backend-better-auth/convex/_generated/api.js +23 -0
- package/assets/backend-better-auth/convex/_generated/dataModel.d.ts +60 -0
- package/assets/backend-better-auth/convex/_generated/server.d.ts +162 -0
- package/assets/backend-better-auth/convex/_generated/server.js +101 -0
- package/assets/backend-better-auth/convex/messages.ts +38 -0
- package/assets/backend-better-auth/convex/schema.ts +9 -0
- package/assets/backend-blank-better-auth/PROVENANCE.md +3 -0
- package/assets/backend-blank-better-auth/convex/_generated/api.d.ts +53 -0
- package/assets/backend-blank-better-auth/convex/_generated/api.js +23 -0
- package/assets/backend-blank-better-auth/convex/_generated/dataModel.d.ts +60 -0
- package/assets/backend-blank-better-auth/convex/_generated/server.d.ts +162 -0
- package/assets/backend-blank-better-auth/convex/_generated/server.js +101 -0
- package/assets/backend-blank-better-auth/convex/schema.ts +3 -0
- package/assets/backend-blank-convex-auth/PROVENANCE.md +3 -0
- package/assets/backend-blank-convex-auth/convex/_generated/api.d.ts +51 -0
- package/assets/backend-blank-convex-auth/convex/_generated/api.js +23 -0
- package/assets/backend-blank-convex-auth/convex/_generated/dataModel.d.ts +60 -0
- package/assets/backend-blank-convex-auth/convex/_generated/server.d.ts +162 -0
- package/assets/backend-blank-convex-auth/convex/_generated/server.js +101 -0
- package/assets/backend-blank-convex-auth/convex/schema.ts +4 -0
- package/assets/backend-convex-auth/PROVENANCE.md +3 -0
- package/assets/backend-convex-auth/convex/_generated/api.d.ts +55 -0
- package/assets/backend-convex-auth/convex/_generated/api.js +23 -0
- package/assets/backend-convex-auth/convex/_generated/dataModel.d.ts +60 -0
- package/assets/backend-convex-auth/convex/_generated/server.d.ts +162 -0
- package/assets/backend-convex-auth/convex/_generated/server.js +101 -0
- package/assets/backend-convex-auth/convex/messages.ts +38 -0
- package/assets/backend-convex-auth/convex/schema.ts +11 -0
- package/assets/setup/better-auth-env.mjs +187 -0
- package/assets/setup/convex-auth-keys.mjs +139 -0
- package/assets/setup/convex-auth-site.mjs +129 -0
- package/assets/setup/convex-setup.d.mts +9 -1
- package/assets/setup/convex-setup.mjs +64 -10
- package/dist/cli/index.js +3 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/create.d.ts +1 -1
- package/dist/commands/create.js +39 -7
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/entry.d.ts +1 -0
- package/dist/commands/entry.js +99 -0
- package/dist/commands/entry.js.map +1 -0
- package/dist/commands/workspace.d.ts +5 -3
- package/dist/commands/workspace.js +118 -38
- package/dist/commands/workspace.js.map +1 -1
- package/dist/generator/context.js +5 -2
- package/dist/generator/context.js.map +1 -1
- package/dist/generator/format.d.ts +9 -0
- package/dist/generator/format.js +61 -0
- package/dist/generator/format.js.map +1 -0
- package/dist/generator/index.js +7 -5
- package/dist/generator/index.js.map +1 -1
- package/dist/generator/options.d.ts +4 -1
- package/dist/generator/options.js +38 -5
- package/dist/generator/options.js.map +1 -1
- package/dist/generator/types.d.ts +8 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/auth/better-auth/controls.d.ts +1 -0
- package/dist/integrations/auth/better-auth/controls.js +67 -0
- package/dist/integrations/auth/better-auth/controls.js.map +1 -0
- package/dist/integrations/auth/better-auth/index.d.ts +2 -0
- package/dist/integrations/auth/better-auth/index.js +109 -0
- package/dist/integrations/auth/better-auth/index.js.map +1 -0
- package/dist/integrations/auth/better-auth/providers.d.ts +2 -0
- package/dist/integrations/auth/better-auth/providers.js +63 -0
- package/dist/integrations/auth/better-auth/providers.js.map +1 -0
- package/dist/integrations/auth/better-auth/setup.d.ts +2 -0
- package/dist/integrations/auth/better-auth/setup.js +37 -0
- package/dist/integrations/auth/better-auth/setup.js.map +1 -0
- package/dist/integrations/auth/clerk/index.js +15 -3
- package/dist/integrations/auth/clerk/index.js.map +1 -1
- package/dist/integrations/auth/convex-auth/controls.d.ts +2 -0
- package/dist/integrations/auth/convex-auth/controls.js +88 -0
- package/dist/integrations/auth/convex-auth/controls.js.map +1 -0
- package/dist/integrations/auth/convex-auth/index.d.ts +3 -0
- package/dist/integrations/auth/convex-auth/index.js +100 -0
- package/dist/integrations/auth/convex-auth/index.js.map +1 -0
- package/dist/integrations/auth/convex-auth/providers.d.ts +2 -0
- package/dist/integrations/auth/convex-auth/providers.js +36 -0
- package/dist/integrations/auth/convex-auth/providers.js.map +1 -0
- package/dist/integrations/auth/convex-auth/setup.d.ts +2 -0
- package/dist/integrations/auth/convex-auth/setup.js +76 -0
- package/dist/integrations/auth/convex-auth/setup.js.map +1 -0
- package/dist/integrations/auth/index.d.ts +2 -1
- package/dist/integrations/auth/index.js +22 -0
- package/dist/integrations/auth/index.js.map +1 -1
- package/dist/integrations/auth/none/index.js +16 -1
- package/dist/integrations/auth/none/index.js.map +1 -1
- package/dist/integrations/auth/shared.d.ts +7 -1
- package/dist/integrations/auth/shared.js +91 -6
- package/dist/integrations/auth/shared.js.map +1 -1
- package/dist/integrations/auth/workos/controls.d.ts +2 -0
- package/dist/integrations/auth/workos/controls.js +53 -0
- package/dist/integrations/auth/workos/controls.js.map +1 -0
- package/dist/integrations/auth/workos/index.d.ts +6 -0
- package/dist/integrations/auth/workos/index.js +104 -0
- package/dist/integrations/auth/workos/index.js.map +1 -0
- package/dist/integrations/auth/workos/providers.d.ts +3 -0
- package/dist/integrations/auth/workos/providers.js +53 -0
- package/dist/integrations/auth/workos/providers.js.map +1 -0
- package/dist/integrations/auth/workos/setup.d.ts +2 -0
- package/dist/integrations/auth/workos/setup.js +27 -0
- package/dist/integrations/auth/workos/setup.js.map +1 -0
- package/dist/package-manager/index.d.ts +7 -1
- package/dist/package-manager/index.js +20 -0
- package/dist/package-manager/index.js.map +1 -1
- package/dist/templates/apps/astro/index.d.ts +2 -0
- package/dist/templates/apps/astro/index.js +69 -0
- package/dist/templates/apps/astro/index.js.map +1 -0
- package/dist/templates/apps/index.js +8 -0
- package/dist/templates/apps/index.js.map +1 -1
- package/dist/templates/apps/nuxt/index.d.ts +2 -0
- package/dist/templates/apps/nuxt/index.js +123 -0
- package/dist/templates/apps/nuxt/index.js.map +1 -0
- package/dist/templates/apps/react-router/index.d.ts +2 -0
- package/dist/templates/apps/react-router/index.js +85 -0
- package/dist/templates/apps/react-router/index.js.map +1 -0
- package/dist/templates/apps/shared.d.ts +1 -1
- package/dist/templates/apps/shared.js +25 -5
- package/dist/templates/apps/shared.js.map +1 -1
- package/dist/templates/apps/sveltekit/index.d.ts +2 -0
- package/dist/templates/apps/sveltekit/index.js +155 -0
- package/dist/templates/apps/sveltekit/index.js.map +1 -0
- package/dist/templates/backend/index.js +4 -4
- package/dist/templates/backend/index.js.map +1 -1
- package/dist/templates/root/index.js +104 -41
- package/dist/templates/root/index.js.map +1 -1
- package/dist/templates/versions.d.ts +46 -0
- package/dist/templates/versions.js +46 -0
- package/dist/templates/versions.js.map +1 -1
- package/dist/workspace/add.d.ts +7 -2
- package/dist/workspace/add.js +745 -115
- package/dist/workspace/add.js.map +1 -1
- package/dist/workspace/doctor.js +326 -36
- package/dist/workspace/doctor.js.map +1 -1
- package/dist/workspace/env.js +1 -1
- package/dist/workspace/env.js.map +1 -1
- package/dist/workspace/planning.d.ts +11 -0
- package/dist/workspace/planning.js +70 -0
- package/dist/workspace/planning.js.map +1 -0
- package/dist/workspace/project.d.ts +6 -2
- package/dist/workspace/project.js +22 -5
- package/dist/workspace/project.js.map +1 -1
- package/dist/workspace/upgrade.d.ts +2 -0
- package/dist/workspace/upgrade.js +153 -0
- package/dist/workspace/upgrade.js.map +1 -1
- package/docs/adding-a-framework.md +30 -4
- package/docs/adding-an-auth-provider.md +23 -6
- package/docs/architecture.md +13 -6
- package/docs/research.md +148 -1
- package/docs/verification.md +182 -0
- package/package.json +11 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# create-convex-monorepo
|
|
2
2
|
|
|
3
|
-
A TypeScript CLI that generates pnpm
|
|
3
|
+
A TypeScript CLI that generates pnpm or bun workspaces. Turborepo runs multiple frontends sharing one typed Convex backend. Choose Next.js, Vite + React, TanStack Start, React Router v7, Expo, Astro + React island, SvelteKit, Nuxt, or a combination. React apps support optional Clerk, Convex Auth, WorkOS AuthKit, or Better Auth authentication on their supported frameworks. SvelteKit and Nuxt support auth `none` only.
|
|
4
4
|
|
|
5
5
|
The generator composes framework templates and auth adapters. It does not copy a single starter and delete unwanted pieces. Choose blank apps or a messages example. The example includes a query and mutation, plus compile-time assertions for the shared API's argument and return types.
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ Convex already generates an API from your backend functions. Sharing that API be
|
|
|
10
10
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
13
|
-
Requires Node.js 22.12 or newer and pnpm for the generated workspace.
|
|
13
|
+
Requires Node.js 22.12 or newer and pnpm or bun for the generated workspace.
|
|
14
14
|
|
|
15
15
|
```sh
|
|
16
16
|
pnpm create convex-monorepo@latest
|
|
@@ -22,60 +22,85 @@ Or use npx:
|
|
|
22
22
|
npx create-convex-monorepo@latest
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
Both commands run the same CLI. You can also install it globally with `npm install --global create-convex-monorepo` and run `create-convex-monorepo` directly. Running through npx does not change the generated workspace's package manager
|
|
25
|
+
Both commands run the same CLI. You can also install it globally with `npm install --global create-convex-monorepo` and run `create-convex-monorepo` directly. Running through npx does not change the generated workspace's package manager. The default is pnpm; select bun with `--package-manager bun` or the interactive prompt.
|
|
26
26
|
|
|
27
27
|
Contributors can run the checkout with `pnpm dev`; see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
28
28
|
|
|
29
29
|
## Manage an existing workspace
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
Run the same CLI from the workspace root or any subdirectory. No global or project installation is needed:
|
|
32
32
|
|
|
33
33
|
```sh
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
npx create-convex-monorepo@latest
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
With a terminal attached, it detects `convex-monorepo.json` and offers a menu to add an app, add a shared package, add authentication, check the workspace, sync frontend URLs, update dependencies, or check for updates. Without a terminal, it prints management help without changing files.
|
|
38
|
+
|
|
39
|
+
You can also run each command directly:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
npx create-convex-monorepo@latest add app admin --framework vite --example none --dry-run
|
|
43
|
+
npx create-convex-monorepo@latest add app admin --framework vite --example none --install
|
|
44
|
+
npx create-convex-monorepo@latest add app mobile --framework expo --no-install
|
|
45
|
+
npx create-convex-monorepo@latest add package shared --dry-run
|
|
46
|
+
npx create-convex-monorepo@latest add package shared --no-install
|
|
47
|
+
npx create-convex-monorepo@latest add auth clerk --dry-run
|
|
48
|
+
npx create-convex-monorepo@latest add auth clerk --install
|
|
49
|
+
npx create-convex-monorepo@latest add auth convex-auth --dry-run
|
|
50
|
+
npx create-convex-monorepo@latest add auth convex-auth --install
|
|
51
|
+
npx create-convex-monorepo@latest add auth better-auth --dry-run
|
|
52
|
+
npx create-convex-monorepo@latest add auth better-auth --install
|
|
53
|
+
npx create-convex-monorepo@latest add auth workos --dry-run
|
|
54
|
+
npx create-convex-monorepo@latest add auth workos --install
|
|
55
|
+
npx create-convex-monorepo@latest env sync --app mobile
|
|
56
|
+
npx create-convex-monorepo@latest doctor
|
|
57
|
+
npx create-convex-monorepo@latest upgrade --check
|
|
58
|
+
npx create-convex-monorepo@latest upgrade --dry-run
|
|
59
|
+
npx create-convex-monorepo@latest upgrade --install
|
|
36
60
|
```
|
|
37
61
|
|
|
38
|
-
|
|
62
|
+
The same commands work through pnpm:
|
|
39
63
|
|
|
40
64
|
```sh
|
|
41
|
-
pnpm
|
|
42
|
-
|
|
65
|
+
pnpm create convex-monorepo@latest add app admin --framework vite --no-install
|
|
66
|
+
pnpm create convex-monorepo@latest doctor
|
|
43
67
|
```
|
|
44
68
|
|
|
45
|
-
|
|
69
|
+
The separate `convex-monorepo` binary remains available for users who install the package locally or globally. For example, after `pnpm add -Dw create-convex-monorepo@latest`, run `pnpm exec convex-monorepo doctor`.
|
|
70
|
+
|
|
71
|
+
To explicitly generate a new project, use `create <project-name>`. This also lets you use a command name such as `doctor` as the project name:
|
|
46
72
|
|
|
47
73
|
```sh
|
|
48
|
-
|
|
49
|
-
pnpm exec convex-monorepo add app admin --framework vite --example none --install
|
|
50
|
-
pnpm exec convex-monorepo add app mobile --framework expo --no-install
|
|
51
|
-
pnpm exec convex-monorepo add auth clerk --dry-run
|
|
52
|
-
pnpm exec convex-monorepo add auth clerk --install
|
|
53
|
-
pnpm exec convex-monorepo env sync --app mobile
|
|
54
|
-
pnpm exec convex-monorepo doctor
|
|
55
|
-
pnpm exec convex-monorepo upgrade --check
|
|
74
|
+
npx create-convex-monorepo@latest create doctor --apps vite --no-install --no-git
|
|
56
75
|
```
|
|
57
76
|
|
|
58
|
-
| Command | Behavior
|
|
59
|
-
| ----------------- |
|
|
60
|
-
| `add app` | Creates an app using the existing backend and auth, updates root scripts and metadata, and links the public backend URL when configured.
|
|
61
|
-
| `add
|
|
62
|
-
| `
|
|
63
|
-
| `
|
|
64
|
-
| `
|
|
77
|
+
| Command | Behavior |
|
|
78
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
79
|
+
| `add app` | Creates an app using the existing backend and auth, updates root scripts and metadata, and links the public backend URL when configured. |
|
|
80
|
+
| `add package` | Creates a blank shared TypeScript package under `packages/<name>` and records it in metadata. |
|
|
81
|
+
| `add auth` | Adds Clerk, Convex Auth, WorkOS AuthKit, or Better Auth to generated app providers and the backend auth configuration. Customized files that need replacement cause a conflict. |
|
|
82
|
+
| `env sync` | Links only the public backend URL, using each framework's variable prefix. Supports `--app` and `--dry-run`. |
|
|
83
|
+
| `doctor` | Checks workspace configuration, installed dependencies, environment settings, and shared API types. Supports `--json`; errors exit with status 1. |
|
|
84
|
+
| `upgrade` | Updates existing exact dependency pins and the recorded package-manager version to the running CLI's tested baseline. Keeps newer pins and rejects non-exact customizations. |
|
|
85
|
+
| `upgrade --check` | Compares generator versions with npm's latest stable release and reports the running CLI's tested dependency baseline through `--json`. Makes no changes. |
|
|
65
86
|
|
|
66
|
-
The add commands support `--dry-run`, `--install`, `--no-install`, and `--yes`. Without prompts, provide the app name and framework
|
|
87
|
+
The `add app`, `add package`, `add auth`, and `upgrade` commands support `--dry-run`, `--install`, `--no-install`, and `--yes`. Without prompts, provide the app name and framework for `add app`, the package name for `add package`, or `clerk`, `convex-auth`, `workos`, or `better-auth` for `add auth`. Dependency installation defaults to off. `--yes` enables installation unless `--no-install` is set, and never overrides conflicts. A dry run shows file paths without printing environment values or installing dependencies.
|
|
67
88
|
|
|
68
|
-
Existing workspaces with metadata version 1, including projects created with 0.2.1, are supported. Preserve `convex-monorepo.json`; the CLI reads it rather than guessing which directories belong to your project. Per-app starter choices are recorded there when they differ from the original selection.
|
|
89
|
+
Existing pnpm workspaces with metadata version 1, including projects created with 0.2.1, are supported. Bun workspaces also use metadata version 1. Preserve `convex-monorepo.json`; the CLI reads it rather than guessing which directories belong to your project. Per-app starter choices are recorded there when they differ from the original selection. Shared packages added by the CLI are recorded in the optional `packages` list as `{ "name": "shared" }` entries.
|
|
69
90
|
|
|
70
91
|
### Changes and conflicts
|
|
71
92
|
|
|
72
|
-
Commands plan every file before applying changes. They reject unsafe paths, symlinks, existing app
|
|
93
|
+
Commands plan every file before applying changes. They reject unsafe paths, symlinks, existing app or package paths, conflicting scripts or dependencies, and customized auth files that would need replacement. App addition requires the generated `apps/*` and `packages/*` workspace layout and Turbo dev script. Adding a messages UI also requires the generated messages backend contract; use `--example none` with a customized backend. Adding SvelteKit also updates an unchanged older URL setup script and adds formatter ignores for its generated output; customized setup scripts cause a conflict. Adding Astro or Nuxt to an older workspace also updates its recognized setup helper, adds the framework's public environment prefix to Turbo settings, and ignores its generated output. Astro adds `PUBLIC_*` and `.astro/`; Nuxt adds `NUXT_PUBLIC_*`, `.nuxt/`, and `.output/`. A customized setup helper that cannot be upgraded causes a conflict before writes. Restore the generated helper, add the app, then reapply custom changes.
|
|
94
|
+
|
|
95
|
+
Package addition creates plain TypeScript source with shared lint and typecheck settings. Add `"@<scope>/<name>": "workspace:*"` to each consuming app's dependencies, then run `pnpm install`. Next configs are updated when they match the generated config apart from the `transpilePackages` string list, so repeated `add package` calls keep appending. A missing config or any other customization produces a note with the required manual edit. Other frameworks need no config change.
|
|
73
96
|
|
|
74
|
-
Auth addition supports `none` to Clerk. It preserves
|
|
97
|
+
Auth addition supports `none` to Clerk, Convex Auth, WorkOS AuthKit, or Better Auth. It preserves user functions, generated internals, unrelated package fields, and existing README content. Convex Auth adds `authTables` to a generated schema or a customized schema with a single `defineSchema` call taking an object literal. Other schema shapes need the two manual edits named in the conflict. A customized HTTP router needs a manual `auth.addHttpRoutes(http)` call. Follow the new `CLERK_SETUP.md`, `CONVEX_AUTH_SETUP.md`, `WORKOS_SETUP.md`, or `BETTER_AUTH_SETUP.md` for setup. For Convex Auth, run `pnpm install`, then `pnpm convex:auth-keys`; refresh generated types with `pnpm convex:dev` or `convex codegen`. Existing public messages do not acquire an owner automatically and will not appear in authenticated accounts. Review stored-data migration separately. Adding the configured provider again is a no-op; replacing an auth provider is not supported.
|
|
75
98
|
|
|
76
99
|
A workspace lock prevents two CLI edits from running together. Each planned file is checked again before writing. Failed edits roll back files that still contain this command's output; observed concurrent edits are preserved and reported. Filesystem checks are optimistic, so avoid editing affected files while a command is applying. A failed dependency installation leaves the applied files available for retry with `pnpm install`.
|
|
77
100
|
|
|
78
|
-
Doctor is read-only and uses an in-memory TypeScript probe. It does not run application scripts, start services, configure a deployment, validate a real Clerk session, or prove a native Expo build works. Missing installation or environment configuration is reported with suggested steps.
|
|
101
|
+
Doctor is read-only and uses an in-memory TypeScript probe. It does not run application scripts, start services, configure a deployment, validate a real Clerk session, or prove a native Expo build works. Missing installation or environment configuration is reported with suggested steps.
|
|
102
|
+
|
|
103
|
+
Upgrade updates matching dependency entries in root, app, and shared-package manifests and records the running CLI version in metadata. It never downgrades exact pins. Non-exact managed pins, such as `^` ranges, cause a conflict before any writes. User-added dependencies and unrelated package fields are preserved; missing tested dependencies are reported but not added. Manifests are rewritten from parsed JSON, so comments are not supported and integer values above 2^53 lose precision. Upgrade does not migrate template files or write the lockfile itself. Run `pnpm install` afterward, or use `--install`, to update the lockfile.
|
|
79
104
|
|
|
80
105
|
## Interactive usage
|
|
81
106
|
|
|
@@ -83,14 +108,15 @@ With a terminal attached, the CLI asks for missing choices:
|
|
|
83
108
|
|
|
84
109
|
```text
|
|
85
110
|
Project name? my-app
|
|
86
|
-
Package manager? pnpm
|
|
111
|
+
Package manager? pnpm / bun (default: pnpm)
|
|
87
112
|
Application framework? Next.js
|
|
88
113
|
Application name? web
|
|
89
114
|
Add another frontend? Yes
|
|
90
115
|
Application framework? Expo / React Native
|
|
91
116
|
Application name? mobile
|
|
92
117
|
Add another frontend? No
|
|
93
|
-
Authentication?
|
|
118
|
+
Authentication? Convex Auth (email + password)
|
|
119
|
+
OAuth providers? None
|
|
94
120
|
Starter content? Blank project
|
|
95
121
|
Initialize git? Yes
|
|
96
122
|
Initialize Convex and link frontend URLs? Yes
|
|
@@ -107,20 +133,43 @@ pnpm create convex-monorepo@latest my-app --apps web:next,admin:vite --no-instal
|
|
|
107
133
|
pnpm create convex-monorepo@latest my-app --apps app:tanstack-start,dashboard:next --auth none --package-manager pnpm --yes
|
|
108
134
|
```
|
|
109
135
|
|
|
110
|
-
| Option | Meaning
|
|
111
|
-
| ----------------------------------- |
|
|
112
|
-
| `--apps` | Comma-separated framework IDs or `name:framework` entries
|
|
113
|
-
| `--auth` | `none`, the default, or `
|
|
114
|
-
| `--
|
|
115
|
-
| `--
|
|
116
|
-
| `--
|
|
117
|
-
| `--
|
|
118
|
-
| `--
|
|
119
|
-
| `--
|
|
120
|
-
| `--
|
|
136
|
+
| Option | Meaning |
|
|
137
|
+
| ----------------------------------- | ----------------------------------------------------------------------- |
|
|
138
|
+
| `--apps` | Comma-separated framework IDs or `name:framework` entries |
|
|
139
|
+
| `--auth` | `none`, the default, `clerk`, `convex-auth`, `workos`, or `better-auth` |
|
|
140
|
+
| `--oauth` | Optional comma list `github,google`; requires `--auth convex-auth` |
|
|
141
|
+
| `--example` | `messages`, the default, or `none` for blank projects |
|
|
142
|
+
| `--package-manager` | `pnpm`, the default, or `bun`; npm and yarn are rejected |
|
|
143
|
+
| `--install`, `--no-install` | Enable or skip dependency installation |
|
|
144
|
+
| `--init-convex`, `--no-init-convex` | Initialize Convex and link URLs; enables installation |
|
|
145
|
+
| `--git`, `--no-git` | Enable or skip `git init`; no commit is created |
|
|
146
|
+
| `--yes`, `-y` | Skip prompts and accept defaults, including install and git |
|
|
147
|
+
| `--help`, `--version` | Show usage or the generator version |
|
|
121
148
|
|
|
122
149
|
Without a terminal, prompts are disabled and install/git default to off unless explicitly enabled or `--yes` is passed. Explicit negative flags override `--yes`. Convex initialization defaults to off when prompts are skipped, including with `--yes`; request it explicitly with `--init-convex`. That flag still lets Convex prompt for an account or deployment, and conflicts with `--no-install`. The default app is Next.js. Project and app names must be lowercase letters, digits, and hyphens, at most 100 characters, with no path separators or reserved device names.
|
|
123
150
|
|
|
151
|
+
## Bun workspaces
|
|
152
|
+
|
|
153
|
+
Select bun in the "Package manager?" prompt or pass the flag:
|
|
154
|
+
|
|
155
|
+
```sh
|
|
156
|
+
npx create-convex-monorepo@latest my-app --apps next,expo --package-manager bun --install --no-git
|
|
157
|
+
cd my-app
|
|
158
|
+
bun run convex:setup
|
|
159
|
+
bun run dev
|
|
160
|
+
bun run typecheck
|
|
161
|
+
bun run lint
|
|
162
|
+
bun run build
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
If installation was skipped, run `bun install` first. Use `bun run convex:link`, `bun run convex:dev`, for Convex Auth, `bun run convex:auth-keys`, and for Better Auth, `bun run convex:better-auth-env`. The pnpm script examples in this README use `bun run <script>` in bun workspaces. Run backend binaries from the root with `bun run --cwd packages/backend convex <command>`.
|
|
166
|
+
|
|
167
|
+
Bun workspaces put `apps/*` and `packages/*` in the root manifest's `workspaces` list and pin bun in `packageManager`. They keep Turborepo and `workspace:*` dependencies. Commit `bun.lock`; no `pnpm-workspace.yaml` is generated. Existing-workspace commands read the recorded manager, including when invoked through npx or pnpm. `--install` uses that manager, and upgrade updates its version pin. This does not migrate existing pnpm workspaces.
|
|
168
|
+
|
|
169
|
+
Keep Node.js 22.12+ installed for the CLI and framework tools. Bun's dependency lifecycle policy differs from pnpm's; the template trusts only esbuild, sharp, and unrs-resolver, matching the pnpm template's build allowlist. Review scripts before trusting additional dependencies. Expo keeps its default Metro configuration; JavaScript export does not verify native Xcode or Gradle builds. See [bun and Expo findings](docs/research.md#bun-workspaces).
|
|
170
|
+
|
|
171
|
+
Metadata stays at version 1. Older CLI releases that validate the manager as pnpm-only reject bun workspaces; use a CLI release with bun support to manage them.
|
|
172
|
+
|
|
124
173
|
## Blank projects
|
|
125
174
|
|
|
126
175
|
Choose **Blank project** in the starter-content prompt, or pass `--example none`:
|
|
@@ -129,22 +178,34 @@ Choose **Blank project** in the starter-content prompt, or pass `--example none`
|
|
|
129
178
|
pnpm create convex-monorepo@latest my-app --apps next,expo --example none --yes
|
|
130
179
|
```
|
|
131
180
|
|
|
132
|
-
Every selected app starts with a minimal page or screen showing its name. Convex providers, workspace dependencies, environment setup, and the selected auth integration remain configured. The backend has an empty schema and
|
|
181
|
+
Every selected app starts with a minimal page or screen showing its name. Convex providers, workspace dependencies, environment setup, and the selected auth integration remain configured. The backend has official generated types and an empty schema, except Convex Auth projects retain their auth tables and functions. Better Auth keeps its tables in the component and exposes the current-user query. There are no example tables, messages functions, access helpers, query/mutation screens, or demo-specific type-test files to remove.
|
|
133
182
|
|
|
134
|
-
Add your tables to `packages/backend/convex/schema.ts` and your functions beside it. Run `pnpm convex:dev` to generate their shared API references. With
|
|
183
|
+
Add your tables to `packages/backend/convex/schema.ts` and your functions beside it. Run `pnpm convex:dev` to generate their shared API references. With any auth provider, add server-side identity and authorization checks to your protected functions. The blank starter retains sign-in controls and the existing authenticated provider behavior.
|
|
135
184
|
|
|
136
185
|
The choice applies to the whole workspace. `--example messages` keeps the existing query/mutation demo and remains the default, including with `--yes`.
|
|
137
186
|
|
|
138
187
|
## Supported frameworks
|
|
139
188
|
|
|
140
|
-
| ID | Application
|
|
141
|
-
| ---------------- |
|
|
142
|
-
| `next` | Next.js App Router
|
|
143
|
-
| `vite` | Vite + React
|
|
144
|
-
| `tanstack-start` | TanStack Start with Vite
|
|
145
|
-
| `
|
|
189
|
+
| ID | Application | Public Convex variable | Convex data loading |
|
|
190
|
+
| ---------------- | ------------------------------------------------------------------- | ------------------------ | ------------------------------------------------------ |
|
|
191
|
+
| `next` | Next.js App Router | `NEXT_PUBLIC_CONVEX_URL` | Client React hooks |
|
|
192
|
+
| `vite` | Vite + React | `VITE_CONVEX_URL` | Client React hooks |
|
|
193
|
+
| `tanstack-start` | TanStack Start with Vite | `VITE_CONVEX_URL` | Client React hooks, no server prefetch |
|
|
194
|
+
| `react-router` | React Router v7 framework mode, SSR enabled | `VITE_CONVEX_URL` | Client React hooks, no server prefetch or data loaders |
|
|
195
|
+
| `expo` | Expo / React Native | `EXPO_PUBLIC_CONVEX_URL` | Client React hooks |
|
|
196
|
+
| `astro` | Astro + React island | `PUBLIC_CONVEX_URL` | Client React hooks in a client-only island |
|
|
197
|
+
| `sveltekit` | SvelteKit with Svelte 5 | `PUBLIC_CONVEX_URL` | Client Svelte queries, no server preloading |
|
|
198
|
+
| `nuxt` | Nuxt, auth `none` only; Node `^22.19.0 \|\| ^24.11.0 \|\| >=26.0.0` | `NUXT_PUBLIC_CONVEX_URL` | Client Vue composables inside `ClientOnly` |
|
|
146
199
|
|
|
147
|
-
|
|
200
|
+
Nuxt uses Vue and supports only `--auth none`, including workspaces that mix Nuxt, SvelteKit, and React apps. Adding Nuxt to an authenticated workspace or adding auth to a workspace containing Nuxt is rejected before files change.
|
|
201
|
+
|
|
202
|
+
Nuxt keeps SSR enabled, but its Convex plugin and messages component run only in the browser. `NUXT_PUBLIC_CONVEX_URL` maps to `runtimeConfig.public.convexUrl`. Dev, build, and preview read `.env.local`; production servers accept the variable at runtime. Typechecking runs `nuxt prepare`, then `vue-tsc --noEmit` against both `.nuxt/tsconfig.json` and `.nuxt/tsconfig.server.json` to check app and server code. Lint uses `eslint-plugin-vue` with the shared TypeScript rules.
|
|
203
|
+
|
|
204
|
+
SvelteKit currently supports only `--auth none`, for both starters. It can share a workspace with any of the React frameworks when auth is `none`. Adding SvelteKit to an authenticated workspace or adding auth to a workspace containing SvelteKit fails before files are written.
|
|
205
|
+
|
|
206
|
+
Astro generates a static page with a React island mounted through `client:only="react"`. Convex and auth run in the browser. Its `typecheck` script uses `astro check`; Clerk uses the official `@clerk/astro` integration and middleware. No SSR adapter is needed for the static page.
|
|
207
|
+
|
|
208
|
+
Versions are pinned in the templates. React Router follows the Vite framework scaffold with `app/root.tsx`, `app/routes.ts`, and `app/routes/home.tsx`. Its typecheck script generates route types before running TypeScript. Its root loader handles auth only; Convex queries and mutations use the shared client components. Expo's build command exports JavaScript, not native application binaries. See [research and upstream caveats](docs/research.md).
|
|
148
209
|
|
|
149
210
|
## Generated architecture
|
|
150
211
|
|
|
@@ -164,7 +225,7 @@ my-app/
|
|
|
164
225
|
│ ├── typescript-config/
|
|
165
226
|
│ └── eslint-config/
|
|
166
227
|
├── convex-monorepo.json
|
|
167
|
-
├── pnpm-workspace.yaml
|
|
228
|
+
├── pnpm-workspace.yaml # pnpm only
|
|
168
229
|
├── turbo.json
|
|
169
230
|
└── package.json
|
|
170
231
|
```
|
|
@@ -179,7 +240,7 @@ Use explicit names to choose folders and repeat a framework:
|
|
|
179
240
|
pnpm create convex-monorepo@latest acme --apps web:next,admin:next,mobile:expo --yes
|
|
180
241
|
```
|
|
181
242
|
|
|
182
|
-
Apps become `@acme/web`, `@acme/admin`, and `@acme/mobile`. All depend on `@acme/backend` through `workspace:*`. The generator assigns distinct web development ports.
|
|
243
|
+
Apps become `@acme/web`, `@acme/admin`, and `@acme/mobile`. All depend on `@acme/backend` through `workspace:*`. The generator assigns distinct web development ports. Use `npx create-convex-monorepo@latest add app` to add another frontend later.
|
|
183
244
|
|
|
184
245
|
## First run and development
|
|
185
246
|
|
|
@@ -203,7 +264,20 @@ pnpm lint
|
|
|
203
264
|
pnpm build
|
|
204
265
|
```
|
|
205
266
|
|
|
206
|
-
Complete setup in a normal terminal before starting Turbo. Stop a separately running backend watcher before `pnpm dev`, which starts its own.
|
|
267
|
+
Complete setup in a normal terminal before starting Turbo. Stop a separately running backend watcher before `pnpm dev` or `bun run dev`, which starts its own. SvelteKit reads `PUBLIC_CONVEX_URL` from `$env/static/public`, so set it before typechecking or building. Its root layout mounts the Svelte Convex provider; messages subscribe with `useQuery`.
|
|
268
|
+
|
|
269
|
+
Public environment values are embedded at build time; rebuild frontends when they change. Backend build checks types and does not deploy.
|
|
270
|
+
|
|
271
|
+
## Code formatting
|
|
272
|
+
|
|
273
|
+
Generated source and configuration files are formatted with Prettier before they are written, including when using `--no-install`. New workspaces include a pinned Prettier dependency and matching configuration:
|
|
274
|
+
|
|
275
|
+
```sh
|
|
276
|
+
pnpm format
|
|
277
|
+
pnpm format:check
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Svelte components use the pinned `prettier-plugin-svelte` formatter. Convex `_generated` files, TanStack's generated route tree, React Router's `.react-router` types, SvelteKit's generated files, build output, lockfiles, and environment files are excluded. Adding an app formats its new files; it does not reformat existing application code. Auth migration accepts formatting differences in older starters while still rejecting customized code that would be replaced.
|
|
207
281
|
|
|
208
282
|
## Convex backend sharing
|
|
209
283
|
|
|
@@ -218,7 +292,153 @@ Dynamic Convex declarations refer to backend source modules. Client TypeScript p
|
|
|
218
292
|
|
|
219
293
|
## Authentication
|
|
220
294
|
|
|
221
|
-
|
|
295
|
+
New projects accept `none`, `clerk`, `convex-auth`, or `better-auth` across the six React frameworks and both starters. SvelteKit and Nuxt support only `none`; the generator has no Svelte or Vue binding for Clerk, Convex Auth, WorkOS, or Better Auth. Existing no-auth workspaces without Nuxt or SvelteKit accept `add auth clerk`, `add auth convex-auth`, `add auth workos`, or `add auth better-auth`. All providers support `add app` for their supported frameworks. WorkOS AuthKit supports Next.js, Vite, and TanStack Start with both starters. Expo, Astro, React Router, SvelteKit, and Nuxt are rejected before writing files. Expo has no official React Native AuthKit SDK. The [official Astro SDK](https://github.com/workos/authkit-astro) requires a server adapter and on-demand rendering; this generator uses static Astro output.
|
|
296
|
+
React Router has an official SDK, but this generator has no binding for it yet.
|
|
297
|
+
|
|
298
|
+
`--auth convex-auth` and `add auth convex-auth` configure email and password sign-up/sign-in, sign-out, and per-user backend access. Web apps use the client ConvexAuthProvider; Expo persists tokens with expo-secure-store. No frontend public auth keys or password-flow redirect scheme are needed. Next.js, TanStack Start, and React Router do not configure server-side authentication or authenticated SSR. GitHub and Google OAuth are opt-in with `--oauth github,google`. Magic links, email verification, password reset, and MFA are outside this starter.
|
|
299
|
+
|
|
300
|
+
Run `pnpm convex:setup`, then `pnpm convex:auth-keys`. The key script generates an RSA 2048 key pair and sets `JWT_PRIVATE_KEY` and `JWKS` on the deployment through the installed Convex CLI. It never stores the key locally or prints either value. The initial push can finish before keys exist, but sign-in fails until they are configured. Run `pnpm convex:auth-keys --prod` to set a separate pair for production. `SITE_URL` is a deployment setting for redirects and is optional for this Password-only flow. The generated `.env.convex-auth.example` belongs to the backend package. See the [official manual setup](https://labs.convex.dev/auth/setup/manual).
|
|
301
|
+
|
|
302
|
+
### Optional GitHub and Google OAuth
|
|
303
|
+
|
|
304
|
+
Keep Password sign-in and add either or both providers:
|
|
305
|
+
|
|
306
|
+
```sh
|
|
307
|
+
pnpm create convex-monorepo@latest my-app --apps next,expo --auth convex-auth --oauth github,google
|
|
308
|
+
npx create-convex-monorepo@latest add auth convex-auth --oauth google --install
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
OAuth supports both package managers. The examples below use pnpm. For bun workspaces, use `bun install`, replace `pnpm <script>` with `bun run <script>`, and replace `pnpm --filter @my-app/backend exec convex` with `bun run --cwd packages/backend convex`. Generated setup instructions use the selected manager.
|
|
312
|
+
|
|
313
|
+
The interactive OAuth multiselect defaults to none. `--oauth` is valid only with Convex Auth; unknown providers fail before generation. Both starters and all six React frameworks support it, including the Astro React island. Nuxt and SvelteKit reject Convex Auth, including OAuth, before generation or workspace changes. Metadata version 1 records the selected providers in an optional `oauth` array. `add auth` accepts this flag only on a no-auth workspace. Adding OAuth to a workspace with authentication already configured requires the manual edits below.
|
|
314
|
+
|
|
315
|
+
For OAuth, `SITE_URL` is required on the Convex deployment. Generated OAuth workspaces include a helper that leaves signing keys unchanged:
|
|
316
|
+
|
|
317
|
+
```sh
|
|
318
|
+
pnpm convex:auth-site http://localhost:3000
|
|
319
|
+
pnpm convex:auth-site https://your-app.example --prod
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Set `AUTH_GITHUB_ID`, `AUTH_GITHUB_SECRET`, `AUTH_GOOGLE_ID`, and `AUTH_GOOGLE_SECRET` for the selected providers with `pnpm --filter @my-app/backend exec convex env set <name> <value>` or the Convex dashboard. These are deployment settings, never frontend public environment variables. The backend `.env.convex-auth.example` lists the selected settings.
|
|
323
|
+
|
|
324
|
+
Create the OAuth applications in GitHub's developer settings and Google's Cloud console. Register the callback for each selected provider:
|
|
325
|
+
|
|
326
|
+
| Provider | Callback URL |
|
|
327
|
+
| -------- | -------------------------------------------- |
|
|
328
|
+
| GitHub | `<CONVEX_SITE_URL>/api/auth/callback/github` |
|
|
329
|
+
| Google | `<CONVEX_SITE_URL>/api/auth/callback/google` |
|
|
330
|
+
|
|
331
|
+
`CONVEX_SITE_URL` is the deployment's HTTPS `.convex.site` URL. Use separate provider applications and credentials for development and production. Web buttons start `signIn('github')` or `signIn('google')`; successful sign-ins return to `SITE_URL`. Browser OAuth must start on the SITE_URL origin so the returning page can read its stored verifier. For additional web origins, change the web handler to `signIn(provider, { redirectTo: window.location.href })` and allow those origins in the backend redirect callback. Changing only the callback is insufficient.
|
|
332
|
+
|
|
333
|
+
Expo uses the scheme already defined in `app.json`, `ccm-<project>-<app>`, with return URL `ccm-<project>-<app>://auth`. Use `pnpm ios` or `pnpm android` in the app directory to create a development build. Expo Go cannot handle this custom scheme. The provider console uses the HTTPS Convex callback above, then Convex redirects to the app scheme. Register the scheme return URL in any native redirect allowlist required by the provider console. Do not replace the GitHub or Google web client's HTTPS callback with the app scheme.
|
|
334
|
+
|
|
335
|
+
The generated native handler uses `expo-linking` to create the return URL and `expo-web-browser` to open the URL returned by `signIn(provider, { redirectTo })`. It completes successful browser sessions with `signIn(provider, { code })`. The backend allows only the generated native return URLs and the configured web origin. Keep those URLs and the app scheme aligned if you rename an app. See [Convex Auth OAuth](https://labs.convex.dev/auth/config/oauth) and [Expo authentication](https://docs.expo.dev/guides/authentication/).
|
|
336
|
+
|
|
337
|
+
### Add OAuth to an existing Convex Auth workspace
|
|
338
|
+
|
|
339
|
+
This is a manual edit. In `packages/backend/convex/auth.ts`, retain Password and add the selected imports and array entries. These OAuth providers come from the existing pinned `@auth/core` dependency; `@convex-dev/auth@0.0.95` does not export GitHub or Google provider modules.
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
import { convexAuth } from '@convex-dev/auth/server';
|
|
343
|
+
import { Password } from '@convex-dev/auth/providers/Password';
|
|
344
|
+
import GitHub from '@auth/core/providers/github';
|
|
345
|
+
import Google from '@auth/core/providers/google';
|
|
346
|
+
|
|
347
|
+
export const { auth, signIn, signOut, store, isAuthenticated } = convexAuth({
|
|
348
|
+
providers: [Password, GitHub, Google],
|
|
349
|
+
});
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Remove the import and array entry for any provider you do not want. In each web app's `src/auth-controls.tsx`, add these buttons inside the signed-out form, beside the Password controls:
|
|
353
|
+
|
|
354
|
+
```tsx
|
|
355
|
+
<button type="button" disabled={pending} onClick={() => {
|
|
356
|
+
void signIn('github').catch(() => setError('Could not sign in. Try again.'));
|
|
357
|
+
}}>Sign in with GitHub</button>
|
|
358
|
+
<button type="button" disabled={pending} onClick={() => {
|
|
359
|
+
void signIn('google').catch(() => setError('Could not sign in. Try again.'));
|
|
360
|
+
}}>Sign in with Google</button>
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
For Expo, add exact dependencies `"expo-web-browser": "57.0.3"` and `"expo-linking": "57.0.10"` to the app's `package.json`, then run `pnpm install`. Confirm the `expo.scheme` value in `app.json`. Add these imports to `src/auth-controls.tsx`:
|
|
364
|
+
|
|
365
|
+
```ts
|
|
366
|
+
import * as Linking from 'expo-linking';
|
|
367
|
+
import { openAuthSessionAsync } from 'expo-web-browser';
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Add this handler inside `AuthControls`, replacing `ccm-my-app-mobile` with the actual scheme:
|
|
371
|
+
|
|
372
|
+
```tsx
|
|
373
|
+
async function authenticateOAuth(provider: 'github' | 'google') {
|
|
374
|
+
if (pending) return;
|
|
375
|
+
setPending(true);
|
|
376
|
+
setError(null);
|
|
377
|
+
try {
|
|
378
|
+
const redirectTo = Linking.createURL('auth', {
|
|
379
|
+
scheme: 'ccm-my-app-mobile',
|
|
380
|
+
});
|
|
381
|
+
const { redirect } = await signIn(provider, { redirectTo });
|
|
382
|
+
if (!redirect) throw new Error('Missing sign-in URL.');
|
|
383
|
+
const result = await openAuthSessionAsync(redirect.toString(), redirectTo);
|
|
384
|
+
if (result.type === 'success') {
|
|
385
|
+
const code = new URL(result.url).searchParams.get('code');
|
|
386
|
+
if (!code) throw new Error('Missing sign-in code.');
|
|
387
|
+
await signIn(provider, { code });
|
|
388
|
+
}
|
|
389
|
+
} catch (cause) {
|
|
390
|
+
setError(cause instanceof Error ? cause.message : 'Could not sign in.');
|
|
391
|
+
} finally {
|
|
392
|
+
setPending(false);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Add native buttons inside the signed-out `View`:
|
|
398
|
+
|
|
399
|
+
```tsx
|
|
400
|
+
<Button title="Sign in with GitHub" disabled={pending} onPress={() => { void authenticateOAuth('github'); }} />
|
|
401
|
+
<Button title="Sign in with Google" disabled={pending} onPress={() => { void authenticateOAuth('google'); }} />
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
For a shared web and native backend, add this `callbacks` property beside `providers` in `convexAuth`. Replace the example native URL with the actual scheme, adding each native app's exact return URL to the array:
|
|
405
|
+
|
|
406
|
+
```ts
|
|
407
|
+
callbacks: {
|
|
408
|
+
async redirect({ redirectTo }) {
|
|
409
|
+
const siteUrl = process.env.SITE_URL;
|
|
410
|
+
if (!siteUrl) throw new Error('Set SITE_URL on the Convex deployment.');
|
|
411
|
+
if (['ccm-my-app-mobile://auth'].includes(redirectTo)) return redirectTo;
|
|
412
|
+
const target = new URL(redirectTo, siteUrl);
|
|
413
|
+
if (target.origin === new URL(siteUrl).origin && ['http:', 'https:'].includes(target.protocol)) {
|
|
414
|
+
return target.toString();
|
|
415
|
+
}
|
|
416
|
+
throw new Error('Invalid OAuth redirect destination.');
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
To enable OAuth from multiple web frontends, pass `{ redirectTo: window.location.href }` as the second argument to each web `signIn` call. Replace the callback's same-origin condition above with an explicit list of trusted origins, using your actual addresses:
|
|
422
|
+
|
|
423
|
+
```ts
|
|
424
|
+
const allowedOrigins = [new URL(siteUrl).origin, 'http://localhost:3001'];
|
|
425
|
+
if (
|
|
426
|
+
allowedOrigins.includes(target.origin) &&
|
|
427
|
+
['http:', 'https:'].includes(target.protocol)
|
|
428
|
+
) {
|
|
429
|
+
return target.toString();
|
|
430
|
+
}
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
Use production origins in production. Do not allow arbitrary URLs supplied by the client.
|
|
434
|
+
|
|
435
|
+
Configure credentials and callbacks as above. Set `SITE_URL` with `pnpm --filter @my-app/backend exec convex env set SITE_URL http://localhost:3000`, or use the scheme return URL for a mobile-only workspace. Add `"oauth": ["github", "google"]` to `convex-monorepo.json`, omitting unselected providers. Add `# SITE_URL is required for OAuth` and the selected `AUTH_*` variable names to `packages/backend/.env.convex-auth.example`. Run `pnpm convex:dev` to push the auth configuration, then rebuild the frontends and native development client. The backend module set is unchanged, so no codegen asset edits are needed.
|
|
436
|
+
|
|
437
|
+
Convex Auth message owners are `users` table IDs returned by `getAuthUserId`. Clerk owners are `tokenIdentifier` values. WorkOS owners are `identity.subject` values from `ctx.auth.getUserIdentity()`. Switching providers changes these keys and needs a data migration; the CLI does not replace auth providers.
|
|
438
|
+
|
|
439
|
+
`--auth workos` and `add auth workos` configure hosted AuthKit sign-in, SDK token refresh, sign-out, and Convex identity validation. The blank starter keeps the providers and sign-in controls. Append each app's `.env.workos.example` to `.env.local` and follow the generated README's WorkOS setup section, or `WORKOS_SETUP.md` after adding auth. The client ID uses each framework's public prefix. Next.js and TanStack Start also need its unprefixed server SDK value, plus server-only `WORKOS_API_KEY` and `WORKOS_COOKIE_PASSWORD`. Vite receives no server secrets. See [WorkOS research and configuration constraints](docs/research.md#workos-authkit).
|
|
440
|
+
|
|
441
|
+
`--auth clerk` adds SDK-specific bindings, a Convex auth configuration, and provider wiring. The messages example also includes backend identity checks and an owner index that keeps messages private. With `--auth none`, that example is a public message board. Blank projects omit the messages example; Convex Auth retains its auth tables and functions. Add authorization checks when writing protected functions. UI visibility alone is not authorization.
|
|
222
442
|
|
|
223
443
|
Use one Clerk application across the frontends. Configure Clerk's Convex integration and a JWT template named `convex`. Set `CLERK_JWT_ISSUER_DOMAIN` on the Convex deployment:
|
|
224
444
|
|
|
@@ -228,7 +448,34 @@ pnpm --filter @my-app/backend exec convex env set CLERK_JWT_ISSUER_DOMAIN https:
|
|
|
228
448
|
|
|
229
449
|
On a fresh deployment, first run `pnpm convex:setup` to select it. If the push reports a missing issuer, set that value and rerun setup. Repeat the configuration for production.
|
|
230
450
|
|
|
231
|
-
Append the variables from each app's `.env.clerk.example` to its `.env.local`, alongside the Convex URL. Publishable keys belong in the appropriate public variables. Next.js and
|
|
451
|
+
Append the variables from each app's `.env.clerk.example` to its `.env.local`, alongside the Convex URL. Publishable keys belong in the appropriate public variables. Next.js, Start, and React Router use a server-only `CLERK_SECRET_KEY`; Vite and Expo must never receive that secret. React Router uses `@clerk/react-router`, `clerkMiddleware`, and `rootAuthLoader`, with `v8_middleware` enabled. Its provider receives the root loader's session data and connects Convex through `ConvexProviderWithClerk`. For production, set `VITE_CLERK_PUBLISHABLE_KEY` at build time and both Clerk keys in the server runtime environment; `react-router-serve` does not load `.env.local` automatically. See [Convex's Clerk guide](https://docs.convex.dev/auth/clerk) and [Clerk's React Router setup](https://clerk.com/docs/react-router/getting-started/quickstart).
|
|
452
|
+
|
|
453
|
+
## Better Auth setup
|
|
454
|
+
|
|
455
|
+
Astro uses Better Auth inside its React island with `PUBLIC_CONVEX_URL` and `PUBLIC_CONVEX_SITE_URL`. React Router uses client authentication. Both support messages and blank starters. `--oauth` is only supported with Convex Auth.
|
|
456
|
+
|
|
457
|
+
`--auth better-auth` uses the official `@convex-dev/better-auth` component for email and password sign-up, sign-in, and sign-out on Next.js, Vite, TanStack Start, React Router, Expo, and Astro. Both starters include loading and error states. Next.js, TanStack Start, and React Router use client authentication. Social providers, magic links, email verification, and authenticated SSR are not configured.
|
|
458
|
+
|
|
459
|
+
Both package managers are supported. The examples below use pnpm; for bun workspaces, replace `pnpm <script>` with `bun run <script>`. Generated setup instructions use the selected manager.
|
|
460
|
+
|
|
461
|
+
Run `pnpm convex:setup` to select a deployment. If its first push requests auth configuration, set the deployment variables below and rerun setup. From the generated workspace root, configure your primary web origin and any additional frontend origins or native schemes:
|
|
462
|
+
|
|
463
|
+
```sh
|
|
464
|
+
pnpm convex:better-auth-env --site-url http://localhost:3000 --trusted-origins http://localhost:3001,ccm-my-app-mobile://
|
|
465
|
+
pnpm convex:better-auth-env --site-url https://example.com --trusted-origins https://admin.example.com,ccm-my-app-mobile:// --prod
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Use the actual scheme from the Expo app's `app.json`. For Expo-only development, use its web origin for `SITE_URL` and include its native scheme in the trusted origins. Use a cloud deployment for physical devices and a development build for your custom scheme.
|
|
469
|
+
|
|
470
|
+
The script generates `BETTER_AUTH_SECRET` in memory and sets it, `SITE_URL`, and `BETTER_AUTH_TRUSTED_ORIGINS` through the installed Convex CLI. It does not store or print the secret. Run the production command separately for production. Re-running rotates the secret, which can invalidate existing sessions. Convex supplies the backend's `CONVEX_SITE_URL`.
|
|
471
|
+
|
|
472
|
+
Set the public HTTP endpoint in every app's `.env.local`: `NEXT_PUBLIC_CONVEX_SITE_URL` for Next.js, `VITE_CONVEX_SITE_URL` for Vite, TanStack Start, and React Router, `PUBLIC_CONVEX_SITE_URL` for Astro, and `EXPO_PUBLIC_CONVEX_SITE_URL` for Expo. Use your deployment's HTTP URL, normally ending in `.convex.site`. Keep the existing public `CONVEX_URL` setting, normally ending in `.convex.cloud`. `convex:link` and `env sync` copy only `CONVEX_URL`; enter the site URL yourself. Never put `BETTER_AUTH_SECRET` in frontend files.
|
|
473
|
+
|
|
474
|
+
Better Auth stores its tables inside the component. Message ownership uses the Better Auth user ID returned by `authComponent.getAuthUser(ctx)`. Blank projects keep an empty application schema and the auth query. Expo uses `@better-auth/expo` with SecureStore on native platforms and the cross-domain client on web.
|
|
475
|
+
|
|
476
|
+
`add auth better-auth` writes `BETTER_AUTH_SETUP.md` and preserves your schema and generated internals. A missing `convex/convex.config.ts` is created. An existing component config or HTTP router that needs integration produces a conflict with the exact manual edit. After installation and configuration, run `pnpm convex:dev` to refresh component types. Provider replacement and stored-data migration remain manual.
|
|
477
|
+
|
|
478
|
+
See the [official React guide](https://labs.convex.dev/better-auth/framework-guides/react), [Expo guide](https://labs.convex.dev/better-auth/framework-guides/expo), and [email/password documentation](https://www.better-auth.com/docs/authentication/email-password).
|
|
232
479
|
|
|
233
480
|
## Expo notes
|
|
234
481
|
|
|
@@ -242,7 +489,7 @@ Typechecking and Metro export checks do not establish that real OAuth, device pe
|
|
|
242
489
|
|
|
243
490
|
- **Destination already exists:** choose a new or empty directory. The CLI refuses non-empty directories and symlinks. Template failures remove staging output; install/git/Convex setup failures preserve the completed project and print a retry command.
|
|
244
491
|
- **Missing URL screen:** run `pnpm convex:setup`, or `pnpm convex:link` if the backend is already configured, then restart development.
|
|
245
|
-
- **Authentication never connects:** check the `convex` JWT template and deployment issuer
|
|
492
|
+
- **Authentication never connects:** for Better Auth, check deployment `BETTER_AUTH_SECRET`, `SITE_URL`, trusted origins, and each frontend's public `CONVEX_SITE_URL`. For Convex Auth, check deployment signing keys and the generated auth modules. For Clerk, check the `convex` JWT template and deployment issuer, and use the same Clerk application across frontends.
|
|
246
493
|
- **Missing API types:** keep both generated JavaScript and declarations, run the backend watcher, and verify matching Convex versions. Do not fix this by casting the API.
|
|
247
494
|
- **Missing Start route tree:** run that app's `routes:generate` script. Its typecheck script runs route generation automatically.
|
|
248
495
|
- **Metro resolution after dependency changes:** run `pnpm --filter @my-app/mobile exec expo start --clear`. Check SDK-compatible dependency versions before changing resolver settings.
|
|
@@ -255,7 +502,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md), [adding a framework](docs/adding-a-frame
|
|
|
255
502
|
|
|
256
503
|
## Roadmap
|
|
257
504
|
|
|
258
|
-
|
|
505
|
+
Next candidates are Convex Auth installation in existing workspaces, reviewed upgrade migrations, and more package-manager adapters. `upgrade` updates dependency pins; template migrations remain manual.
|
|
259
506
|
|
|
260
507
|
MIT licensed. See [LICENSE](LICENSE).
|
|
261
508
|
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
Generated files under convex/\_generated were produced unchanged by convex@1.45.0 using CONVEX_AGENT_MODE=anonymous pnpm exec convex dev --once on 2026-09-18, after pnpm install in a temporary generated workspace. Dynamic JS/declaration output. Auth dependencies: @convex-dev/better-auth@0.12.5, better-auth@1.6.15 and @better-auth/expo@1.6.15. Input modules: convex.config.ts, schema.ts, auth.ts, http.ts, messages.ts, access.ts. auth.config.ts configures the issuer and is excluded from the generated function API. No internal codegen entry point was called. Run normal convex dev after changing backend modules.
|
|
2
|
+
|
|
3
|
+
Convex SDK source is Apache-2.0 licensed: https://github.com/get-convex/convex-js/blob/main/LICENSE.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/**
|
|
3
|
+
* Generated `api` utility.
|
|
4
|
+
*
|
|
5
|
+
* THIS CODE IS AUTOMATICALLY GENERATED.
|
|
6
|
+
*
|
|
7
|
+
* To regenerate, run `npx convex dev`.
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type * as access from "../access.js";
|
|
12
|
+
import type * as auth from "../auth.js";
|
|
13
|
+
import type * as http from "../http.js";
|
|
14
|
+
import type * as messages from "../messages.js";
|
|
15
|
+
|
|
16
|
+
import type {
|
|
17
|
+
ApiFromModules,
|
|
18
|
+
FilterApi,
|
|
19
|
+
FunctionReference,
|
|
20
|
+
} from "convex/server";
|
|
21
|
+
|
|
22
|
+
declare const fullApi: ApiFromModules<{
|
|
23
|
+
access: typeof access;
|
|
24
|
+
auth: typeof auth;
|
|
25
|
+
http: typeof http;
|
|
26
|
+
messages: typeof messages;
|
|
27
|
+
}>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* A utility for referencing Convex functions in your app's public API.
|
|
31
|
+
*
|
|
32
|
+
* Usage:
|
|
33
|
+
* ```js
|
|
34
|
+
* const myFunctionReference = api.myModule.myFunction;
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare const api: FilterApi<
|
|
38
|
+
typeof fullApi,
|
|
39
|
+
FunctionReference<any, "public">
|
|
40
|
+
>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A utility for referencing Convex functions in your app's internal API.
|
|
44
|
+
*
|
|
45
|
+
* Usage:
|
|
46
|
+
* ```js
|
|
47
|
+
* const myFunctionReference = internal.myModule.myFunction;
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare const internal: FilterApi<
|
|
51
|
+
typeof fullApi,
|
|
52
|
+
FunctionReference<any, "internal">
|
|
53
|
+
>;
|
|
54
|
+
|
|
55
|
+
export declare const components: {
|
|
56
|
+
betterAuth: import("@convex-dev/better-auth/_generated/component.js").ComponentApi<"betterAuth">;
|
|
57
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/**
|
|
3
|
+
* Generated `api` utility.
|
|
4
|
+
*
|
|
5
|
+
* THIS CODE IS AUTOMATICALLY GENERATED.
|
|
6
|
+
*
|
|
7
|
+
* To regenerate, run `npx convex dev`.
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { anyApi, componentsGeneric } from "convex/server";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A utility for referencing Convex functions in your app's API.
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* ```js
|
|
18
|
+
* const myFunctionReference = api.myModule.myFunction;
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export const api = anyApi;
|
|
22
|
+
export const internal = anyApi;
|
|
23
|
+
export const components = componentsGeneric();
|