Skip to content

Conversation

AmanVarshney01
Copy link
Owner

@AmanVarshney01 AmanVarshney01 commented Sep 17, 2025

Summary by CodeRabbit

  • New Features

    • Better‑Auth support for Convex across the CLI: scaffolding, templates, frontend & backend auth routes, dashboard and auth UI (sign‑in/sign‑up/user menu), automatic installs and env hints.
  • Bug Fixes

    • Relaxed and clarified compatibility checks for Better‑Auth + Convex and payments with clearer error messages.
  • Chores

    • Removed Convex codegen from project creation.
  • Tests/Tooling

    • Dependency map updated (Convex bumped; Better‑Auth added); installer accepts custom overrides; env file comments supported.

Copy link
Contributor

coderabbitai bot commented Sep 17, 2025

Warning

Rate limit exceeded

@AmanVarshney01 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 3 minutes and 50 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between d64ac45 and 914c6cb.

📒 Files selected for processing (43)
  • apps/cli/src/constants.ts (1 hunks)
  • apps/cli/src/helpers/core/auth-setup.ts (1 hunks)
  • apps/cli/src/helpers/core/convex-codegen.ts (1 hunks)
  • apps/cli/src/helpers/core/create-project.ts (0 hunks)
  • apps/cli/src/helpers/core/env-setup.ts (5 hunks)
  • apps/cli/src/helpers/core/template-manager.ts (1 hunks)
  • apps/cli/src/prompts/auth.ts (1 hunks)
  • apps/cli/src/utils/add-package-deps.ts (3 hunks)
  • apps/cli/src/utils/compatibility-rules.ts (1 hunks)
  • apps/cli/src/utils/config-validation.ts (1 hunks)
  • apps/cli/templates/addons/biome/biome.json.hbs (2 hunks)
  • apps/cli/templates/addons/ultracite/biome.json.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.config.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/privateData.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/api/auth/[...all]/route.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/dashboard/page.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-in-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-up-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-client.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-server.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/lib/auth-client.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/routes/dashboard.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/user-menu.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-client.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/api/auth/$.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/dashboard.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/web/react/next/src/components/theme-provider.tsx.hbs (0 hunks)
  • apps/cli/templates/frontend/react/next/src/components/providers.tsx.hbs (2 hunks)
  • apps/cli/templates/frontend/react/tanstack-router/src/main.tsx.hbs (2 hunks)
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs (4 hunks)
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/index.tsx.hbs (2 hunks)
  • apps/cli/templates/frontend/react/web-base/src/components/header.tsx.hbs (2 hunks)
  • apps/web/src/app/(home)/new/_components/utils.ts (4 hunks)

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds Better‑Auth support for Convex across the CLI: dependency map updated, install and template wiring for Convex+better‑auth (backend + React frontends), prompt/validation/env updates, add-package-deps overrides, many new templates/UI components, and Convex codegen invocation removed from project creation.

Changes

Cohort / File(s) Summary
Dependency map
apps/cli/src/constants.ts
Bump convex ^1.25.4^1.27.0; add @convex-dev/better-auth: ^0.8.4. AvailableDependencies keys updated.
Auth install & templates
apps/cli/src/helpers/core/auth-setup.ts, apps/cli/src/helpers/core/template-manager.ts, apps/cli/templates/auth/better-auth/convex/...
Add better-auth branch: install [email protected] + @convex-dev/better-auth into backend and detected React clients; copy multiple Convex+better‑auth backend and web templates (auth, config, http, privateData, auth-client, routes, pages, components).
Frontend providers & integration
apps/cli/templates/frontend/..., apps/cli/templates/auth/better-auth/convex/web/react/...
Add/modify templates to use ConvexBetterAuthProvider, add authClient modules, pass { expectAuth: true } to Convex client for better‑auth, and add TanStack Start / Next server auth handlers.
New UI/routes components
.../tanstack-router/src/..., .../tanstack-start/src/..., .../next/src/...
Add dashboard routes, SignIn/SignUp forms, UserMenu, auth-client modules, server routes (/api/auth handlers / Next catch‑all), and Next dashboard page templates.
Prompts, validation & compatibility
apps/cli/src/prompts/auth.ts, apps/cli/src/utils/config-validation.ts, apps/cli/src/utils/compatibility-rules.ts
Detect React frontends to surface Better‑Auth option; extend unsupported frontends list (add native-nativewind, native-unistyles); conditionally forbid Better‑Auth with non‑React frontends under Convex; rename unused backend param → _backend in payments validator.
Env setup
apps/cli/src/helpers/core/env-setup.ts
Add optional comment on EnvVariable; generate client env keys (NEXT_PUBLIC_CONVEX_SITE_URL or VITE_CONVEX_SITE_URL) and append backend .env.local Convex env commands and SITE_URL when Convex + better‑auth and backend exists.
Package dependency helper
apps/cli/src/utils/add-package-deps.ts
Add customDependencies / customDevDependencies overrides to options; dependency resolution prefers custom maps before dependencyVersionMap; function signature updated.
Project creation / codegen
apps/cli/src/helpers/core/convex-codegen.ts, apps/cli/src/helpers/core/create-project.ts
Insert comment in convex-codegen.ts; remove automatic Convex codegen invocation from project creation flow.
Template cleanup & guards
apps/cli/templates/auth/better-auth/web/react/next/src/components/theme-provider.tsx.hbs, apps/cli/templates/frontend/react/web-base/src/components/header.tsx.hbs
Remove theme-provider template; tighten UserMenu import/render guards to skip importing/rendering UserMenu when backend === "convex".
Minor/no-op
apps/cli/src/helpers/core/convex-codegen.ts
Single comment added; no behavioral change.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Developer
  participant CLI as CLI scaffolder
  participant PM as Package Manager
  participant FS as File System

  Developer->>CLI: scaffold (backend=convex, auth=better-auth)
  CLI->>CLI: validate config (ensure React frontends)
  CLI->>PM: install [email protected] + @convex-dev/better-auth (backend + client)
  CLI->>FS: copy Convex better-auth backend templates
  CLI->>FS: copy React frontend templates (auth-client, routes, components)
  CLI->>FS: write env vars (.env.local / NEXT_PUBLIC_/VITE_)
  CLI-->>Developer: scaffold complete (convex codegen skipped)
Loading
sequenceDiagram
  autonumber
  participant Web as React App
  participant Provider as ConvexBetterAuthProvider
  participant AuthClient as authClient
  participant Backend as Convex Backend
  participant Plugin as @convex-dev/better-auth

  Web->>Provider: init(convex client, authClient)
  Web->>AuthClient: signIn / signUp / signOut
  AuthClient->>Backend: /api/auth/... requests
  Backend->>Plugin: createAuth / registerRoutes
  Plugin-->>Backend: session/token handling
  Backend-->>AuthClient: auth responses
  Web->>Backend: authenticated queries (with token)
  Backend-->>Web: auth-gated data
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

In my burrow I hopped through templates and yarn,
Better‑Auth seeds planted, Convex woke at dawn.
Env keys and routes, small carrots aligned,
Tokens find tunnels, users sign in and dine.
Hoppy deploy — the warren’s well-defined. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "feat(cli): add convex + better-auth" is concise and accurately summarizes the primary change—adding Convex backend support with Better‑Auth integration to the CLI (matching dependency, template, and helper updates in the changeset). It is specific, follows conventional commit style, and is sufficient for a reviewer scanning history to understand the main intent.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (14)
apps/cli/src/helpers/core/auth-setup.ts (1)

49-71: Collapse identical branches for better-auth install (reduce repetition)

The three branches install the same deps. Fold into one check to simplify.

Apply:

-            if (hasNextJs) {
-              await addPackageDependency({
-                dependencies: ["better-auth", "@convex-dev/better-auth"],
-                projectDir: clientDir,
-              });
-            } else if (hasTanStackStart) {
-              await addPackageDependency({
-                dependencies: ["better-auth", "@convex-dev/better-auth"],
-                projectDir: clientDir,
-              });
-            } else if (hasViteReactOther) {
-              await addPackageDependency({
-                dependencies: ["better-auth", "@convex-dev/better-auth"],
-                projectDir: clientDir,
-              });
-            }
+            const hasReactWeb =
+              hasNextJs || hasTanStackStart || hasViteReactOther;
+            if (hasReactWeb) {
+              await addPackageDependency({
+                dependencies: ["better-auth", "@convex-dev/better-auth"],
+                projectDir: clientDir,
+              });
+            }
apps/cli/templates/auth/better-auth/convex/backend/convex/auth.config.ts.hbs (1)

1-8: Fail fast if CONVEX_SITE_URL is missing

Avoid undefined domain at runtime; throw with a clear message.

Apply:

-export default {
-    providers: [
-        {
-            domain: process.env.CONVEX_SITE_URL,
-            applicationID: "convex",
-        },
-    ],
-};
+const domain = process.env.CONVEX_SITE_URL;
+if (!domain) {
+  throw new Error("Missing CONVEX_SITE_URL env var for Better-Auth provider");
+}
+export default {
+  providers: [{ domain, applicationID: "convex" }],
+};
apps/cli/src/utils/config-validation.ts (1)

238-253: Include offending frontends in the error for quicker feedback

Surface the actual incompatible selections.

Apply:

-    const hasUnsupportedFrontends = config.frontend?.some((f) =>
-      [
-        "nuxt",
-        "svelte",
-        "solid",
-        "native-nativewind",
-        "native-unistyles",
-      ].includes(f),
-    );
-
-    if (hasUnsupportedFrontends) {
-      exitWithError(
-        "Better-Auth with Convex backend is not supported for non-React frontends (nuxt, svelte, solid) or native frontends (native-nativewind, native-unistyles). Please use '--auth clerk' or '--auth none'.",
-      );
-    }
+    const unsupported = (config.frontend ?? []).filter((f) =>
+      ["nuxt", "svelte", "solid", "native-nativewind", "native-unistyles"].includes(f),
+    );
+    if (unsupported.length > 0) {
+      exitWithError(
+        `Better-Auth with Convex is not supported for: ${unsupported.join(
+          ", ",
+        )}. Please use '--auth clerk' or '--auth none'.`,
+      );
+    }
apps/cli/src/prompts/auth.ts (1)

28-31: Coerce hasReactFrontends to boolean

Avoid boolean | undefined.

Apply:

-    const hasReactFrontends = frontend?.some((f) =>
+    const hasReactFrontends = !!frontend?.some((f) =>
       ["react-router", "tanstack-router", "tanstack-start", "next"].includes(f),
     );
apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs (1)

6-6: Scope CORS instead of cors: true

Open CORS may broaden attack surface. Prefer restricting allowed origins (e.g., via env/config) or leaving CORS off for same‑origin setups.

Would you like me to propose a template-friendly pattern to inject allowed origins?

apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs (2)

22-22: Provide a safe fallback label while user loads

Avoid rendering an empty button if user?.name is undefined.

-                <Button variant="outline">{user?.name}</Button>
+                <Button variant="outline" aria-label="User menu">
+                    {user?.name ?? "Account"}
+                </Button>

9-13: Use consistent import aliasing for UI components

Mixing @/... and relative imports in the same file can cause path alias inconsistencies across templates.

-import { Button } from "./ui/button";
+import { Button } from "@/components/ui/button";
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs (1)

37-40: Harden error handling for unknown shapes

Defensive fallback avoids runtime errors if error.error is missing or differently shaped.

-                    onError: (error) => {
-                        toast.error(error.error.message || error.error.statusText);
-                    },
+                    onError: (error) => {
+                        const msg =
+                            error?.error?.message ??
+                            error?.error?.statusText ??
+                            "Sign in failed";
+                        toast.error(msg);
+                    },
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/routes/dashboard.tsx.hbs (1)

6-11: Skip private query until authenticated to avoid useless requests

Gate useQuery behind auth to reduce load and avoid unnecessary calls when unauthenticated.

-import {
-  Authenticated,
-  AuthLoading,
-  Unauthenticated,
-  useQuery,
-} from "convex/react";
+import {
+  Authenticated,
+  AuthLoading,
+  Unauthenticated,
+  useQuery,
+  useConvexAuth,
+} from "convex/react";
@@
 function RouteComponent() {
   const [showSignIn, setShowSignIn] = useState(false);
-  const privateData = useQuery(api.privateData.get);
+  const { isAuthenticated } = useConvexAuth();
+  const privateData = useQuery(isAuthenticated ? api.privateData.get : undefined);

Also applies to: 19-21

apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs (2)

71-77: Add autocomplete attributes for better UX/a11y.

Improves autofill and password manager behavior.

-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
+                                    autoComplete="name"
@@
-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
                                     type="email"
+                                    autoComplete="email"
@@
-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
                                     type="password"
+                                    autoComplete="new-password"

Also applies to: 93-100, 116-123


78-83: Use stable keys and link errors for a11y.

Keys based on message can collide; also consider aria-invalid and aria-describedby.

-                                {field.state.meta.errors.map((error) => (
-                                    <p key={error?.message} className="text-red-500">
-                                        {error?.message}
-                                    </p>
-                                ))}
+                                {field.state.meta.errors.map((error, i) => (
+                                    <p
+                                        key={`${field.name}-err-${i}`}
+                                        id={`${field.name}-error-${i}`}
+                                        className="text-red-500"
+                                    >
+                                        {error?.message}
+                                    </p>
+                                ))}

And on each Input:

-                                <Input
+                                <Input
+                                    aria-invalid={field.state.meta.errors.length > 0}
+                                    aria-describedby={
+                                        field.state.meta.errors.length
+                                            ? `${field.name}-error-0`
+                                            : undefined
+                                    }

Also applies to: 101-106, 124-129

apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs (3)

27-30: Production hardening: enable email verification by default.

Templates should guide toward safer defaults. Consider requireEmailVerification: true with a comment explaining how to disable for demos.

-        emailAndPassword: {
-            enabled: true,
-            requireEmailVerification: false,
-        },
+        emailAndPassword: {
+            enabled: true,
+            requireEmailVerification: true, // Set to false only for local demos
+        },

24-25: Trusted origins in dev.

Consider allowing common dev origins when NODE_ENV !== "production" to reduce setup friction.

-        trustedOrigins: [siteUrl],
+        trustedOrigins:
+            process.env.NODE_ENV === "production"
+                ? [siteUrl]
+                : [siteUrl, "http://localhost:3000", "http://localhost:5173"],

Also applies to: 31-36


14-17: Minor typing clarity for options arg.

Make the options object explicit and default optionsOnly via destructuring.

-export const createAuth = (
-    ctx: GenericCtx<DataModel>,
-    { optionsOnly } = { optionsOnly: false },
-) => {
+export const createAuth = (
+    ctx: GenericCtx<DataModel>,
+    opts: { optionsOnly?: boolean } = {},
+) => {
+    const { optionsOnly = false } = opts;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd866b3 and 26e5033.

📒 Files selected for processing (17)
  • apps/cli/src/constants.ts (1 hunks)
  • apps/cli/src/helpers/core/auth-setup.ts (1 hunks)
  • apps/cli/src/helpers/core/template-manager.ts (1 hunks)
  • apps/cli/src/prompts/auth.ts (1 hunks)
  • apps/cli/src/utils/compatibility-rules.ts (1 hunks)
  • apps/cli/src/utils/config-validation.ts (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.config.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/privateData.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/base/src/lib/auth-client.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/routes/dashboard.tsx.hbs (1 hunks)
  • apps/cli/templates/frontend/react/tanstack-router/src/main.tsx.hbs (2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{hbs,handlebars}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

In Handlebars templates, avoid generic if/else blocks; write explicit conditions (e.g., if (eq orm "prisma") and else if (eq orm "drizzle")).

Files:

  • apps/cli/templates/auth/better-auth/convex/web/base/src/lib/auth-client.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/privateData.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs
  • apps/cli/templates/frontend/react/tanstack-router/src/main.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/routes/dashboard.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.config.ts.hbs
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/convex_rules.mdc)

**/*.{ts,tsx}: Use Id from './_generated/dataModel' to type document ids (e.g., Id<'users'>)
Ensure Record key/value types align with validators (e.g., v.record(v.id('users'), v.string()) => Record<Id<'users'>, string>)
Be strict with types for document ids; prefer Id<'table'> over string
Use 'as const' for string literals in discriminated unions
When using Array and Record types, declare with explicit generic types (e.g., const arr: Array = ...)

**/*.{ts,tsx}: Use TypeScript type aliases instead of interface declarations.
Do not use explicit return types in TypeScript.

Files:

  • apps/cli/src/helpers/core/auth-setup.ts
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/prompts/auth.ts
  • apps/cli/src/utils/compatibility-rules.ts
  • apps/cli/src/utils/config-validation.ts
**/*.{js,jsx,ts,tsx,mjs,cjs}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{js,jsx,ts,tsx,mjs,cjs}: Do not use dotenv; Bun auto-loads .env
Use Bun.serve() for HTTP/WebSockets; do not use express
Use bun:sqlite for SQLite; do not use better-sqlite3
Use Bun.redis for Redis; do not use ioredis
Use Bun.sql for Postgres; do not use pg or postgres.js
Use built-in WebSocket; do not use ws
Prefer Bun.file over node:fs readFile/writeFile
Use Bun.$ instead of execa for shelling out

Files:

  • apps/cli/src/helpers/core/auth-setup.ts
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/prompts/auth.ts
  • apps/cli/src/utils/compatibility-rules.ts
  • apps/cli/src/utils/config-validation.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

Define functions using the standard function declaration syntax, not arrow functions.

Files:

  • apps/cli/src/helpers/core/auth-setup.ts
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/prompts/auth.ts
  • apps/cli/src/utils/compatibility-rules.ts
  • apps/cli/src/utils/config-validation.ts
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/**/*.ts : Always use the new Convex function syntax (query/mutation/action/internal*) with args/returns/handler
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/http.ts : Define HTTP endpoints only in convex/http.ts and wrap handlers with httpAction

Applied to files:

  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/http.ts : HTTP endpoints are registered at the exact path specified in route.path (no implicit prefixes)

Applied to files:

  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/schema.ts : Always define the Convex schema in convex/schema.ts and import schema helpers from convex/server

Applied to files:

  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/**/*.ts : Always use the new Convex function syntax (query/mutation/action/internal*) with args/returns/handler

Applied to files:

  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/**/*.ts : Always include argument and return validators for all Convex functions (public and internal)

Applied to files:

  • apps/cli/src/utils/config-validation.ts
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/**/*.ts : Respect file-based routing: api.<path>.<name> for public and internal.<path>.<name> for private functions based on file location/name

Applied to files:

  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/routes/dashboard.tsx.hbs
🧬 Code graph analysis (4)
apps/cli/src/helpers/core/auth-setup.ts (1)
apps/cli/src/utils/add-package-deps.ts (1)
  • addPackageDependency (6-43)
apps/cli/src/helpers/core/template-manager.ts (1)
apps/cli/src/constants.ts (1)
  • PKG_ROOT (7-7)
apps/cli/src/utils/compatibility-rules.ts (2)
apps/cli/src/types.ts (1)
  • Backend (16-16)
apps/cli/test/test-utils.ts (1)
  • Backend (199-199)
apps/cli/src/utils/config-validation.ts (1)
apps/cli/src/utils/errors.ts (1)
  • exitWithError (9-15)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (10)
apps/cli/templates/auth/better-auth/convex/web/base/src/lib/auth-client.ts.hbs (1)

7-10: Type/env safety: ensure VITE_CONVEX_SITE_URL is typed and present

This relies on a Vite env var; add an env.d.ts to type it and prevent undefined.

Add a template at apps/cli/templates/auth/better-auth/convex/web/base/src/env.d.ts.hbs:

/// <reference types="vite/client" />

interface ImportMetaEnv {
  readonly VITE_CONVEX_SITE_URL: string;
}
interface ImportMeta {
  readonly env: ImportMetaEnv;
}

And confirm the .env scaffold sets VITE_CONVEX_SITE_URL for dev/prod.

apps/cli/src/utils/compatibility-rules.ts (2)

254-259: Param rename to _backend to silence unused is fine

No functional impact. LGTM.


262-276: Confirm intent: Polar no longer blocked on Convex backend

You removed the explicit backend===“convex” check. If Polar+Convex is intended to be allowed (with Better Auth + web), please confirm templates cover this; otherwise reintroduce the guard.

Option A (intended): add tests exercising Polar+Convex+React web.

Option B (restore guard):

   if (payments === "polar") {
+    if (_backend === "convex") {
+      exitWithError("Polar payments are not supported with Convex backend.");
+    }
apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs (1)

1-8: HTTP router wiring looks correct and aligns with Convex rules

Routes are registered from a single convex/http.ts and exported via a default httpRouter() instance. Good.

apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs (1)

33-41: No change needed — authClient.signOut uses a single options object. Confirmed: signOut accepts one optional options object (e.g. { fetchOptions: { onSuccess: () => {} } }) and does not take a separate second callbacks argument; the existing code is correct.

apps/cli/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs (1)

1-7: Confirmed: use plugin directly (no invocation)
Verified against the package docs and Convex setup examples — app.use(betterAuth) is correct; no change needed in apps/cli/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs (lines 1–7).

apps/cli/templates/frontend/react/tanstack-router/src/main.tsx.hbs (1)

20-27: Better-Auth provider wiring verified — ConvexReactClient accepts { expectAuth: true } and ConvexBetterAuthProvider accepts { client, authClient } as used here.

apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs (2)

58-66: Form submit interception is correct.

Prevents native submit and routes through TanStack Form.


134-144: Good submit-state UX.

Disables the button while validating/submitting and shows progress text.

apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs (1)

12-13: authComponent wiring looks correct.

Hooked to components.betterAuth with the correct DataModel.

import { convex, crossDomain } from "@convex-dev/better-auth/plugins";
import { components } from "./_generated/api";
import { DataModel } from "./_generated/dataModel";
import { query } from "./_generated/server";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add returns schema to Convex function per our guideline.

Use returns for stronger typing. If unsure of shape, v.any() is acceptable for the template.

-import { query } from "./_generated/server";
+import { query, v } from "./_generated/server";
@@
 export const getCurrentUser = query({
-    args: {},
-    handler: async (ctx) => {
-        return authComponent.getAuthUser(ctx);
-    },
+    args: {},
+    returns: v.any(),
+    handler: async (ctx) => authComponent.getAuthUser(ctx),
 });

Also applies to: 42-47

🤖 Prompt for AI Agents
In apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs around
line 5 (and similarly for lines 42-47), Convex query functions are missing a
returns schema; update the exported query definitions to include a returns
schema (use v.any() if the exact shape is unknown) by importing v from
"convex/values" where needed and adding returns: v.any() (or the precise schema)
to each query/function declaration to satisfy the typing guideline.

import { useForm } from "@tanstack/react-form";
import { useNavigate } from "@tanstack/react-router";
import { toast } from "sonner";
import z from "zod";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix Zod import and schema (current code won’t type-check/run)

  • Zod exports z as a named export, not default.
  • email must be z.string().email(...), not z.email(...).
-import z from "zod";
+import { z } from "zod";
@@
-            onSubmit: z.object({
-                email: z.email("Invalid email address"),
-                password: z.string().min(8, "Password must be at least 8 characters"),
-            }),
+            onSubmit: z.object({
+                email: z.string().email("Invalid email address"),
+                password: z.string().min(8, "Password must be at least 8 characters"),
+            }),

Also applies to: 44-47

🤖 Prompt for AI Agents
In
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs
around lines 5 and 44-47, the file incorrectly imports Zod as a default and uses
z.email(...) which will not type-check; change the import to use the named
export (import { z } from "zod") and update the email schema to use
z.string().email("invalid email message") (i.e., replace z.email(...) with
z.string().email(...)); ensure any other Zod usages in those lines follow the
z.string()/z.object() patterns as needed.

cursor[bot]

This comment was marked as outdated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/cli/src/helpers/core/env-setup.ts (1)

6-10: Use a type alias instead of an interface (repo guideline)

Switch EnvVariable to a type alias.

-export interface EnvVariable {
-	key: string;
-	value: string | null | undefined;
-	condition: boolean;
-}
+export type EnvVariable = {
+	key: string;
+	value: string | null | undefined;
+	condition: boolean;
+};
♻️ Duplicate comments (1)
apps/cli/src/helpers/core/auth-setup.ts (1)

68-86: Frontend missing 'convex' dep for convex + better-auth (will break imports)

React clients import Convex (e.g., ConvexReactClient). Add "convex" to the client deps in all three branches.

-					await addPackageDependency({
-						dependencies: ["better-auth", "@convex-dev/better-auth"],
+					await addPackageDependency({
+						dependencies: ["better-auth", "@convex-dev/better-auth", "convex"],
 						customDependencies: { "better-auth": "1.3.8" },
 						projectDir: clientDir,
 					});
...
-					await addPackageDependency({
-						dependencies: ["better-auth", "@convex-dev/better-auth"],
+					await addPackageDependency({
+						dependencies: ["better-auth", "@convex-dev/better-auth", "convex"],
 						customDependencies: { "better-auth": "1.3.8" },
 						projectDir: clientDir,
 					});
...
-					await addPackageDependency({
-						dependencies: ["better-auth", "@convex-dev/better-auth"],
+					await addPackageDependency({
+						dependencies: ["better-auth", "@convex-dev/better-auth", "convex"],
 						customDependencies: { "better-auth": "1.3.8" },
 						projectDir: clientDir,
 					});
🧹 Nitpick comments (6)
apps/cli/src/helpers/core/env-setup.ts (2)

29-31: Escape env keys in regex to avoid false matches

Keys with regex meta-chars would misbehave. Escape the key.

-			const regex = new RegExp(`^${key}=.*$`, "m");
+			const regex = new RegExp(`^${escapeRegExp(key)}=.*$`, "m");

Add once in this module:

function escapeRegExp(str: string): string {
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

54-55: Preserve trailing newline in .env files

trimEnd() removes the final newline; keep POSIX-friendly newline at EOF.

-		await fs.writeFile(filePath, envContent.trimEnd());
+		await fs.writeFile(filePath, envContent.endsWith("\n") ? envContent : envContent + "\n");
-		await fs.writeFile(exampleFilePath, exampleEnvContent.trimEnd());
+		await fs.writeFile(
+			exampleFilePath,
+			exampleEnvContent.endsWith("\n") ? exampleEnvContent : exampleEnvContent + "\n",
+		);

Also applies to: 83-84

apps/cli/src/helpers/core/auth-setup.ts (2)

54-58: Pinned [email protected] conflicts with version map (^1.3.10)

Either rely on dependencyVersionMap or align the override. Prefer removing the overrides to keep versions centralized.

-					await addPackageDependency({
-						dependencies: ["better-auth", "@convex-dev/better-auth"],
-						customDependencies: { "better-auth": "1.3.8" },
-						projectDir: convexBackendDir,
-					});
+					await addPackageDependency({
+						dependencies: ["better-auth", "@convex-dev/better-auth"],
+						projectDir: convexBackendDir,
+					});
-						await addPackageDependency({
-							dependencies: ["better-auth", "@convex-dev/better-auth", "convex"],
-							customDependencies: { "better-auth": "1.3.8" },
-							projectDir: clientDir,
-						});
+						await addPackageDependency({
+							dependencies: ["better-auth", "@convex-dev/better-auth", "convex"],
+							projectDir: clientDir,
+						});

(repeat the same removal for the TanStack Start and Vite React branches)

Also applies to: 69-72, 75-78, 81-84


49-89: Optional: factor repeated client-branch install logic

Reduce repetition by computing deps once and calling addPackageDependency once per detected frontend.

apps/cli/src/utils/add-package-deps.ts (2)

9-10: Tighten override types to catch typos

Type overrides against AvailableDependencies.

-	customDependencies?: Record<string, string>;
-	customDevDependencies?: Record<string, string>;
+	customDependencies?: Partial<Record<AvailableDependencies, string>>;
+	customDevDependencies?: Partial<Record<AvailableDependencies, string>>;

42-45: Optional: avoid unnecessary writes

Compute if pkgJson changed before write to reduce churn.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 26e5033 and 0315b5b.

📒 Files selected for processing (6)
  • apps/cli/src/helpers/core/auth-setup.ts (1 hunks)
  • apps/cli/src/helpers/core/convex-codegen.ts (1 hunks)
  • apps/cli/src/helpers/core/create-project.ts (0 hunks)
  • apps/cli/src/helpers/core/env-setup.ts (1 hunks)
  • apps/cli/src/prompts/auth.ts (1 hunks)
  • apps/cli/src/utils/add-package-deps.ts (3 hunks)
💤 Files with no reviewable changes (1)
  • apps/cli/src/helpers/core/create-project.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/cli/src/helpers/core/convex-codegen.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/cli/src/prompts/auth.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/convex_rules.mdc)

**/*.{ts,tsx}: Use Id from './_generated/dataModel' to type document ids (e.g., Id<'users'>)
Ensure Record key/value types align with validators (e.g., v.record(v.id('users'), v.string()) => Record<Id<'users'>, string>)
Be strict with types for document ids; prefer Id<'table'> over string
Use 'as const' for string literals in discriminated unions
When using Array and Record types, declare with explicit generic types (e.g., const arr: Array = ...)

**/*.{ts,tsx}: Use TypeScript type aliases instead of interface declarations.
Do not use explicit return types in TypeScript.

Files:

  • apps/cli/src/helpers/core/env-setup.ts
  • apps/cli/src/utils/add-package-deps.ts
  • apps/cli/src/helpers/core/auth-setup.ts
**/*.{js,jsx,ts,tsx,mjs,cjs}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{js,jsx,ts,tsx,mjs,cjs}: Do not use dotenv; Bun auto-loads .env
Use Bun.serve() for HTTP/WebSockets; do not use express
Use bun:sqlite for SQLite; do not use better-sqlite3
Use Bun.redis for Redis; do not use ioredis
Use Bun.sql for Postgres; do not use pg or postgres.js
Use built-in WebSocket; do not use ws
Prefer Bun.file over node:fs readFile/writeFile
Use Bun.$ instead of execa for shelling out

Files:

  • apps/cli/src/helpers/core/env-setup.ts
  • apps/cli/src/utils/add-package-deps.ts
  • apps/cli/src/helpers/core/auth-setup.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

Define functions using the standard function declaration syntax, not arrow functions.

Files:

  • apps/cli/src/helpers/core/env-setup.ts
  • apps/cli/src/utils/add-package-deps.ts
  • apps/cli/src/helpers/core/auth-setup.ts
🧬 Code graph analysis (2)
apps/cli/src/utils/add-package-deps.ts (1)
apps/cli/src/constants.ts (1)
  • dependencyVersionMap (42-163)
apps/cli/src/helpers/core/auth-setup.ts (1)
apps/cli/src/utils/add-package-deps.ts (1)
  • addPackageDependency (6-45)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (4)
apps/cli/src/helpers/core/env-setup.ts (1)

182-196: Convex better-auth site URL vars added — confirm frameworks coverage

Looks good for Next.js and React Router/TanStack (incl. Start). If any Nuxt/Svelte/Solid templates consume a CONVEX_SITE_URL equivalent, add those here too; otherwise explicitly confirm React-only usage to avoid drift.

apps/cli/src/helpers/core/auth-setup.ts (2)

22-47: Clerk branches look consistent with frontend detection

Next/TanStack/Vite splits and clientDirExists guard are correct.


138-149: Expo setup aligns with server echo of @better-auth/expo

Native deps wiring looks correct.

apps/cli/src/utils/add-package-deps.ts (1)

23-24: LGTM: override > map fallback resolution

Override precedence is correct for both deps and devDeps.

Also applies to: 32-33

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

♻️ Duplicate comments (3)
apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs (3)

12-12: Don’t read process.env at module scope in Convex; use ctx.env.

Move SITE_URL lookup inside createAuth using ctx.env.get("SITE_URL") and validate it. This is required in Convex.

-const siteUrl = process.env.SITE_URL!;

(and define siteUrl inside createAuth as shown below)


---

`16-41`: **Load SITE_URL via ctx.env and fail fast if missing.**

Also keep `siteUrl` in scope for plugins/options.




```diff
 export const createAuth = (
     ctx: GenericCtx<DataModel>,
     { optionsOnly } = { optionsOnly: false },
 ) => {
-    return betterAuth({
+    const siteUrl = ctx.env.get("SITE_URL");
+    if (!siteUrl) {
+        throw new Error("SITE_URL is required (e.g. https://app.example.com)");
+    }
+    return betterAuth({
         logger: {
             disabled: optionsOnly,
         },
         {{#if (eq frontend "tanstack-start")}}
         baseUrl: siteUrl,
-        {{else}}
+        {{else if (eq frontend "tanstack-router")}}
         trustedOrigins: [siteUrl],
         {{/if}}
         database: authComponent.adapter(ctx),
         emailAndPassword: {
             enabled: true,
             requireEmailVerification: false,
         },
         plugins: [
-            {{#unless (eq frontend "tanstack-start")}}
+            {{#if (eq frontend "tanstack-router")}}
             crossDomain({ siteUrl }),
-            {{/unless}}
+            {{/if}}
             convex(),
         ],
     });
 };

9-10: Add returns schema to the Convex query.

Follow our guideline to include returns. Use v.any() if the exact shape varies.

-import { query } from "./_generated/server";
+import { query, v } from "./_generated/server";
@@
 export const getCurrentUser = query({
     args: {},
+    returns: v.any(),
     handler: async (ctx) => {
         return authComponent.getAuthUser(ctx);
     },
 });

Also applies to: 43-48

🧹 Nitpick comments (9)
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/dashboard.tsx.hbs (2)

19-20: Add error handling for unauthenticated queries

The useQuery call might fail if the user is not authenticated. Consider wrapping it with the Authenticated component logic or handling potential null/error states.

 function RouteComponent() {
   const [showSignIn, setShowSignIn] = useState(false);
-  const privateData = useQuery(api.privateData.get);

   return (
     <>
       <Authenticated>
-        <div>
-          <h1>Dashboard</h1>
-          <p>privateData: {privateData?.message}</p>
-          <UserMenu />
-        </div>
+        <AuthenticatedDashboard />
       </Authenticated>

Add a separate component:

function AuthenticatedDashboard() {
  const privateData = useQuery(api.privateData.get);
  return (
    <div>
      <h1>Dashboard</h1>
      <p>privateData: {privateData?.message}</p>
      <UserMenu />
    </div>
  );
}

32-36: Use function syntax for inline callbacks

For consistency with the coding guidelines, use function declarations for callbacks.

         {showSignIn ? (
-          <SignInForm onSwitchToSignUp={() => setShowSignIn(false)} />
+          <SignInForm onSwitchToSignUp={function() { setShowSignIn(false) }} />
         ) : (
-          <SignUpForm onSwitchToSignIn={() => setShowSignIn(true)} />
+          <SignUpForm onSwitchToSignIn={function() { setShowSignIn(true) }} />
         )}
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/user-menu.tsx.hbs (1)

21-23: Add a safe fallback label and a11y to the trigger.

Avoid rendering an empty button while the user is loading; expose an accessible label.

-                <Button variant="outline">{user?.name}</Button>
+                <Button variant="outline" aria-label="User menu">
+                  {user?.name ?? user?.email ?? "Account"}
+                </Button>
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs (3)

39-41: Harden error handling to avoid runtime crashes.

error.error may be undefined. Add safe fallbacks.

-                        toast.error(error.error.message || error.error.statusText);
+                        toast.error(
+                          error?.error?.message ??
+                          error?.error?.statusText ??
+                          "Sign up failed"
+                        );

71-77: Add autocomplete hints.

Improves UX and browser password manager behavior.

-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
+                                    autoComplete="name"
@@
-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
                                     type="email"
+                                    autoComplete="email"
@@
-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
                                     type="password"
+                                    autoComplete="new-password"

Also applies to: 93-100, 116-123


58-64: Optional: await form submission.

Prevents double‑submit if the click handler fires rapidly.

-                onSubmit={(e) => {
+                onSubmit={async (e) => {
                     e.preventDefault();
                     e.stopPropagation();
-                    form.handleSubmit();
+                    await form.handleSubmit();
                 }}
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbs (2)

37-39: Harden error handling.

Guard against missing properties.

-                        toast.error(error.error.message || error.error.statusText);
+                        toast.error(
+                          error?.error?.message ??
+                          error?.error?.statusText ??
+                          "Sign in failed"
+                        );

69-75: Add autocomplete hints.

Better UX and password manager integration.

-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
                                     type="email"
+                                    autoComplete="email"
@@
-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
                                     type="password"
+                                    autoComplete="current-password"

Also applies to: 92-98

apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs (1)

2-6: Prefer explicit Handlebars branches over a generic else.

Make the template resilient if new frontends are added by using else if (eq frontend "tanstack-router") consistently (imports, options, plugins).

-{{#if (eq frontend "tanstack-start")}}
+{{#if (eq frontend "tanstack-start")}}
 import { convex } from "@convex-dev/better-auth/plugins";
-{{else}}
+{{else if (eq frontend "tanstack-router")}}
 import { convex, crossDomain } from "@convex-dev/better-auth/plugins";
 {{/if}}

(Also applied in options/plugins in the other diff above.)

Also applies to: 24-28, 35-39

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0315b5b and 0aa73f9.

📒 Files selected for processing (11)
  • apps/cli/src/helpers/core/env-setup.ts (2 hunks)
  • apps/cli/src/helpers/core/template-manager.ts (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/lib/auth-client.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/user-menu.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/api/auth/$.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/dashboard.tsx.hbs (1 hunks)
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs
  • apps/cli/src/helpers/core/template-manager.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{hbs,handlebars}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

In Handlebars templates, avoid generic if/else blocks; write explicit conditions (e.g., if (eq orm "prisma") and else if (eq orm "drizzle")).

Files:

  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/user-menu.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/lib/auth-client.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/dashboard.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/api/auth/$.ts.hbs
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/convex_rules.mdc)

**/*.{ts,tsx}: Use Id from './_generated/dataModel' to type document ids (e.g., Id<'users'>)
Ensure Record key/value types align with validators (e.g., v.record(v.id('users'), v.string()) => Record<Id<'users'>, string>)
Be strict with types for document ids; prefer Id<'table'> over string
Use 'as const' for string literals in discriminated unions
When using Array and Record types, declare with explicit generic types (e.g., const arr: Array = ...)

**/*.{ts,tsx}: Use TypeScript type aliases instead of interface declarations.
Do not use explicit return types in TypeScript.

Files:

  • apps/cli/src/helpers/core/env-setup.ts
**/*.{js,jsx,ts,tsx,mjs,cjs}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{js,jsx,ts,tsx,mjs,cjs}: Do not use dotenv; Bun auto-loads .env
Use Bun.serve() for HTTP/WebSockets; do not use express
Use bun:sqlite for SQLite; do not use better-sqlite3
Use Bun.redis for Redis; do not use ioredis
Use Bun.sql for Postgres; do not use pg or postgres.js
Use built-in WebSocket; do not use ws
Prefer Bun.file over node:fs readFile/writeFile
Use Bun.$ instead of execa for shelling out

Files:

  • apps/cli/src/helpers/core/env-setup.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

Define functions using the standard function declaration syntax, not arrow functions.

Files:

  • apps/cli/src/helpers/core/env-setup.ts
🧠 Learnings (5)
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/**/*.ts : Always use the new Convex function syntax (query/mutation/action/internal*) with args/returns/handler

Applied to files:

  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/schema.ts : Always define the Convex schema in convex/schema.ts and import schema helpers from convex/server

Applied to files:

  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/**/*.ts : Always include argument and return validators for all Convex functions (public and internal)

Applied to files:

  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/**/*.ts : When calling a function in the same file with ctx.run*, add a return type annotation to avoid TS circularity issues

Applied to files:

  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/**/*.ts : Use ctx.runQuery/ctx.runMutation/ctx.runAction instead of calling functions directly; pass a FunctionReference

Applied to files:

  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (4)
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/lib/auth-client.ts.hbs (1)

7-10: LGTM! Clean auth client setup

The auth client configuration correctly uses the environment variable and includes the necessary plugins for Convex integration.

apps/cli/src/helpers/core/env-setup.ts (1)

182-196: LGTM! Proper environment variable setup for Better-Auth

The implementation correctly adds frontend-specific environment variables for different frameworks, maintaining consistency with the existing Clerk integration pattern.

apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs (1)

153-171: LGTM! Proper provider integration

The ConvexBetterAuthProvider integration correctly passes both the Convex client and auth client, maintaining the same structure as the Clerk provider branch.

apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/user-menu.tsx.hbs (1)

36-38: Confirm redirect after sign‑out.

Navigating to “/dashboard” post sign‑out may immediately bounce; typically redirect to “/” or “/sign-in”. Verify route guards.

Comment on lines 236 to 276
if (auth === "better-auth") {
const convexBackendDir = path.join(projectDir, "packages/backend");
if (await fs.pathExists(convexBackendDir)) {
const convexBackendVars: EnvVariable[] = [
{
key: "VITE_CONVEX_SITE_URL",
value: "",
condition: true,
},
{
key: "SITE_URL",
value: "http://localhost:3001",
condition: true,
},
];
await addEnvVariablesToFile(path.join(convexBackendDir, ".env.local"), convexBackendVars);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 Analysis chain

Verify the dual URL configuration pattern

The backend configuration sets both VITE_CONVEX_SITE_URL (empty) and SITE_URL (http://localhost:3001). This dual configuration could be confusing.

Could you clarify why VITE_CONVEX_SITE_URL is set with an empty value in the backend .env.local while SITE_URL has a specific value? This seems inconsistent with the frontend setup where VITE_CONVEX_SITE_URL has a placeholder value.


🏁 Script executed:

#!/bin/bash
# Check how these environment variables are used in the Better-Auth backend templates
rg -n -C3 'VITE_CONVEX_SITE_URL|SITE_URL' --type=hbs -g '**/auth/better-auth/convex/backend/**'

Length of output: 1419


Replace VITE_CONVEX_SITE_URL with CONVEX_SITE_URL in the backend .env.local

Templates read process.env.CONVEX_SITE_URL and process.env.SITE_URL; env-setup.ts currently injects VITE_CONVEX_SITE_URL (empty) alongside SITE_URL, so the backend will not receive the expected CONVEX_SITE_URL. Change the convexBackendVars entry to use CONVEX_SITE_URL (with an appropriate placeholder or the same value as SITE_URL) or remove the VITE_ entry.

Locations: apps/cli/src/helpers/core/env-setup.ts (lines ~236–253) — verified in apps/cli/templates/auth/better-auth/convex/backend/convex/auth.config.ts.hbs (uses CONVEX_SITE_URL) and auth.ts.hbs (uses SITE_URL).

🤖 Prompt for AI Agents
In apps/cli/src/helpers/core/env-setup.ts around lines 236 to 253, the backend
.env.local is being populated with VITE_CONVEX_SITE_URL instead of
CONVEX_SITE_URL, so the backend templates that read process.env.CONVEX_SITE_URL
won't see the value; replace the VITE_CONVEX_SITE_URL EnvVariable entry with a
CONVEX_SITE_URL entry (set its value to an appropriate placeholder or to the
same value as SITE_URL, e.g., "http://localhost:3001"), then run the existing
addEnvVariablesToFile call unchanged so .env.local contains CONVEX_SITE_URL and
SITE_URL.

cursor[bot]

This comment was marked as outdated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (6)
apps/cli/templates/frontend/react/next/src/components/providers.tsx.hbs (2)

9-9: Remove unused ConvexProvider import in the better-auth branch.

ConvexProvider isn’t used when auth === "better-auth" and will trip no‑unused‑vars in generated projects.

- import { ConvexProvider, ConvexReactClient } from "convex/react";
+ import { ConvexReactClient } from "convex/react";

8-11: Make auth branches explicit; avoid generic else per template guidelines.

Per the Handlebars guideline, enumerate all supported auth values rather than using a generic else. Do the same in both the import section and the render flow.

Example (adjust the literal(s) to match your supported set, e.g., "none", "authjs", etc.):

 {{#if (eq auth "clerk")}}
   ...
-{{else if (eq auth "better-auth")}}
+{{else if (eq auth "better-auth")}}
   ...
-{{else}}
+{{else if (eq auth "none")}}
   import { ConvexProvider, ConvexReactClient } from "convex/react";
 {{/if}}
 {{#if (eq auth "clerk")}}
   ...
-{{else if (eq auth "better-auth")}}
+{{else if (eq auth "better-auth")}}
   <ConvexBetterAuthProvider client={convex} authClient={authClient}>
     {children}
   </ConvexBetterAuthProvider>
-{{else}}
+{{else if (eq auth "none")}}
   <ConvexProvider client={convex}>{children}</ConvexProvider>
 {{/if}}

Also applies to: 51-54

apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbs (2)

17-18: Terminate statement and add a safe fallback label.

Avoid empty trigger text while loading/unauthenticated.

Apply:

-const user = useQuery(api.auth.getCurrentUser)
+const user = useQuery(api.auth.getCurrentUser);
+const displayName = user?.name ?? "Account";

21-23: Use the fallback label to avoid blank trigger UI.

Apply:

-<Button variant="outline">{user?.name}</Button>
+<Button variant="outline">{displayName}</Button>
apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-in-form.tsx.hbs (1)

33-35: Harden error toast to avoid optional chaining pitfalls.

If error.error is absent, this will throw.

Apply:

-						toast.error(error.error.message || error.error.statusText);
+						toast.error(error?.error?.message ?? error?.error?.statusText ?? "Sign in failed");
apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-up-form.tsx.hbs (1)

35-37: Defensive error handling in toast.

Apply:

-						toast.error(error.error.message || error.error.statusText);
+						toast.error(error?.error?.message ?? error?.error?.statusText ?? "Sign up failed");
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0aa73f9 and 763c631.

📒 Files selected for processing (12)
  • apps/cli/src/helpers/core/env-setup.ts (2 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/api/auth/[...all]/route.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-in-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-up-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-client.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-server.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/web/react/next/src/components/theme-provider.tsx.hbs (0 hunks)
  • apps/cli/templates/frontend/react/next/src/components/providers.tsx.hbs (2 hunks)
  • apps/cli/templates/frontend/react/web-base/src/components/header.tsx.hbs (2 hunks)
💤 Files with no reviewable changes (1)
  • apps/cli/templates/auth/better-auth/web/react/next/src/components/theme-provider.tsx.hbs
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs
  • apps/cli/src/helpers/core/env-setup.ts
  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{hbs,handlebars}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

In Handlebars templates, avoid generic if/else blocks; write explicit conditions (e.g., if (eq orm "prisma") and else if (eq orm "drizzle")).

Files:

  • apps/cli/templates/frontend/react/web-base/src/components/header.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-in-form.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-client.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-up-form.tsx.hbs
  • apps/cli/templates/frontend/react/next/src/components/providers.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-server.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/api/auth/[...all]/route.ts.hbs
🧠 Learnings (1)
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/**/*.ts : Respect file-based routing: api.<path>.<name> for public and internal.<path>.<name> for private functions based on file location/name

Applied to files:

  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/api/auth/[...all]/route.ts.hbs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (6)
apps/cli/templates/frontend/react/next/src/components/providers.tsx.hbs (2)

11-11: Verify authClient path alias and export shape

  • apps/cli/templates/frontend/react/next/src/lib/auth-client.ts.hbs was not found by the search.
  • The verification run hit regex parse errors, so I could not reliably confirm the tsconfig '@/* → src/*' alias or that authClient is exported as a named symbol. Run these corrected checks locally:
fd -HI -a 'auth-client.ts*' apps/cli/templates || echo "No auth-client template found"
fd -HI -a 'tsconfig*.json.hbs' apps/cli/templates/frontend/react/next -x sed -n '1,200p' {} || echo "No tsconfig template found"
rg -n --hidden 'authClient' apps/cli/templates -S || echo "authClient not referenced/exported"

51-54: Confirm @convex-dev/better-auth provider API and correct package version

npm shows no v0.8.x; published releases are 0.7.x — ConvexBetterAuthProvider is exported in 0.7.x and accepts props {client: ConvexReactClient, authClient: AuthClient} and provides the Convex context. Update the template's version hint from ^0.8.x to ^0.7.x or ensure package.json targets a compatible 0.7.x release.

Location: apps/cli/templates/frontend/react/next/src/components/providers.tsx.hbs (lines 51–54)

apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-client.ts.hbs (1)

1-6: LGTM.

Client init with the Convex plugin looks correct.

apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbs (1)

33-39: Incorrect — signOut accepts callbacks via fetchOptions; keep the current call

TypeScript signature is async signOut(opts?: { fetchOptions?: { onSuccess?:..., onError?:... } }): Promise; passing callbacks as a second argument is wrong. Use the canonical form:

authClient.signOut({
fetchOptions: {
onSuccess: () => { router.push("/dashboard"); },
},
});

File: apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbs (lines 33–39)

Likely an incorrect or invalid review comment.

apps/cli/templates/frontend/react/web-base/src/components/header.tsx.hbs (1)

12-14: Approve — conditional UserMenu import & render are correct.

Both the import and the rendered are wrapped in (and (eq auth "better-auth") (ne backend "convex")), so "./user-menu" is not emitted when backend == "convex", preventing missing-file errors. Confirmed in apps/cli/templates/frontend/react/web-base/src/components/header.tsx.hbs (import: lines 12–14; render: lines 70–72). No other "user-menu" occurrences found.

apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-in-form.tsx.hbs (1)

4-4: Use named import for z from "zod"

Zod exposes z as a named export; default import can break types/runtime.

File: apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-in-form.tsx.hbs (line 4)

-import z from "zod";
+import { z } from "zod";

Scan repo for other default zod imports and fix if found:

rg -nP --hidden --no-ignore '\bimport\s+z\s+from\s+"zod"' -g '!**/node_modules/**'

cursor[bot]

This comment was marked as outdated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/cli/templates/frontend/react/tanstack-start/src/routes/index.tsx.hbs (1)

65-80: Avoid generic else in Handlebars; use explicit conditions per guidelines.

Replace the generic else + unless with an explicit else-if for TRPC/ORPC so conditions remain self-documenting in templates.

-          {{else}}
-            {{#unless (eq api "none")}}
+          {{else if (or (eq api "trpc") (eq api "orpc"))}}
             <div className="flex items-center gap-2">
               <div
                 className={`h-2 w-2 rounded-full ${healthCheck.data ? "bg-green-500" : "bg-red-500"}`}
               />
               <span className="text-muted-foreground text-sm">
                 {healthCheck.isLoading
                   ? "Checking..."
                   : healthCheck.data
                     ? "Connected"
                     : "Disconnected"}
               </span>
             </div>
-            {{/unless}}
           {{/if}}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 763c631 and 876020b.

📒 Files selected for processing (3)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-client.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbs (1 hunks)
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/index.tsx.hbs (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{hbs,handlebars}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

In Handlebars templates, avoid generic if/else blocks; write explicit conditions (e.g., if (eq orm "prisma") and else if (eq orm "drizzle")).

Files:

  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-client.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbs
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/index.tsx.hbs
🧠 Learnings (1)
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/**/*.ts : Use query/mutation/action for public API; use internalQuery/internalMutation/internalAction for private functions; do not register via api/internal objects

Applied to files:

  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbs
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/index.tsx.hbs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (4)
apps/cli/templates/frontend/react/tanstack-start/src/routes/index.tsx.hbs (2)

4-5: Switch to useQuery is fine.

Importing useQuery for the Convex path is correct given the move away from Suspense. Ensure the app is wrapped in QueryClientProvider at the root for TanStack Start.


38-44: Convex health check via useQuery(convexQuery(...)) looks correct.

convexQuery(api.healthCheck.get, {}) should return query options compatible with useQuery; status rendering matches returned "OK". No blocking issues.

apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-client.ts.hbs (1)

1-6: Auth client imports verified — approve changes. createAuthClient is exported from "better-auth/react" and convexClient from "@convex-dev/better-auth/client/plugins" (matches v^0.8.3 examples).

apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbs (1)

1-5: Replace setupFetchClient usage — not exported by @convex-dev/better-auth/react-start

@convex-dev/better-auth/react-start does not export setupFetchClient that returns {fetchQuery, fetchMutation, fetchAction} compatible with convex/auth v^0.8.3; update apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbs (lines 1–5) to import Convex's server/nextjs fetch helpers or wire Better Auth's convexClient plugin to provide equivalent helpers.

Likely an incorrect or invalid review comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/dashboard/page.tsx.hbs (1)

35-37: Optional: refine loading UX.

Replace the plain “Loading...” with a lightweight skeleton/spinner to avoid layout shift.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 876020b and 85c43fe.

📒 Files selected for processing (2)
  • apps/cli/src/constants.ts (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/dashboard/page.tsx.hbs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/cli/src/constants.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{hbs,handlebars}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

In Handlebars templates, avoid generic if/else blocks; write explicit conditions (e.g., if (eq orm "prisma") and else if (eq orm "drizzle")).

Files:

  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/dashboard/page.tsx.hbs
🔇 Additional comments (2)
apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/dashboard/page.tsx.hbs (2)

1-1: Client component directive looks correct for hooks.

This page needs to be a client component for useState and Convex hooks. Good call.


6-6: Verify deep import to Convex codegen output resolves in the generated workspace.

Ensure the package name and path @{{projectName}}/backend/convex/_generated/api exist at runtime:

  • The backend package should not restrict deep imports via exports.
  • Convex codegen must run to materialize _generated/api before the web app builds.

If either is false, switch to a local re-export (e.g., a small wrapper module in the backend that re-exports api) or update the path to whatever your workspace exposes.

cursor[bot]

This comment was marked as outdated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (4)
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs (3)

39-41: Harden error handling to avoid possible TypeError and add fallback.

Apply:

-                    onError: (error) => {
-                        toast.error(error.error.message || error.error.statusText);
-                    },
+                    onError: (error) => {
+                        toast.error(
+                            error?.error?.message ??
+                                error?.error?.statusText ??
+                                "Sign up failed",
+                        );
+                    },

5-5: Fix Zod import and use correct email validator.

Use named import and z.string().email(...). Current code will fail type-check/runtime.

Apply:

-import z from "zod";
+import { z } from "zod";
@@
-                email: z.email("Invalid email address"),
+                email: z.string().email("Invalid email address"),

Also applies to: 46-50


2-4: Wire TanStack Zod adapter so validators actually run.

Without the adapter, Zod schemas in validators won’t execute.

Apply:

 import { useForm } from "@tanstack/react-form";
+import { zodValidator } from "@tanstack/zod-form-adapter";
@@
     const form = useForm({
       defaultValues: {
@@
-      validators: {
+      validatorAdapter: zodValidator(),
+      validators: {
         onSubmit: z.object({

Also applies to: 19-25, 45-52

apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs (1)

5-5: Fix Zod import, schema, and wire up TanStack Zod adapter (won’t type‑check/run as written).

  • Zod’s z is a named export.
  • email must be z.string().email(...).
  • TanStack Form needs the Zod adapter to accept Zod schemas in validators.

Apply:

-import z from "zod";
+import { z } from "zod";
+import { zodValidator } from "@tanstack/zod-form-adapter";
@@
-    const form = useForm({
+    const form = useForm({
         defaultValues: {
           email: "",
           password: "",
         },
+        validatorAdapter: zodValidator(),
         onSubmit: async ({ value }) => {
@@
-        validators: {
-            onSubmit: z.object({
-                email: z.email("Invalid email address"),
-                password: z.string().min(8, "Password must be at least 8 characters"),
-            }),
-        },
+        validators: {
+            onSubmit: z.object({
+                email: z.string().email("Invalid email address"),
+                password: z.string().min(8, "Password must be at least 8 characters"),
+            }),
+        },

Also ensure the scaffolded template installs @tanstack/zod-form-adapter.

#!/bin/bash
# Verify adapter dependency exists in template package.json files
fd -a package.json apps/cli/templates | xargs -I {} rg -n '"@tanstack/zod-form-adapter"\s*:\s*"[^\"]+"'

Also applies to: 19-24, 44-47

🧹 Nitpick comments (11)
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs (4)

25-44: Catch unexpected rejections from signUp call.

Guard against network/transport errors that may bypass onError callback.

Apply:

-        onSubmit: async ({ value }) => {
-            await authClient.signUp.email(
+        onSubmit: async ({ value }) => {
+            try {
+                await authClient.signUp.email(
                   {
                     email: value.email,
                     password: value.password,
                     name: value.name,
                   },
                   {
                     onSuccess: () => {
                       navigate({
                         to: "/dashboard",
                       });
                       toast.success("Sign up successful");
                     },
                     onError: (error) => {
-                        toast.error(error.error.message || error.error.statusText);
+                        toast.error(
+                            error?.error?.message ??
+                                error?.error?.statusText ??
+                                "Sign up failed",
+                        );
                     },
                   },
-            );
+                );
+            } catch (err) {
+                const msg =
+                    err instanceof Error ? err.message : "Sign up failed";
+                toast.error(msg);
+            }
         },

71-77: Improve a11y/UX: add autocomplete and basic a11y flags to inputs.

Apply:

                                 <Input
                                     id={field.name}
                                     name={field.name}
+                                    autoComplete="name"
+                                    aria-invalid={field.state.meta.errors.length > 0}
                                     value={field.state.value}
                                     onBlur={field.handleBlur}
                                     onChange={(e) => field.handleChange(e.target.value)}
                                 />
@@
                                 <Input
                                     id={field.name}
                                     name={field.name}
                                     type="email"
+                                    inputMode="email"
+                                    autoComplete="email"
+                                    aria-invalid={field.state.meta.errors.length > 0}
                                     value={field.state.value}
                                     onBlur={field.handleBlur}
                                     onChange={(e) => field.handleChange(e.target.value)}
                                 />
@@
                                 <Input
                                     id={field.name}
                                     name={field.name}
                                     type="password"
+                                    autoComplete="new-password"
+                                    aria-invalid={field.state.meta.errors.length > 0}
                                     value={field.state.value}
                                     onBlur={field.handleBlur}
                                     onChange={(e) => field.handleChange(e.target.value)}
                                 />

Also applies to: 93-100, 116-123


78-83: Avoid duplicate React keys for error messages.

Apply:

-                                {field.state.meta.errors.map((error) => (
-                                    <p key={error?.message} className="text-red-500">
-                                        {error?.message}
-                                    </p>
-                                ))}
+                                {field.state.meta.errors.map((error, i) => (
+                                    <p
+                                        key={`${error?.message ?? "error"}-${i}`}
+                                        className="text-red-500"
+                                        aria-live="polite"
+                                        role="alert"
+                                    >
+                                        {error?.message}
+                                    </p>
+                                ))}

Also applies to: 101-106, 124-129


15-17: Nit: simplify useNavigate call.

The from option isn’t needed here.

Apply:

-    const navigate = useNavigate({
-        from: "/",
-    });
+    const navigate = useNavigate();
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs (4)

37-39: Harden error handling to avoid crashes when shape varies.

Use optional chaining and a safe fallback:

-                        toast.error(error.error.message || error.error.statusText);
+                        toast.error(error?.error?.message ?? error?.error?.statusText ?? "Sign in failed");

109-119: Limit re-renders by selecting only needed form state.

-                <form.Subscribe>
+                <form.Subscribe selector={(state) => [state.canSubmit, state.isSubmitting]}>

55-61: Clarify intentional promise ignore to satisfy linters.

-                    form.handleSubmit();
+                    void form.handleSubmit();

69-75: Improve a11y and list key stability; add autocomplete hints.

                                 <Input
                                     id={field.name}
                                     name={field.name}
                                     type="email"
+                                    autoComplete="email"
                                     value={field.state.value}
                                     onBlur={field.handleBlur}
                                     onChange={(e) => field.handleChange(e.target.value)}
+                                    aria-invalid={field.state.meta.errors.length > 0}
                                 />
-                                {field.state.meta.errors.map((error) => (
-                                    <p key={error?.message} className="text-red-500">
+                                {field.state.meta.errors.map((error, i) => (
+                                    <p key={`${field.name}-err-${i}`} className="text-red-500" role="alert">
                                         {error?.message}
                                     </p>
                                 ))}
@@
                                 <Input
                                     id={field.name}
                                     name={field.name}
                                     type="password"
+                                    autoComplete="current-password"
                                     value={field.state.value}
                                     onBlur={field.handleBlur}
                                     onChange={(e) => field.handleChange(e.target.value)}
+                                    aria-invalid={field.state.meta.errors.length > 0}
                                 />
-                                {field.state.meta.errors.map((error) => (
-                                    <p key={error?.message} className="text-red-500">
+                                {field.state.meta.errors.map((error, i) => (
+                                    <p key={`${field.name}-err-${i}`} className="text-red-500" role="alert">
                                         {error?.message}
                                     </p>
                                 ))}

Also applies to: 76-81, 91-98, 99-104

apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs (3)

22-22: Handle loading/null user states to avoid empty UI.

useQuery returns undefined while loading and null if not authenticated. Provide sensible fallbacks.

-                <Button variant="outline">{user?.name}</Button>
+                <Button variant="outline">{user?.name ?? "Account"}</Button>
@@
-                <DropdownMenuItem>{user?.email}</DropdownMenuItem>
+                <DropdownMenuItem>{user?.email ?? ""}</DropdownMenuItem>

Also applies to: 27-27


11-11: Unify import style (prefer alias to relative for consistency).

Minor consistency nit; aligns with the other import above.

-import { Button } from "./ui/button";
+import { Button } from "@/components/ui/button";

28-46: Prefer menu semantics: use DropdownMenuItem’s onSelect instead of nesting a Button.

Avoids nested interactive controls and auto-closes the menu after select.

-                <DropdownMenuItem asChild>
-                    <Button
-                        variant="destructive"
-                        className="w-full"
-                        onClick={async () => {
-                            await authClient.signOut();
-                            navigate({ to: "/dashboard" });
-                        }}
-                    >
-                        Sign Out
-                    </Button>
-                </DropdownMenuItem>
+                <DropdownMenuItem
+                    className="text-destructive focus:text-destructive"
+                    onSelect={async () => {
+                        await authClient.signOut();
+                        navigate({ to: "/dashboard" });
+                    }}
+                >
+                    Sign Out
+                </DropdownMenuItem>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 85c43fe and 94b70bc.

📒 Files selected for processing (4)
  • apps/cli/src/constants.ts (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/cli/src/constants.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{hbs,handlebars}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

In Handlebars templates, avoid generic if/else blocks; write explicit conditions (e.g., if (eq orm "prisma") and else if (eq orm "drizzle")).

Files:

  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (2)
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs (1)

1-8: Template style OK for .hbs guidelines.

No generic if/else blocks; compliant with the template rule.

apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs (1)

32-42: Incorrect — fetchOptions.onSuccess is supported; keep the onSuccess redirect.
Better Auth docs show authClient.signOut accepts a fetchOptions.onSuccess callback and examples use it for redirects; the await-based change is unnecessary.

Likely an incorrect or invalid review comment.

cursor[bot]

This comment was marked as outdated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs (1)

5-5: Blocker: Fix Zod import and TanStack Form validator wiring (use zodValidator).

  • Zod doesn’t have a default export; use named import.
  • validators.onSubmit must be a function; passing a Zod schema object will throw at runtime.
  • Replace z.email(...) with z.string().email(...).

Apply:

-import z from "zod";
+import { z } from "zod";
+import { zodValidator } from "@tanstack/zod-form-adapter";
@@
-        validators: {
-            onSubmit: z.object({
-                email: z.email("Invalid email address"),
-                password: z.string().min(8, "Password must be at least 8 characters"),
-            }),
-        },
+        validators: {
+            onSubmit: zodValidator(
+                z.object({
+                    email: z.string().email("Invalid email address"),
+                    password: z.string().min(8, "Password must be at least 8 characters"),
+                }),
+            ),
+        },

Please confirm that @tanstack/zod-form-adapter is added to the template’s dependencies/install step. You can verify with:

#!/bin/bash
rg -n '@tanstack/zod-form-adapter' -C2
rg -nP '"@tanstack/zod-form-adapter"\s*:' -g '**/package.json*' -n

Also applies to: 43-48

🧹 Nitpick comments (6)
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs (5)

55-63: Prefer custom validation only: disable native HTML validation.

Avoid mixed UX between native and TanStack validation.

-            <form
+            <form
+                noValidate
                 onSubmit={(e) => {

68-81: A11y + stable keys for errors (email field).

Add autocomplete/aria and use deterministic keys/ids.

-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
                                     type="email"
                                     value={field.state.value}
                                     onBlur={field.handleBlur}
-                                    onChange={(e) => field.handleChange(e.target.value)}
+                                    onChange={(e) => field.handleChange(e.target.value)}
+                                    autoComplete="email"
+                                    aria-invalid={field.state.meta.errors.length > 0}
+                                    aria-describedby={
+                                      field.state.meta.errors.length ? `${field.name}-error-0` : undefined
+                                    }
                                 />
-                                {field.state.meta.errors.map((error) => (
-                                    <p key={error?.message} className="text-red-500">
+                                {field.state.meta.errors.map((error, i) => (
+                                    <p key={`${field.name}-error-${i}`} id={`${field.name}-error-${i}`} className="text-red-500">
                                         {error?.message}
                                     </p>
                                 ))}

91-104: A11y + stable keys for errors (password field).

Same treatment for password, with proper autocomplete.

-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
                                     type="password"
                                     value={field.state.value}
                                     onBlur={field.handleBlur}
-                                    onChange={(e) => field.handleChange(e.target.value)}
+                                    onChange={(e) => field.handleChange(e.target.value)}
+                                    autoComplete="current-password"
+                                    aria-invalid={field.state.meta.errors.length > 0}
+                                    aria-describedby={
+                                      field.state.meta.errors.length ? `${field.name}-error-0` : undefined
+                                    }
                                 />
-                                {field.state.meta.errors.map((error) => (
-                                    <p key={error?.message} className="text-red-500">
+                                {field.state.meta.errors.map((error, i) => (
+                                    <p key={`${field.name}-error-${i}`} id={`${field.name}-error-${i}`} className="text-red-500">
                                         {error?.message}
                                     </p>
                                 ))}

37-39: Harden error handling fallback.

Avoid assumptions about error shape; provide a safe default.

-                        toast.error(error.error.message || error.error.statusText);
+                        toast.error(
+                          error?.error?.message ?? error?.message ?? "Failed to sign in"
+                        );

109-119: Reduce re-renders with a selector in Subscribe.

Minor perf tidy-up.

-                <form.Subscribe>
-                    {(state) => (
+                <form.Subscribe selector={(s) => [s.canSubmit, s.isSubmitting] as const}>
+                    {([canSubmit, isSubmitting]) => (
                         <Button
                             type="submit"
                             className="w-full"
-                            disabled={!state.canSubmit || state.isSubmitting}
+                            disabled={!canSubmit || isSubmitting}
                         >
-                            {state.isSubmitting ? "Submitting..." : "Sign In"}
+                            {isSubmitting ? "Submitting..." : "Sign In"}
                         </Button>
                     )}
                 </form.Subscribe>
apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs (1)

6-10: Avoid generic else; enumerate frontends explicitly (and drop the or helper).
Our handlebars guideline prefers explicit branches. This also removes reliance on a non‑standard or helper.

Apply this diff:

-{{#if (or (eq frontend "tanstack-start") (eq frontend "next"))}}
+{{#if (eq frontend "tanstack-start")}}
 authComponent.registerRoutes(http, createAuth);
-{{else}}
+{{else if (eq frontend "next")}}
+authComponent.registerRoutes(http, createAuth);
+{{else}}
 authComponent.registerRoutes(http, createAuth, { cors: true });
 {{/if}}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 94b70bc and 2475324.

📒 Files selected for processing (40)
  • apps/cli/src/constants.ts (1 hunks)
  • apps/cli/src/helpers/core/auth-setup.ts (1 hunks)
  • apps/cli/src/helpers/core/convex-codegen.ts (1 hunks)
  • apps/cli/src/helpers/core/create-project.ts (0 hunks)
  • apps/cli/src/helpers/core/env-setup.ts (2 hunks)
  • apps/cli/src/helpers/core/template-manager.ts (1 hunks)
  • apps/cli/src/prompts/auth.ts (1 hunks)
  • apps/cli/src/utils/add-package-deps.ts (3 hunks)
  • apps/cli/src/utils/compatibility-rules.ts (1 hunks)
  • apps/cli/src/utils/config-validation.ts (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.config.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/privateData.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/api/auth/[...all]/route.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/dashboard/page.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-in-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-up-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-client.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-server.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/lib/auth-client.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/routes/dashboard.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/user-menu.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-client.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/api/auth/$.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/dashboard.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/web/react/next/src/components/theme-provider.tsx.hbs (0 hunks)
  • apps/cli/templates/frontend/react/next/src/components/providers.tsx.hbs (2 hunks)
  • apps/cli/templates/frontend/react/tanstack-router/src/main.tsx.hbs (2 hunks)
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs (4 hunks)
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/index.tsx.hbs (2 hunks)
  • apps/cli/templates/frontend/react/web-base/src/components/header.tsx.hbs (2 hunks)
💤 Files with no reviewable changes (2)
  • apps/cli/templates/auth/better-auth/web/react/next/src/components/theme-provider.tsx.hbs
  • apps/cli/src/helpers/core/create-project.ts
✅ Files skipped from review due to trivial changes (2)
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.config.ts.hbs
🚧 Files skipped from review as they are similar to previous changes (34)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-client.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/dashboard.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/lib/auth-client.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbs
  • apps/cli/src/constants.ts
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs
  • apps/cli/templates/frontend/react/web-base/src/components/header.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/routes/dashboard.tsx.hbs
  • apps/cli/src/prompts/auth.ts
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-server.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/api/auth/$.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs
  • apps/cli/src/utils/add-package-deps.ts
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbs
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-client.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs
  • apps/cli/src/utils/compatibility-rules.ts
  • apps/cli/src/helpers/core/env-setup.ts
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/user-menu.tsx.hbs
  • apps/cli/src/utils/config-validation.ts
  • apps/cli/templates/frontend/react/next/src/components/providers.tsx.hbs
  • apps/cli/src/helpers/core/auth-setup.ts
  • apps/cli/templates/auth/better-auth/convex/backend/convex/privateData.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/api/auth/[...all]/route.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/dashboard/page.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-in-form.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/index.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-up-form.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbs
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs
  • apps/cli/templates/frontend/react/tanstack-router/src/main.tsx.hbs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{hbs,handlebars}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

In Handlebars templates, avoid generic if/else blocks; write explicit conditions (e.g., if (eq orm "prisma") and else if (eq orm "drizzle")).

Files:

  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs
🧠 Learnings (2)
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/http.ts : Define HTTP endpoints only in convex/http.ts and wrap handlers with httpAction

Applied to files:

  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs
📚 Learning: 2025-08-24T18:00:39.152Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-08-24T18:00:39.152Z
Learning: Applies to convex/http.ts : HTTP endpoints are registered at the exact path specified in route.path (no implicit prefixes)

Applied to files:

  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (4)
apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs (4)

1-2: Imports look correct for Convex http router and local auth helpers.
Matches Convex’s expected http.ts shape.


4-4: Router init + default export are aligned with Convex conventions.
Good placement per our “define HTTP endpoints only in convex/http.ts” learning.

Also applies to: 12-12


6-10: Remove the unsupported { cors: true } arg; configure CORS in the server and use Better Auth’s trustedOrigins.

registerRoutes(...) does not accept a CORS option — { cors: true } is not supported. Remove the third argument and configure CORS on your HTTP server (Hono/Express/Fastify) and set Better Auth’s trustedOrigins (exact or wildcard) from env/template values; gate dev-only permissive CORS via NODE_ENV if needed.

File: apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs (lines 6–10)

  • Replace the conditional branches with: authComponent.registerRoutes(http, createAuth);
  • Add server-level CORS middleware (origin allow-list from env or dev-only) and pass an allow-list to Better Auth via trustedOrigins.

Likely an incorrect or invalid review comment.


7-9: Confirm auth handlers are wrapped with httpAction.

Verify that authComponent.registerRoutes wraps its HTTP handlers with httpAction; I couldn't find the implementation in this repo (only the template call and ossStats.registerRoutes(http) at packages/backend/convex/http.ts), so this likely lives in the Better Auth package or generated code.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (14)
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs (4)

39-41: Harden error handler with optional chaining + fallback.

Prevents TypeError when fields are missing.

-                    onError: (error) => {
-                        toast.error(error.error.message || error.error.statusText);
-                    },
+                    onError: (error) => {
+                        toast.error(
+                            error?.error?.message ??
+                                error?.error?.statusText ??
+                                "Sign up failed",
+                        );
+                    },

5-5: Fix Zod import (no default export).

Use the named export to prevent type/runtime issues.

-import z from "zod";
+import { z } from "zod";

19-25: Zod validators won’t run without the TanStack Zod adapter.

Register the adapter in useForm.

-    const form = useForm({
+    const form = useForm({
+        validatorAdapter: zodValidator(),
         defaultValues: {

And add the import:

+import { zodValidator } from "@tanstack/zod-form-adapter";

46-50: Schema bug: z.email() does not exist; use z.string().email().

This currently throws at runtime.

-            onSubmit: z.object({
-                name: z.string().min(2, "Name must be at least 2 characters"),
-                email: z.email("Invalid email address"),
-                password: z.string().min(8, "Password must be at least 8 characters"),
-            }),
+            onSubmit: z.object({
+                name: z.string().min(2, "Name must be at least 2 characters"),
+                email: z.string().email("Invalid email address"),
+                password: z.string().min(8, "Password must be at least 8 characters"),
+            }),
apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs (2)

49-57: Follow repo style: prefer function declarations over arrow functions.

Convert the server handler to a named async function.

-const fetchAuth = createServerFn({ method: "GET" }).handler(async () => {
+async function fetchAuthHandler() {
   const { session } = await fetchSession(getWebRequest());
   const sessionCookieName = getCookieName(createAuth);
   const token = getCookie(sessionCookieName);
   return {
     userId: session?.user.id,
     token,
   };
-});
+}
+const fetchAuth = createServerFn({ method: "GET" }).handler(fetchAuthHandler);

118-124: Use function declaration for beforeLoad to match codebase conventions.

-  beforeLoad: async (ctx) => {
+  beforeLoad: async function (ctx) {
     const { userId, token } = await fetchAuth();
     if (token) {
       ctx.context.convexQueryClient.serverHttpClient?.setAuth(token);
     }
     return { userId, token };
   },
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbs (4)

37-39: Make error toast resilient.

-                    onError: (error) => {
-                        toast.error(error.error.message || error.error.statusText);
-                    },
+                    onError: (error) => {
+                        toast.error(
+                            error?.error?.message ??
+                                error?.error?.statusText ??
+                                "Sign in failed",
+                        );
+                    },

5-5: Fix Zod import (no default export).

-import z from "zod";
+import { z } from "zod";

19-24: Register TanStack Zod adapter so validators execute.

-    const form = useForm({
+    const form = useForm({
+        validatorAdapter: zodValidator(),
         defaultValues: {

Add import:

+import { zodValidator } from "@tanstack/zod-form-adapter";

44-47: Schema bug: replace z.email() with z.string().email().

-            onSubmit: z.object({
-                email: z.email("Invalid email address"),
-                password: z.string().min(8, "Password must be at least 8 characters"),
-            }),
+            onSubmit: z.object({
+                email: z.string().email("Invalid email address"),
+                password: z.string().min(8, "Password must be at least 8 characters"),
+            }),
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs (4)

39-41: Harden error toast.

-                    onError: (error) => {
-                        toast.error(error.error.message || error.error.statusText);
-                    },
+                    onError: (error) => {
+                        toast.error(
+                            error?.error?.message ??
+                                error?.error?.statusText ??
+                                "Sign up failed",
+                        );
+                    },

5-5: Fix Zod import (no default export).

-import z from "zod";
+import { z } from "zod";

19-25: Register TanStack Zod adapter so validators execute.

-    const form = useForm({
+    const form = useForm({
+        validatorAdapter: zodValidator(),
         defaultValues: {

Add import:

+import { zodValidator } from "@tanstack/zod-form-adapter";

46-51: Schema bug: replace z.email() with z.string().email().

-            onSubmit: z.object({
-                name: z.string().min(2, "Name must be at least 2 characters"),
-                email: z.email("Invalid email address"),
-                password: z.string().min(8, "Password must be at least 8 characters"),
-            }),
+            onSubmit: z.object({
+                name: z.string().min(2, "Name must be at least 2 characters"),
+                email: z.string().email("Invalid email address"),
+                password: z.string().min(8, "Password must be at least 8 characters"),
+            }),
🧹 Nitpick comments (7)
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-client.ts.hbs (1)

1-6: Consider cross‑domain support and baseURL parity with Router variant.

If the frontend origin differs from the Better‑Auth API during dev, wire crossDomainClient() and a baseURL to avoid cookie/CORS issues. Verify this aligns with your TanStack Start env before adopting.

Example (only if cross‑domain is expected):

-import { convexClient } from "@convex-dev/better-auth/client/plugins";
+import { convexClient, crossDomainClient } from "@convex-dev/better-auth/client/plugins";

-export const authClient = createAuthClient({
-  plugins: [convexClient()],
-});
+export const authClient = createAuthClient({
+  baseURL: typeof window !== "undefined" ? window.location.origin : undefined,
+  plugins: [convexClient(), crossDomainClient()],
+});
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbs (1)

69-75: Minor a11y/UX: add autocomplete attributes.

Helps browsers and password managers.

-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
                                     type="email"
+                                    autoComplete="email"
                                     value={field.state.value}
@@
-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
                                     type="password"
+                                    autoComplete="current-password"
                                     value={field.state.value}

Also applies to: 91-98

apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs (1)

71-77: Minor a11y/UX: add autocomplete attributes.

-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
+                                    autoComplete="name"
                                     value={field.state.value}
@@
-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
                                     type="email"
+                                    autoComplete="email"
                                     value={field.state.value}
@@
-                                <Input
+                                <Input
                                     id={field.name}
                                     name={field.name}
                                     type="password"
+                                    autoComplete="new-password"
                                     value={field.state.value}

Also applies to: 93-100, 116-123

apps/cli/src/utils/compatibility-rules.ts (4)

254-259: Unused _backend parameter — either remove or mark as intentionally unused

If noUnusedParameters/ESLint is enabled, this can error. If you’re keeping the arg for API-shape compatibility, mark it as used.

 export function validatePaymentsCompatibility(
   payments: Payments | undefined,
   auth: Auth | undefined,
-  _backend: Backend | undefined,
+  _backend: Backend | undefined,
   frontends: Frontend[] = [],
 ) {
-  if (!payments || payments === "none") return;
+  // mark intentionally unused param to satisfy linters
+  void _backend;
+  if (!payments || payments === "none") return;

262-267: Simplify auth check and tighten copy

(!auth || auth === "none" || auth !== "better-auth") is equivalent to auth !== "better-auth". Also tweak the message for subject–verb agreement.

-    if (!auth || auth === "none" || auth !== "better-auth") {
+    if (auth !== "better-auth") {
       exitWithError(
-        "Polar payments requires Better Auth. Please use '--auth better-auth' or choose a different payments provider.",
+        "Polar requires Better Auth. Please use '--auth better-auth' or choose a different payments provider.",
       );
     }

269-275: Clarify native-only case in error message

If only native frontends are selected, the current message is a bit vague. Minor copy tweak to call out “native-only” explicitly.

-      exitWithError(
-        "Polar payments requires a web frontend or no frontend. Please select a web frontend or choose a different payments provider.",
-      );
+      exitWithError(
+        "Polar requires a web frontend (or no frontend). Native-only selections are not supported. Add a web frontend or choose a different payments provider.",
+      );

254-276: Add tests to lock in new Polar + Convex allowance

Since the backend gate was removed, add tests that:

  • Polar + Better Auth + Convex + web passes
  • Polar + Better Auth + Convex + native-only fails
  • Polar + non-Better Auth fails

I can draft unit tests in apps/cli/src/utils/tests/compatibility-rules.test.ts validating these paths. Want me to push a test patch?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2475324 and a2097c5.

📒 Files selected for processing (40)
  • apps/cli/src/constants.ts (1 hunks)
  • apps/cli/src/helpers/core/auth-setup.ts (1 hunks)
  • apps/cli/src/helpers/core/convex-codegen.ts (1 hunks)
  • apps/cli/src/helpers/core/create-project.ts (0 hunks)
  • apps/cli/src/helpers/core/env-setup.ts (2 hunks)
  • apps/cli/src/helpers/core/template-manager.ts (1 hunks)
  • apps/cli/src/prompts/auth.ts (1 hunks)
  • apps/cli/src/utils/add-package-deps.ts (3 hunks)
  • apps/cli/src/utils/compatibility-rules.ts (1 hunks)
  • apps/cli/src/utils/config-validation.ts (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.config.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/backend/convex/privateData.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/api/auth/[...all]/route.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/dashboard/page.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-in-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-up-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-client.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-server.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/lib/auth-client.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/routes/dashboard.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/user-menu.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-client.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/api/auth/$.ts.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/dashboard.tsx.hbs (1 hunks)
  • apps/cli/templates/auth/better-auth/web/react/next/src/components/theme-provider.tsx.hbs (0 hunks)
  • apps/cli/templates/frontend/react/next/src/components/providers.tsx.hbs (2 hunks)
  • apps/cli/templates/frontend/react/tanstack-router/src/main.tsx.hbs (2 hunks)
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs (4 hunks)
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/index.tsx.hbs (2 hunks)
  • apps/cli/templates/frontend/react/web-base/src/components/header.tsx.hbs (2 hunks)
💤 Files with no reviewable changes (2)
  • apps/cli/templates/auth/better-auth/web/react/next/src/components/theme-provider.tsx.hbs
  • apps/cli/src/helpers/core/create-project.ts
🚧 Files skipped from review as they are similar to previous changes (32)
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/dashboard.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-client.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/lib/auth-client.ts.hbs
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/src/constants.ts
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-in-form.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/routes/dashboard.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-server.ts.hbs
  • apps/cli/templates/frontend/react/next/src/components/providers.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/user-menu.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbs
  • apps/cli/templates/frontend/react/web-base/src/components/header.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/dashboard/page.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/api/auth/$.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs
  • apps/cli/src/utils/config-validation.ts
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/privateData.ts.hbs
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/api/auth/[...all]/route.ts.hbs
  • apps/cli/templates/frontend/react/tanstack-router/src/main.tsx.hbs
  • apps/cli/src/helpers/core/env-setup.ts
  • apps/cli/src/utils/add-package-deps.ts
  • apps/cli/src/helpers/core/auth-setup.ts
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/index.tsx.hbs
  • apps/cli/src/prompts/auth.ts
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/backend/convex/auth.config.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-up-form.tsx.hbs
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{hbs,handlebars}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

In Handlebars templates, avoid generic if/else blocks; write explicit conditions (e.g., if (eq orm "prisma") and else if (eq orm "drizzle")).

Files:

  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbs
  • apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-client.ts.hbs
  • apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/convex_rules.mdc)

**/*.{ts,tsx}: Use Id from './_generated/dataModel' to type document ids (e.g., Id<'users'>)
Ensure Record key/value types align with validators (e.g., v.record(v.id('users'), v.string()) => Record<Id<'users'>, string>)
Be strict with types for document ids; prefer Id<'table'> over string
Use 'as const' for string literals in discriminated unions
When using Array and Record types, declare with explicit generic types (e.g., const arr: Array = ...)

**/*.{ts,tsx}: Use TypeScript type aliases instead of interface declarations.
Do not use explicit return types in TypeScript.

Files:

  • apps/cli/src/utils/compatibility-rules.ts
**/*.{js,jsx,ts,tsx,mjs,cjs}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{js,jsx,ts,tsx,mjs,cjs}: Do not use dotenv; Bun auto-loads .env
Use Bun.serve() for HTTP/WebSockets; do not use express
Use bun:sqlite for SQLite; do not use better-sqlite3
Use Bun.redis for Redis; do not use ioredis
Use Bun.sql for Postgres; do not use pg or postgres.js
Use built-in WebSocket; do not use ws
Prefer Bun.file over node:fs readFile/writeFile
Use Bun.$ instead of execa for shelling out

Files:

  • apps/cli/src/utils/compatibility-rules.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

Define functions using the standard function declaration syntax, not arrow functions.

Files:

  • apps/cli/src/utils/compatibility-rules.ts
🧠 Learnings (1)
📚 Learning: 2025-09-11T04:31:24.508Z
Learnt from: CR
PR: AmanVarshney01/create-better-t-stack#0
File: .cursor/rules/better-t-stack-repo.mdc:0-0
Timestamp: 2025-09-11T04:31:24.508Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Define functions using the standard function declaration syntax, not arrow functions.

Applied to files:

  • apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs
🧬 Code graph analysis (1)
apps/cli/src/utils/compatibility-rules.ts (2)
apps/cli/src/types.ts (1)
  • Backend (16-16)
apps/cli/test/test-utils.ts (1)
  • Backend (199-199)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (2)
apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs (1)

153-171: Better‑Auth provider wiring looks correct.

ConvexBetterAuthProvider receives client and the exported authClient; SSR token handoff via beforeLoad sets Convex auth. No issues.

apps/cli/src/utils/compatibility-rules.ts (1)

254-276: Quick repo check for stale “Polar x Convex” guards

Verify there are no remaining blockers elsewhere (e.g., config-validation, prompts) that still forbid Polar with Convex.

cursor[bot]

This comment was marked as outdated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
apps/cli/src/helpers/core/env-setup.ts (1)

245-267: Backend env misconfigured: write CONVEX_SITE_URL (not NEXT_PUBLIC_/VITE_) and comment out CLI commands in .env.local

The backend templates read process.env.CONVEX_SITE_URL and process.env.SITE_URL. Writing NEXT_PUBLIC_/VITE_ vars into packages/backend/.env.local means the backend won’t see the value. Also, embedding executable npx commands in .env.local is surprising—comment them.

-const convexCommands = `# Set Convex environment variables
-npx convex env set BETTER_AUTH_SECRET=$(openssl rand -base64 32)
-npx convex env set SITE_URL http://localhost:3001
-
-`;
+const convexCommands = `# Set Convex environment variables
+# Run these once from packages/backend to set Convex env vars:
+# npx convex env set BETTER_AUTH_SECRET "$(openssl rand -base64 32)"
+# npx convex env set SITE_URL "http://localhost:3001"
+
+`;
-const convexBackendVars: EnvVariable[] = [
-  {
-    key: hasNextJs ? "NEXT_PUBLIC_CONVEX_SITE_URL" : "VITE_CONVEX_SITE_URL",
-    value: "",
-    condition: true,
-    comment: "Same as CONVEX_URL but ends in .site",
-  },
-  {
-    key: "SITE_URL",
-    value: "http://localhost:3001",
-    condition: true,
-  },
-];
+const convexBackendVars: EnvVariable[] = [
+  {
+    key: "CONVEX_SITE_URL",
+    value: "",
+    condition: true,
+    comment: "Convex .site URL for the backend (e.g., https://<YOUR_CONVEX_SITE_URL>)",
+  },
+  {
+    key: "SITE_URL",
+    value: "http://localhost:3001",
+    condition: true,
+  },
+];
#!/bin/bash
# Verify which env vars templates consume.
rg -n -C2 -g 'apps/cli/templates/**' \
  -e 'process\.env\.(CONVEX_SITE_URL|SITE_URL|NEXT_PUBLIC_CONVEX_SITE_URL|VITE_CONVEX_SITE_URL)'
🧹 Nitpick comments (4)
apps/cli/src/helpers/core/env-setup.ts (4)

6-11: Use a type alias instead of an interface (project guideline).

Please switch EnvVariable to a type alias.

-export interface EnvVariable {
-	key: string;
-	value: string | null | undefined;
-	condition: boolean;
-	comment?: string;
-}
+export type EnvVariable = {
+	key: string;
+	value: string | null | undefined;
+	condition: boolean;
+	comment?: string;
+};

61-62: .env.example path logic doesn’t handle .env.local

When filePath ends with .env.local, the example file currently resolves to the same path. Generate .env.local.example (or fallback to appending .example).

-const exampleFilePath = filePath.replace(/\.env$/, ".env.example");
+const exampleFilePath = filePath.endsWith(".env")
+	? filePath.replace(/\.env$/, ".env.example")
+	: filePath.endsWith(".env.local")
+	? filePath.replace(/\.env\.local$/, ".env.local.example")
+	: `${filePath}.example`;

70-77: Duplicate keys can be appended to .env.example in a single run

You test only existing exampleEnvContent, not what you queued in exampleContentToAdd, so repeated keys in variables will be duplicated.

- for (const exampleVar of exampleVariables) {
-   const key = exampleVar.split("=")[0];
-   const regex = new RegExp(`^${key}=.*$`, "m");
-   if (!regex.test(exampleEnvContent)) {
-     exampleContentToAdd += `${exampleVar}\n`;
-     exampleModified = true;
-   }
- }
+ const presentKeys = new Set(
+   exampleEnvContent.split("\n").map((l) => l.split("=")[0])
+ );
+ for (const exampleVar of exampleVariables) {
+   const key = exampleVar.split("=")[0];
+   if (!presentKeys.has(key)) {
+     exampleContentToAdd += `${exampleVar}\n`;
+     presentKeys.add(key);
+     exampleModified = true;
+   }
+ }

186-201: Use the SITE URL placeholder and clarify it’s the .site domain

For Better‑Auth + Convex clients, prefer <YOUR_CONVEX_SITE_URL> to avoid confusion with CONVEX_URL.

- key: "NEXT_PUBLIC_CONVEX_SITE_URL",
- value: "https://<YOUR_CONVEX_URL>",
+ key: "NEXT_PUBLIC_CONVEX_SITE_URL",
+ value: "https://<YOUR_CONVEX_SITE_URL>",
+ comment: "Convex .site URL used by the client (Better-Auth callbacks)",
- key: "VITE_CONVEX_SITE_URL",
- value: "https://<YOUR_CONVEX_URL>",
+ key: "VITE_CONVEX_SITE_URL",
+ value: "https://<YOUR_CONVEX_SITE_URL>",
+ comment: "Convex .site URL used by the client (Better-Auth callbacks)",
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 46360b9 and d64ac45.

📒 Files selected for processing (1)
  • apps/cli/src/helpers/core/env-setup.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/convex_rules.mdc)

**/*.{ts,tsx}: Use Id from './_generated/dataModel' to type document ids (e.g., Id<'users'>)
Ensure Record key/value types align with validators (e.g., v.record(v.id('users'), v.string()) => Record<Id<'users'>, string>)
Be strict with types for document ids; prefer Id<'table'> over string
Use 'as const' for string literals in discriminated unions
When using Array and Record types, declare with explicit generic types (e.g., const arr: Array = ...)

**/*.{ts,tsx}: Use TypeScript type aliases instead of interface declarations.
Do not use explicit return types in TypeScript.

Files:

  • apps/cli/src/helpers/core/env-setup.ts
**/*.{js,jsx,ts,tsx,mjs,cjs}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{js,jsx,ts,tsx,mjs,cjs}: Do not use dotenv; Bun auto-loads .env
Use Bun.serve() for HTTP/WebSockets; do not use express
Use bun:sqlite for SQLite; do not use better-sqlite3
Use Bun.redis for Redis; do not use ioredis
Use Bun.sql for Postgres; do not use pg or postgres.js
Use built-in WebSocket; do not use ws
Prefer Bun.file over node:fs readFile/writeFile
Use Bun.$ instead of execa for shelling out

Files:

  • apps/cli/src/helpers/core/env-setup.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

Define functions using the standard function declaration syntax, not arrow functions.

Files:

  • apps/cli/src/helpers/core/env-setup.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cursor Bugbot
🔇 Additional comments (1)
apps/cli/src/helpers/core/env-setup.ts (1)

28-44: Env writer comment support: LGTM.

Prepending “# {comment}” is correct and minimal.

@AmanVarshney01 AmanVarshney01 merged commit 24e33c6 into main Sep 18, 2025
1 check passed
@AmanVarshney01 AmanVarshney01 deleted the better-auth-convex branch September 18, 2025 20:16
navigate({
to: "/dashboard",
});
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Post-Logout Redirect to Protected Route

After signing out, the application redirects to /dashboard. This route is generally protected, resulting in a poor user experience when a signed-out user lands on a page they cannot access.

Additional Locations (2)

Fix in Cursor Fix in Web

},
validators: {
onSubmit: z.object({
email: z.email("Invalid email address"),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant