docs: add Convex integration (#4785)

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Bereket Engida <86073083+Bekacru@users.noreply.github.com>
Co-authored-by: TheUntraceable <73362400+TheUntraceable@users.noreply.github.com>
This commit is contained in:
Maxwell
2025-09-21 15:30:14 +10:00
committed by Alex Yang
parent f62675e8bd
commit d586e18f87
3 changed files with 375 additions and 0 deletions

View File

@@ -561,4 +561,27 @@ export const Icons = {
/> />
</svg> </svg>
), ),
convex: (props?: SVGProps<any>) => (
<svg
width="1.2em"
height="1.2em"
viewBox="15 15 160 160"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M108.092 130.021C126.258 128.003 143.385 118.323 152.815 102.167C148.349 142.128 104.653 167.385 68.9858 151.878C65.6992 150.453 62.8702 148.082 60.9288 145.034C52.9134 132.448 50.2786 116.433 54.0644 101.899C64.881 120.567 86.8748 132.01 108.092 130.021Z"
fill="currentColor"
></path>
<path
d="M53.4012 90.1735C46.0375 107.19 45.7186 127.114 54.7463 143.51C22.9759 119.608 23.3226 68.4578 54.358 44.7949C57.2286 42.6078 60.64 41.3096 64.2178 41.1121C78.9312 40.336 93.8804 46.0225 104.364 56.6193C83.0637 56.8309 62.318 70.4756 53.4012 90.1735Z"
fill="currentColor"
></path>
<path
d="M114.637 61.8552C103.89 46.8701 87.0686 36.6684 68.6387 36.358C104.264 20.1876 148.085 46.4045 152.856 85.1654C153.3 88.7635 152.717 92.4322 151.122 95.6775C144.466 109.195 132.124 119.679 117.702 123.559C128.269 103.96 126.965 80.0151 114.637 61.8552Z"
fill="currentColor"
></path>
</svg>
),
}; };

View File

@@ -1391,6 +1391,11 @@ C0.7,239.6,62.1,0.5,62.2,0.4c0,0,54,13.8,119.9,30.8S302.1,62,302.2,62c0.2,0,0.2,
icon: Icons.nestJS, icon: Icons.nestJS,
href: "/docs/integrations/nestjs", href: "/docs/integrations/nestjs",
}, },
{
title: "Convex",
icon: Icons.convex,
href: "/docs/integrations/convex",
},
{ {
group: true, group: true,
title: "Mobile & Desktop", title: "Mobile & Desktop",

View File

@@ -0,0 +1,347 @@
---
title: Convex Integration
description: Integrate Better Auth with Convex.
---
<Callout>
This documentation comes from the [Convex documentation](https://convex-better-auth.netlify.app/),
for more information, please refer to their documentation.
</Callout>
## Prerequisites
<Steps>
<Step>
### Create a Convex project
To use Convex + Better Auth, you'll first need a [Convex](https://www.convex.dev/) project.
If you don't have one, run the following command to get started.
```package-install
npm create convex@latest
```
Check out the [Convex docs](https://docs.convex.dev/home) to learn more about Convex.
</Step>
<Step>
### Run `convex dev`
Running the CLI during setup will initialize your Convex deployment
if it doesn't already exist, and keeps generated types current through the process. Keep it running.
```package-install
npx convex dev
```
</Step>
</Steps>
## Installation of Convex + Better Auth
The following documentation assumes you're using Next.js.
If you're not using Next.js, please refer to the [installation guide by Convex](https://convex-better-auth.netlify.app/#select-your-framework).
<Callout>
For a complete example, check out Convex + Better Auth example with Next.js in this [Github repository](https://github.com/get-convex/better-auth/tree/main/examples/next).
</Callout>
### Installation
<Steps>
<Step>
#### Install packages
Install the component, a pinned version of Better Auth, and ensure the latest version of Convex.
<Callout>
This component requires Convex `1.25.0` or later.
</Callout>
```package-install
npm install better-auth@1.3.8 --save-exact
npm install convex@latest @convex-dev/better-auth
```
</Step>
<Step>
#### Register the component
Register the Better Auth component in your Convex project.
```ts title="convex/convex.config.ts"
import { defineApp } from "convex/server";
import betterAuth from "@convex-dev/better-auth/convex.config";
const app = defineApp();
app.use(betterAuth);
export default app;
```
</Step>
<Step>
#### Add Convex auth config
Add a `convex/auth.config.ts` file to configure Better Auth as an authentication provider.
```ts title="convex/auth.config.ts"
export default {
providers: [
{
domain: process.env.CONVEX_SITE_URL,
applicationID: "convex",
},
],
};
```
</Step>
<Step>
#### Set environment variables
Generate a secret for encryption and generating hashes. Use the command below if you have openssl installed,
or use the button to generate a random value instead. Or generate your own however you like.
```package-install
npx convex env set BETTER_AUTH_SECRET=$(openssl rand -base64 32)
```
Add your site URL to your Convex deployment.
```package-install
npx convex env set SITE_URL http://localhost:3000
```
Add environment variables to the `.env.local` file created by `npx convex dev`.
It will be picked up by your framework dev server.
```shell title=".env.local" tab="Cloud"
# Deployment used by \`npx convex dev\`
CONVEX_DEPLOYMENT=dev:adjective-animal-123 # team: team-name, project: project-name
NEXT_PUBLIC_CONVEX_URL=https://adjective-animal-123.convex.cloud
# Same as NEXT_PUBLIC_CONVEX_URL but ends in .site // [!code ++]
NEXT_PUBLIC_CONVEX_SITE_URL=https://adjective-animal-123.convex.site # [!code ++]
# Your local site URL // [!code ++]
SITE_URL=http://localhost:3000 # [!code ++]
```
```shell title=".env.local" tab="Self hosted"
# Deployment used by \`npx convex dev\`
CONVEX_DEPLOYMENT=dev:adjective-animal-123 # team: team-name, project: project-name
NEXT_PUBLIC_CONVEX_URL=http://127.0.0.1:3210
# Will generally be one number higher than NEXT_PUBLIC_CONVEX_URL,
# so if your convex url is :3212, your site url will be :3213
NEXT_PUBLIC_CONVEX_SITE_URL=http://127.0.0.1:3211 # [!code ++]
# Your local site URL // [!code ++]
SITE_URL=http://localhost:3000 # [!code ++]
```
</Step>
<Step>
### Create a Better Auth instance
Create a Better Auth instance and initialize the component.
<Callout>Some TypeScript errors will show until you save the file.</Callout>
```ts title="convex/auth.ts"
import { createClient, type GenericCtx } from "@convex-dev/better-auth";
import { convex } from "@convex-dev/better-auth/plugins";
import { components } from "./_generated/api";
import { DataModel } from "./_generated/dataModel";
import { query } from "./_generated/server";
import { betterAuth } from "better-auth";
const siteUrl = process.env.SITE_URL!;
// The component client has methods needed for integrating Convex with Better Auth,
// as well as helper methods for general use.
export const authComponent = createClient<DataModel>(components.betterAuth);
export const createAuth = (
ctx: GenericCtx<DataModel>,
{ optionsOnly } = { optionsOnly: false },
) => {
return betterAuth({
// disable logging when createAuth is called just to generate options.
// this is not required, but there's a lot of noise in logs without it.
logger: {
disabled: optionsOnly,
},
baseURL: siteUrl,
database: authComponent.adapter(ctx),
// Configure simple, non-verified email/password to get started
emailAndPassword: {
enabled: true,
requireEmailVerification: false,
},
plugins: [
// The Convex plugin is required for Convex compatibility
convex(),
],
});
};
// Example function for getting the current user
// Feel free to edit, omit, etc.
export const getCurrentUser = query({
args: {},
handler: async (ctx) => {
return authComponent.getAuthUser(ctx);
},
});
```
</Step>
<Step>
### Create a Better Auth client instance
Create a Better Auth client instance for interacting with the Better Auth server from your client.
```ts title="src/lib/auth-client.ts"
import { createAuthClient } from "better-auth/react";
import { convexClient } from "@convex-dev/better-auth/client/plugins";
export const authClient = createAuthClient({
plugins: [convexClient()],
});
```
</Step>
<Step>
### Mount handlers
Register Better Auth route handlers on your Convex deployment.
```ts title="convex/http.ts"
import { httpRouter } from "convex/server";
import { authComponent, createAuth } from "./auth";
const http = httpRouter();
authComponent.registerRoutes(http, createAuth);
export default http;
```
Set up route handlers to proxy auth requests from your framework server to your Convex deployment.
```ts title="app/api/auth/[...all]/route.ts"
import { nextJsHandler } from "@convex-dev/better-auth/nextjs";
export const { GET, POST } = nextJsHandler();
```
</Step>
<Step>
### Set up Convex client provider
Wrap your app with the `ConvexBetterAuthProvider` component.
```ts title="app/ConvexClientProvider.tsx"
"use client";
import { ReactNode } from "react";
import { ConvexReactClient } from "convex/react";
import { authClient } from "@/lib/auth-client"; // [!code ++]
import { ConvexBetterAuthProvider } from "@convex-dev/better-auth/react"; // [!code ++]
const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!, {
// Optionally pause queries until the user is authenticated // [!code ++]
expectAuth: true, // [!code ++]
});
export function ConvexClientProvider({ children }: { children: ReactNode }) {
return (
<ConvexBetterAuthProvider client={convex} authClient={authClient}> // [!code ++]
{children}
</ConvexBetterAuthProvider> // [!code ++]
);
}
```
</Step>
</Steps>
### You're done!
You're now ready to start using Better Auth with Convex.
## Usage
### Using Better Auth from the server
To use Better Auth's [server
methods](https://www.better-auth.com/docs/concepts/api) in server rendering,
server functions, or any other Next.js server code, use Convex functions
and call the function from your server code.
First, a token helper for calling Convex functions from your server code.
```ts title="src/lib/auth-server.ts"
import { createAuth } from "convex/auth";
import { getToken as getTokenNextjs } from "@convex-dev/better-auth/nextjs";
export const getToken = () => {
return getTokenNextjs(createAuth);
};
```
Here's an example Convex function that uses Better Auth's server methods, and
a server action that calls the Convex function.
```ts title="convex/users.ts"
import { mutation } from "./_generated/server";
import { v } from "convex/values";
import { createAuth, authComponent } from "./auth";
export const updateUserPassword = mutation({
args: {
currentPassword: v.string(),
newPassword: v.string(),
},
handler: async (ctx, args) => {
await createAuth(ctx).api.changePassword({
body: {
currentPassword: args.currentPassword,
newPassword: args.newPassword,
},
headers: await authComponent.getHeaders(ctx),
});
},
});
```
```ts title="app/actions.ts"
"use server";
import { fetchMutation } from "convex/nextjs";
import { api } from "../convex/_generated/api";
import { getToken } from "../lib/auth-server";
// Authenticated mutation via server function
export async function updatePassword({
currentPassword,
newPassword,
}: {
currentPassword: string;
newPassword: string;
}) {
const token = await getToken();
await fetchMutation(
api.users.updatePassword,
{ currentPassword, newPassword },
{ token }
);
}
```
<Callout>
This documentation comes from the [Convex documentation](https://convex-better-auth.netlify.app/),
for more information, please refer to their documentation.
</Callout>