-
-
Notifications
You must be signed in to change notification settings - Fork 203
feat(cli): add convex + better-auth #582
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
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 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. 📒 Files selected for processing (43)
Note Other AI code review bot(s) detectedCodeRabbit 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. WalkthroughAdds 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
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)
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
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. Comment |
There was a problem hiding this 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 missingAvoid 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 feedbackSurface 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 booleanAvoid 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 ofcors: trueOpen 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 loadsAvoid rendering an empty button if
user?.nameis 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 componentsMixing
@/...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 shapesDefensive fallback avoids runtime errors if
error.erroris 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 requestsGate
useQuerybehind 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-invalidandaria-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: truewith 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
optionsOnlyvia 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
📒 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.hbsapps/cli/templates/auth/better-auth/convex/backend/convex/http.ts.hbsapps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbsapps/cli/templates/auth/better-auth/convex/backend/convex/privateData.ts.hbsapps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbsapps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbsapps/cli/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbsapps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbsapps/cli/templates/frontend/react/tanstack-router/src/main.tsx.hbsapps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/routes/dashboard.tsx.hbsapps/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.tsapps/cli/src/helpers/core/template-manager.tsapps/cli/src/constants.tsapps/cli/src/prompts/auth.tsapps/cli/src/utils/compatibility-rules.tsapps/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
UseBun.serve()for HTTP/WebSockets; do not useexpress
Usebun:sqlitefor SQLite; do not usebetter-sqlite3
UseBun.redisfor Redis; do not useioredis
UseBun.sqlfor Postgres; do not usepgorpostgres.js
Use built-inWebSocket; do not usews
PreferBun.fileovernode:fsreadFile/writeFile
UseBun.$instead ofexecafor shelling out
Files:
apps/cli/src/helpers/core/auth-setup.tsapps/cli/src/helpers/core/template-manager.tsapps/cli/src/constants.tsapps/cli/src/prompts/auth.tsapps/cli/src/utils/compatibility-rules.tsapps/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.tsapps/cli/src/helpers/core/template-manager.tsapps/cli/src/constants.tsapps/cli/src/prompts/auth.tsapps/cli/src/utils/compatibility-rules.tsapps/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.hbsapps/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.hbsapps/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.hbsapps/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 presentThis 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 fineNo functional impact. LGTM.
262-276: Confirm intent: Polar no longer blocked on Convex backendYou 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 rulesRoutes are registered from a single
convex/http.tsand exported via a defaulthttpRouter()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.signOutuses 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.betterAuthwith 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"; |
There was a problem hiding this comment.
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.
apps/cli/templates/auth/better-auth/convex/backend/convex/privateData.ts.hbs
Show resolved
Hide resolved
| import { useForm } from "@tanstack/react-form"; | ||
| import { useNavigate } from "@tanstack/react-router"; | ||
| import { toast } from "sonner"; | ||
| import z from "zod"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix Zod import and schema (current code won’t type-check/run)
- Zod exports
zas a named export, not default. emailmust bez.string().email(...), notz.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.
...plates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs
Show resolved
Hide resolved
...plates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs
Show resolved
Hide resolved
...plates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs
Show resolved
Hide resolved
There was a problem hiding this 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 matchesKeys 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 filestrimEnd() 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 logicReduce 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 typosType 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 writesCompute if pkgJson changed before write to reduce churn.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 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.tsapps/cli/src/utils/add-package-deps.tsapps/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
UseBun.serve()for HTTP/WebSockets; do not useexpress
Usebun:sqlitefor SQLite; do not usebetter-sqlite3
UseBun.redisfor Redis; do not useioredis
UseBun.sqlfor Postgres; do not usepgorpostgres.js
Use built-inWebSocket; do not usews
PreferBun.fileovernode:fsreadFile/writeFile
UseBun.$instead ofexecafor shelling out
Files:
apps/cli/src/helpers/core/env-setup.tsapps/cli/src/utils/add-package-deps.tsapps/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.tsapps/cli/src/utils/add-package-deps.tsapps/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 coverageLooks 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 detectionNext/TanStack/Vite splits and clientDirExists guard are correct.
138-149: Expo setup aligns with server echo of @better-auth/expoNative deps wiring looks correct.
apps/cli/src/utils/add-package-deps.ts (1)
23-24: LGTM: override > map fallback resolutionOverride precedence is correct for both deps and devDeps.
Also applies to: 32-33
There was a problem hiding this 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_URLlookup insidecreateAuthusingctx.env.get("SITE_URL")and validate it. This is required in Convex.-const siteUrl = process.env.SITE_URL!;(and define
siteUrlinsidecreateAuthas 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. Usev.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 queriesThe
useQuerycall might fail if the user is not authenticated. Consider wrapping it with theAuthenticatedcomponent 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 callbacksFor 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.errormay 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
📒 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.hbsapps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/lib/auth-client.ts.hbsapps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbsapps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/dashboard.tsx.hbsapps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbsapps/cli/templates/auth/better-auth/convex/backend/convex/auth.ts.hbsapps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/api/auth/$.ts.hbsapps/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
UseBun.serve()for HTTP/WebSockets; do not useexpress
Usebun:sqlitefor SQLite; do not usebetter-sqlite3
UseBun.redisfor Redis; do not useioredis
UseBun.sqlfor Postgres; do not usepgorpostgres.js
Use built-inWebSocket; do not usews
PreferBun.fileovernode:fsreadFile/writeFile
UseBun.$instead ofexecafor 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 setupThe 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-AuthThe 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 integrationThe 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.
| 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); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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.
...mplates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbs
Show resolved
Hide resolved
...mplates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbs
Show resolved
Hide resolved
...mplates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs
Show resolved
Hide resolved
...mplates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs
Show resolved
Hide resolved
.../templates/auth/better-auth/convex/web/react/tanstack-start/src/components/user-menu.tsx.hbs
Show resolved
Hide resolved
.../cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/api/auth/$.ts.hbs
Show resolved
Hide resolved
apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs
Show resolved
Hide resolved
apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs
Show resolved
Hide resolved
There was a problem hiding this 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.
ConvexProviderisn’t used whenauth === "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 genericelseper template guidelines.Per the Handlebars guideline, enumerate all supported
authvalues rather than using a genericelse. 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.erroris 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
📒 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.hbsapps/cli/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbsapps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-in-form.tsx.hbsapps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-client.ts.hbsapps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-up-form.tsx.hbsapps/cli/templates/frontend/react/next/src/components/providers.tsx.hbsapps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-server.ts.hbsapps/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 versionnpm 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 callTypeScript 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/**'
.../cli/templates/auth/better-auth/convex/web/react/next/src/app/api/auth/[...all]/route.ts.hbs
Show resolved
Hide resolved
apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-up-form.tsx.hbs
Show resolved
Hide resolved
apps/cli/templates/auth/better-auth/convex/web/react/next/src/lib/auth-server.ts.hbs
Show resolved
Hide resolved
There was a problem hiding this 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
📒 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.hbsapps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbsapps/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.hbsapps/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.
There was a problem hiding this 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
📒 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
useStateand 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/apiexist at runtime:
- The backend package should not restrict deep imports via
exports.- Convex codegen must run to materialize
_generated/apibefore 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.
apps/cli/templates/auth/better-auth/convex/web/react/next/src/app/dashboard/page.tsx.hbs
Show resolved
Hide resolved
There was a problem hiding this 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
zis a named export.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.
useQueryreturnsundefinedwhile loading andnullif 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: useDropdownMenuItem’sonSelectinstead 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
📒 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.hbsapps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbsapps/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.
...templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs
Show resolved
Hide resolved
94b70bc to
2475324
Compare
There was a problem hiding this 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.onSubmitmust be a function; passing a Zod schema object will throw at runtime.- Replace
z.email(...)withz.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-adapteris 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*' -nAlso 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 theorhelper).
Our handlebars guideline prefers explicit branches. This also removes reliance on a non‑standardorhelper.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
📒 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.hbsapps/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 withhttpAction.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.
2475324 to
a2097c5
Compare
There was a problem hiding this 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; usez.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 forbeforeLoadto 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: replacez.email()withz.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: replacez.email()withz.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 abaseURLto 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_backendparameter — either remove or mark as intentionally unusedIf
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 toauth !== "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 messageIf 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 allowanceSince 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
📒 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.hbsapps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbsapps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbsapps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-client.ts.hbsapps/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
UseBun.serve()for HTTP/WebSockets; do not useexpress
Usebun:sqlitefor SQLite; do not usebetter-sqlite3
UseBun.redisfor Redis; do not useioredis
UseBun.sqlfor Postgres; do not usepgorpostgres.js
Use built-inWebSocket; do not usews
PreferBun.fileovernode:fsreadFile/writeFile
UseBun.$instead ofexecafor 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.
ConvexBetterAuthProviderreceivesclientand the exportedauthClient; SSR token handoff viabeforeLoadsets Convex auth. No issues.apps/cli/src/utils/compatibility-rules.ts (1)
254-276: Quick repo check for stale “Polar x Convex” guardsVerify there are no remaining blockers elsewhere (e.g., config-validation, prompts) that still forbid Polar with Convex.
There was a problem hiding this 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.localThe 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.localWhen 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 runYou 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 domainFor 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
📒 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
UseBun.serve()for HTTP/WebSockets; do not useexpress
Usebun:sqlitefor SQLite; do not usebetter-sqlite3
UseBun.redisfor Redis; do not useioredis
UseBun.sqlfor Postgres; do not usepgorpostgres.js
Use built-inWebSocket; do not usews
PreferBun.fileovernode:fsreadFile/writeFile
UseBun.$instead ofexecafor 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.
eceed36 to
cc1603c
Compare
cc1603c to
914c6cb
Compare
| navigate({ | ||
| to: "/dashboard", | ||
| }); | ||
| }, |
There was a problem hiding this comment.
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)
| }, | ||
| validators: { | ||
| onSubmit: z.object({ | ||
| email: z.email("Invalid email address"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Email Validation Bug in Sign-Up/Sign-In Forms
The email validation in the sign-up and sign-in forms uses z.email(), but Zod expects z.string().email() for validating email strings.
Additional Locations (5)
apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs#L47-L48apps/cli/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs#L47-L48apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-in-form.tsx.hbs#L40-L41apps/cli/templates/auth/better-auth/convex/web/react/next/src/components/sign-up-form.tsx.hbs#L42-L43apps/cli/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs#L44-L45
Summary by CodeRabbit
New Features
Bug Fixes
Chores
Tests/Tooling