---
title: Quickstart
description: Get convex-auth running in a new Convex app in 10 minutes.
sidebar:
  order: 3
---

This guide assumes you already installed `convex-auth` and set `JWT_PRIVATE_KEY`, `JWKS`, `CONVEX_SITE_URL`, and `EMAIL_FROM_ADDRESS`. If not, start with [`Installation`](/convex-auth/installation).

At the end you will have email/password and Google/GitHub/Discord OAuth sign-in working in a React (Vite) app. Building with a different framework? Each has its own guide: [Next.js](/convex-auth/nextjs), [TanStack Start](/convex-auth/tanstack-start), [Hono](/convex-auth/hono), or [React Native / Expo](/convex-auth/react-native).

## Project layout

When you are done, your project will look like this:

- convex/
  - auth.config.ts
    - registers `convex-auth` as the auth provider
  - convex.config.ts
    - mounts the `convexAuth` component
  - auth.ts
    - configures `convexAuth({...})` and re-exports actions
  - http.ts
    - mounts `/api/auth/*` routes
- src/
  - main.tsx
    - wraps the app with `ConvexAuthClientProvider`
  - SignIn.tsx
    - calls `useAuthActions`

## Steps

1. **Register the auth provider**

    `convex/auth.config.ts` tells Convex that `convex-auth` is your auth provider:

    ```ts convex/auth.config.ts
    import { createConvexAuthProvider } from "@vortex-api/convex-auth/convex";

    export default {
      providers: [createConvexAuthProvider()],
    };
    ```

2. **Mount the component**

    `convex/convex.config.ts` mounts the `convex-auth` component and wires the key env vars:

    ```ts convex/convex.config.ts
    import { defineApp } from "convex/server";
    import { v } from "convex/values";
    import auth from "@vortex-api/convex-auth/convex.config";

    const app = defineApp({
      env: {
        JWT_PRIVATE_KEY: v.string(),
        JWKS: v.string(),
      },
    });

    app.use(auth, {
      env: {
        JWT_PRIVATE_KEY: app.env.JWT_PRIVATE_KEY,
        JWKS: app.env.JWKS,
      },
    });

    export default app;
    ```

3. **Configure auth in convex/auth.ts**

    Choose which providers are enabled and how they behave:

    ```ts convex/auth.ts
    import { components } from "./_generated/api";
    import { convexAuth, type EmailDraft } from "@vortex-api/convex-auth/convex";

    const siteUrl = process.env.CONVEX_SITE_URL?.replace(/\/$/, "");

    export const auth = convexAuth({
      component: components.convexAuth,
      emailAndPassword: {
        enabled: true,
        email: {
          from: process.env.EMAIL_FROM_ADDRESS ?? "auth@example.com",
          appOrigin: siteUrl,
          sendEmail: async (draft: EmailDraft) => {
            // production: call Resend/Postmark/SES
            console.log("Email draft", draft);
            return "email-id";
          },
          sendOnSignUp: true,
          sendOnSignIn: false,
        },
      },
      oauth: {
        github: {
          clientId: process.env.GITHUB_CLIENT_ID ?? "",
          clientSecret: process.env.GITHUB_CLIENT_SECRET ?? "",
        },
        google: {
          clientId: process.env.GOOGLE_CLIENT_ID ?? "",
          clientSecret: process.env.GOOGLE_CLIENT_SECRET ?? "",
        },
        discord: {
          clientId: process.env.DISCORD_CLIENT_ID ?? "",
          clientSecret: process.env.DISCORD_CLIENT_SECRET ?? "",
        },
      },
    });

    export const {
      signUp,
      signIn,
      signOut,
      updateSession,
      sendEmailVerification,
      verifyEmail,
      sendPasswordReset,
      resetPassword,
      verifyPassword,
      twoFactorEnable,
      twoFactorVerifyTOTP,
      twoFactorVerifyBackupCode,
      twoFactorDisable,
      twoFactorGenerateBackupCodes,
    } = auth;
    ```

4. **Wire HTTP routes**

    `convex/http.ts` exposes the OAuth redirect/callback, email verification, and password reset routes:

    ```ts convex/http.ts
    import { httpRouter } from "convex/server";
    import { auth } from "./auth";

    const http = httpRouter();
    auth.addHttpRoutes(http);

    export default http;
    ```

5. **Wrap the React app**

    `src/main.tsx` wraps `ConvexAuthClientProvider` inside `ConvexProvider` — the auth provider calls `useConvex()`, so the Convex client context must be above it:

    ```tsx src/main.tsx
    import { ConvexReactClient, ConvexProvider } from "convex/react";
    import { ConvexAuthClientProvider } from "@vortex-api/convex-auth/react";
    import { api } from "../convex/_generated/api";
    import App from "./App";

    const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL);

    function Root() {
      return (
        <ConvexProvider client={convex}>
          <ConvexAuthClientProvider actions={api.auth}>
            <App />
          </ConvexAuthClientProvider>
        </ConvexProvider>
      );
    }

    export default Root;
    ```

6. **Sign in from a component**

    ```tsx src/SignIn.tsx
    import { useAuthActions } from "@vortex-api/convex-auth/react";

    export function SignIn() {
      const { signIn, isLoading, isAuthenticated } = useAuthActions();

      async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
        event.preventDefault();
        const formData = new FormData(event.currentTarget);
        await signIn({
          email: formData.get("email") as string,
          password: formData.get("password") as string,
        });
      }

      if (isAuthenticated) {
        return <p>Already signed in.</p>;
      }

      return (
        <form onSubmit={handleSubmit}>
          <input name="email" type="email" required />
          <input name="password" type="password" required />
          <button type="submit" disabled={isLoading}>
            {isLoading ? "Signing in..." : "Sign in"}
          </button>
        </form>
      );
    }
    ```

7. **Verify and deploy**

    ```bash
    pnpm dlx @vortex-api/convex-auth check
    pnpm dlx @vortex-api/convex-auth preflight
    pnpm dlx convex deploy
    ```

    > **Tip**
    >
    > `check` validates that your `convex/` files do not accidentally import internal exports. `preflight` verifies environment variables and the component mount.

    Email verification and password reset are one-click via the `/api/auth/verify-email` and `/api/auth/reset-password/:token` HTTP routes. In production, `sendEmail` should call Resend, Postmark, SES, or any other email service.

## Next steps

- Look up every option in [`Configuration`](/convex-auth/configuration).
- Read the [`React`](/convex-auth/react) guide for all hooks.
- See the [Hono guide](/convex-auth/hono) for a working Hono server deployment.
