t-convex-nextjs-saas/convex/auth.ts
nxtkofi d6da6e6193 feat(email): add Resend integration with password reset and email verification
Install resend package. Add convex/lib/resend.ts for sending emails via Resend API. Update convex/auth.ts to enable requireEmailVerification, sendVerificationEmail, and sendResetPassword handlers.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-21 21:37:09 +02:00

67 lines
1.9 KiB
TypeScript

import { createClient, type GenericCtx } from '@convex-dev/better-auth';
import { convex } from '@convex-dev/better-auth/plugins';
import { betterAuth, type BetterAuthOptions } from 'better-auth/minimal';
import { haveIBeenPwned } from 'better-auth/plugins';
import { components } from './_generated/api';
import { DataModel } from './_generated/dataModel';
import { query } from './_generated/server';
import authConfig from './auth.config';
import authSchema from './betterAuth/schema';
import { sendEmail } from './lib/resend';
const siteUrl = process.env.SITE_URL!;
export const authComponent = createClient<DataModel, typeof authSchema>(
components.betterAuth,
{
local: {
schema: authSchema,
},
},
);
export const createAuthOptions = (
ctx: GenericCtx<DataModel>,
): BetterAuthOptions => {
return {
baseURL: siteUrl,
database: authComponent.adapter(ctx),
emailAndPassword: {
minPasswordLength: 8,
maxPasswordLength: 128,
autoSignIn: true,
enabled: true,
requireEmailVerification: true,
sendResetPassword: async ({ user, url }) => {
void sendEmail({
to: user.email,
subject: 'Reset your password',
html: `<p>Click <a href="${url}">here</a> to reset your password.</p>`,
});
},
},
emailVerification: {
sendOnSignUp: true,
sendVerificationEmail: async ({ user, url }) => {
void sendEmail({
to: user.email,
subject: 'Verify your email',
html: `<p>Click <a href="${url}">here</a> to verify your email address.</p>`,
});
},
},
plugins: [convex({ authConfig }), haveIBeenPwned()],
};
};
export const createAuth = (ctx: GenericCtx<DataModel>) => {
return betterAuth(createAuthOptions(ctx));
};
export const getCurrentUser = query({
args: {},
handler: async (ctx) => {
return authComponent.getAuthUser(ctx);
},
});