Skip to content

better auth working #3

Merged
Akashamba merged 6 commits intomainfrom
akash/clerk-to-betterauth
Jun 5, 2025
Merged

better auth working #3
Akashamba merged 6 commits intomainfrom
akash/clerk-to-betterauth

Conversation

@Akashamba
Copy link
Owner

@Akashamba Akashamba commented Jun 5, 2025

Summary by CodeRabbit

  • New Features

    • Integrated a new authentication system using "better-auth" with support for Google sign-in.
    • Added new authentication-related database tables for users, sessions, accounts, and verifications.
    • Introduced an API route for authentication handling.
  • Improvements

    • Updated the articles page to handle user sessions and render content based on authentication status.
    • Refactored the Navbar to display real user information and authentication actions.
    • Enhanced article management with a new articles page supporting search, create, edit, and delete features.
  • Bug Fixes

    • Ensured empty strings are used for article tags when none are provided.
  • Chores

    • Removed legacy authentication and middleware related to Clerk.
    • Updated database schema and migration files for improved article and authentication support.
    • Added the "better-auth" package as a dependency.
    • Cleaned up old and unused components.

@netlify
Copy link

netlify bot commented Jun 5, 2025

Deploy Preview for flipside1 ready!

Name Link
🔨 Latest commit 353453a
🔍 Latest deploy log https://app.netlify.com/projects/flipside1/deploys/68415e0085db1b0008448cd8
😎 Deploy Preview https://deploy-preview-3--flipside1.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link

coderabbitai bot commented Jun 5, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This update transitions the authentication system from Clerk to "better-auth" with Drizzle ORM integration, introducing new authentication modules, database schemas, and API route handlers. It updates the articles UI to use the new auth client, removes Clerk and related middleware, and refactors the articles router to the new session management approach. Several obsolete files and migrations are deleted, and the database schema for articles is consolidated.

Changes

Files / Groups Change Summary
package.json Added better-auth dependency.
src/lib/auth.ts, src/lib/auth-client.ts Introduced new authentication modules using "better-auth" and Drizzle ORM.
src/app/api/auth/[...all]/route.ts Added new API route handlers for authentication (POST/GET) using the new auth logic.
src/server/db/auth-schema.ts Added Drizzle schema for auth tables: user, session, account, verification.
src/app/articles/articles-page.tsx New ArticlesPage component for managing articles with CRUD, search, and modal logic.
src/app/articles/page.tsx Replaced ArticlesPage with a session-aware page that conditionally renders content based on authentication.
src/components/navbar.tsx Refactored to use real authentication client instead of mock user state.
src/components/modals/edit-article-modal.tsx Ensured tags property always has a string value when updating articles.
src/app/layout.tsx Removed ClerkProvider; now only uses TRPCReactProvider.
src/app/(auth)/sign-in/page.tsx, src/app/(auth)/sign-up/page.tsx Removed Clerk UI components; now render empty styled containers.
src/server/api/routers/articles.ts Switched authentication from Clerk to new auth client/session management.
src/server/db/schema.ts Removed "Clerk user ID" comment from userId field.
drizzle.config.ts Changed schema property to an array, added commented auth schema path.
drizzle/0000_classy_lilandra.sql Added new flipside_article table with updated schema and index.
drizzle/meta/_journal.json, drizzle/meta/0000_snapshot.json Updated migration journal and schema snapshot to reflect new schema state.
drizzle/0000_harsh_iron_fist.sql, drizzle/0001_glamorous_ben_parker.sql, drizzle/0002_magical_nico_minoru.sql, drizzle/0003_perpetual_spectrum.sql, drizzle/0004_opposite_dark_phoenix.sql Deleted old migration SQL files.
drizzle/meta/0001_snapshot.json, drizzle/meta/0002_snapshot.json, drizzle/meta/0003_snapshot.json, drizzle/meta/0004_snapshot.json Deleted old schema snapshot files.
src/components/old:ArticleList.tsx, src/components/old:HomePage.tsx, src/components/old:LandingPage.tsx Deleted legacy article and landing page components.
src/middleware.ts Deleted Clerk middleware and matcher configuration.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Navbar
    participant authClient
    participant ArticlesPage
    participant API
    participant DB

    User->>Navbar: Loads app
    Navbar->>authClient: useSession()
    authClient-->>Navbar: Session/User info

    User->>ArticlesPage: Navigates to articles
    ArticlesPage->>authClient: useSession()
    alt No session
        ArticlesPage-->>User: Show "No session" message
    else Session exists
        ArticlesPage->>API: Fetch articles (with user session)
        API->>DB: Query articles by userId
        DB-->>API: Return articles
        API-->>ArticlesPage: Article data
        ArticlesPage-->>User: Render articles UI
    end

    User->>Navbar: Clicks "Sign In"
    Navbar->>authClient: signIn.social("google", callbackURL)
    authClient-->>User: Redirect to Google OAuth

    User->>Navbar: Clicks "Sign Out"
    Navbar->>authClient: signOut()
    authClient-->>User: Session cleared
Loading

Poem

🐇✨
Out with the Clerk, in with auth anew,
Drizzle and better-auth—what a crew!
Articles now sparkle, sessions hold sway,
Old files hop away, new schemas in play.
With every commit, the garden grows bright—
Hopping forward with code,
Everything feels right!

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

drizzle.config.ts

Oops! Something went wrong! :(

ESLint: 9.28.0

ESLint couldn't find the plugin "eslint-plugin-react-hooks".

(The package "eslint-plugin-react-hooks" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-react-hooks@latest --save-dev

The plugin "eslint-plugin-react-hooks" was referenced from the config file in " » eslint-config-next/core-web-vitals » /node_modules/.pnpm/eslint-config-next@15.3.3_eslint@9.28.0_typescript@5.8.3/node_modules/eslint-config-next/index.js".

If you still can't figure out the problem, please see https://eslint.org/docs/latest/use/troubleshooting.

src/app/layout.tsx

Oops! Something went wrong! :(

ESLint: 9.28.0

ESLint couldn't find the plugin "eslint-plugin-react-hooks".

(The package "eslint-plugin-react-hooks" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-react-hooks@latest --save-dev

The plugin "eslint-plugin-react-hooks" was referenced from the config file in " » eslint-config-next/core-web-vitals » /node_modules/.pnpm/eslint-config-next@15.3.3_eslint@9.28.0_typescript@5.8.3/node_modules/eslint-config-next/index.js".

If you still can't figure out the problem, please see https://eslint.org/docs/latest/use/troubleshooting.

src/app/articles/page.tsx

Oops! Something went wrong! :(

ESLint: 9.28.0

ESLint couldn't find the plugin "eslint-plugin-react-hooks".

(The package "eslint-plugin-react-hooks" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-react-hooks@latest --save-dev

The plugin "eslint-plugin-react-hooks" was referenced from the config file in " » eslint-config-next/core-web-vitals » /node_modules/.pnpm/eslint-config-next@15.3.3_eslint@9.28.0_typescript@5.8.3/node_modules/eslint-config-next/index.js".

If you still can't figure out the problem, please see https://eslint.org/docs/latest/use/troubleshooting.

  • 7 others

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de51b1d and 353453a.

📒 Files selected for processing (26)
  • drizzle.config.ts (1 hunks)
  • drizzle/0000_classy_lilandra.sql (1 hunks)
  • drizzle/0000_harsh_iron_fist.sql (0 hunks)
  • drizzle/0001_glamorous_ben_parker.sql (0 hunks)
  • drizzle/0002_magical_nico_minoru.sql (0 hunks)
  • drizzle/0003_perpetual_spectrum.sql (0 hunks)
  • drizzle/0004_opposite_dark_phoenix.sql (0 hunks)
  • drizzle/meta/0000_snapshot.json (4 hunks)
  • drizzle/meta/0001_snapshot.json (0 hunks)
  • drizzle/meta/0002_snapshot.json (0 hunks)
  • drizzle/meta/0003_snapshot.json (0 hunks)
  • drizzle/meta/0004_snapshot.json (0 hunks)
  • drizzle/meta/_journal.json (1 hunks)
  • src/app/(auth)/sign-in/page.tsx (1 hunks)
  • src/app/(auth)/sign-up/page.tsx (1 hunks)
  • src/app/articles/articles-page.tsx (1 hunks)
  • src/app/articles/page.tsx (1 hunks)
  • src/app/layout.tsx (1 hunks)
  • src/components/modals/edit-article-modal.tsx (1 hunks)
  • src/components/navbar.tsx (8 hunks)
  • src/components/old:ArticleList.tsx (0 hunks)
  • src/components/old:HomePage.tsx (0 hunks)
  • src/components/old:LandingPage.tsx (0 hunks)
  • src/middleware.ts (0 hunks)
  • src/server/api/routers/articles.ts (5 hunks)
  • src/server/db/schema.ts (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Akashamba Akashamba marked this pull request as draft June 5, 2025 06:59
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🔭 Outside diff range comments (1)
package.json (1)

24-37: 💡 Verification agent

🧩 Analysis chain

Potential conflict with existing authentication provider.

The addition of better-auth while retaining @clerk/nextjs may cause conflicts since both are authentication solutions. If you're migrating from Clerk to better-auth, consider removing the Clerk dependency once the migration is complete.


🏁 Script executed:

#!/bin/bash
# Check for any remaining Clerk usage in the codebase
rg -i "clerk|useAuth|useUser" --type ts --type tsx --type js --type jsx

Length of output: 101


🏁 Script executed:

#!/bin/bash
# Correctly search for any remaining Clerk usage in JS/TS files
rg "@clerk/nextjs" -t ts -t tsx -t js -t jsx
rg -i "useAuth|useUser" -t ts -t tsx -t js -t jsx

Length of output: 152


🏁 Script executed:

#!/bin/bash
# Search for any remaining Clerk imports and hook usage in code without relying on ripgrep file‐type detection
rg "from ['\"]@clerk/nextjs" -g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx'
rg "@clerk/nextjs"                  -g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx'
rg -i "useAuth|useUser"            -g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx'

Length of output: 999


Remove residual Clerk imports before completing migration to better-auth

The following files still import from @clerk/nextjs, indicating Clerk hasn’t been fully removed. Please replace or remove these before finalizing your switch to better-auth:

• src/middleware.ts — clerkMiddleware
• src/server/api/routers/articles.ts — auth
• src/app/layout.tsx — ClerkProvider
• src/app/(auth)/sign-in/page.tsx — SignIn as ClerkSignInUI
• src/app/(auth)/sign-up/page.tsx — SignUp as ClerkSignUpUI

Ensure you’ve updated these to use your new auth solution (or removed them if no longer needed) to avoid bundle bloat and runtime conflicts.

🧹 Nitpick comments (7)
src/lib/auth.ts (1)

6-15: Consider supplying a signing secret & other Better-Auth options

betterAuth() usually expects a top-level secret, cookies, etc. Relying on package defaults may produce weak signing keys in non-production environments. Double-check the docs and pass an explicit secret (e.g. process.env.AUTH_SECRET!) to stay compliant with OWASP recommendations.

src/app/articles/page.tsx (2)

24-26: signOut should surface failure states as well

Same rationale as above—wrap the call in try/​catch and give the user visual feedback if it fails.


30-39: UI/UX nit – label buttons descriptively

“Test” / “signOut” don’t convey intent in production. Consider “Sign in with Google” and “Sign out”.

src/app/articles/old-page.tsx (2)

118-126: Search placeholder advertises “description” but filter ignores it

Either update the placeholder or include description in the predicate:

-    return articles.filter((article) => {
-      const matchesSearch = article.title
-        .toLowerCase()
-        .includes(searchQuery.toLowerCase());
-      return matchesSearch;
-    });
+    const q = searchQuery.toLowerCase();
+    return articles.filter((a) =>
+      a.title.toLowerCase().includes(q) ||
+      (a.description ?? "").toLowerCase().includes(q)
+    );

50-63: handleNewArticle / handleUpdateArticle only log – consider cache invalidation

The comments hint at a missing refetch. Call utils.articles.getAll.invalidate() (or optimistic update) so the UI reflects the mutation.

src/server/db/auth-schema.ts (2)

7-7: Use clearer boolean default syntax.

The expression .$defaultFn(() => !1) is unnecessarily obscure. Use false directly for better readability.

- emailVerified: boolean('email_verified').$defaultFn(() => !1).notNull(),
+ emailVerified: boolean('email_verified').default(false).notNull(),

9-10: Consider using SQL defaults for timestamps and auto-update behavior.

The current approach uses JavaScript Date objects for defaults, but SQL-level defaults are generally preferred for consistency and performance. Also consider auto-update behavior for updatedAt fields.

- createdAt: timestamp('created_at').$defaultFn(() => new Date).notNull(),
- updatedAt: timestamp('updated_at').$defaultFn(() => new Date).notNull()
+ createdAt: timestamp('created_at').defaultNow().notNull(),
+ updatedAt: timestamp('updated_at').defaultNow().notNull().$onUpdate(() => new Date())

Note: You may need to handle the auto-update behavior at the application level if Drizzle doesn't support $onUpdate for your use case.

Also applies to: 17-18, 36-37

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3ea1ef4 and de51b1d.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • drizzle.config.ts (1 hunks)
  • drizzle/0005_freezing_spyke.sql (1 hunks)
  • drizzle/meta/0005_snapshot.json (1 hunks)
  • drizzle/meta/_journal.json (1 hunks)
  • package.json (1 hunks)
  • src/app/api/auth/[...all]/route.ts (1 hunks)
  • src/app/articles/old-page.tsx (1 hunks)
  • src/app/articles/page.tsx (1 hunks)
  • src/lib/auth-client.ts (1 hunks)
  • src/lib/auth.ts (1 hunks)
  • src/server/db/auth-schema.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/lib/auth.ts (2)
src/server/db/index.ts (1)
  • db (18-18)
src/server/db/auth-schema.ts (4)
  • verification (40-47)
  • account (24-38)
  • session (13-22)
  • user (3-11)
src/app/api/auth/[...all]/route.ts (1)
src/lib/auth.ts (1)
  • auth (6-22)
src/app/articles/old-page.tsx (5)
src/server/db/schema.ts (1)
  • articles (20-34)
src/trpc/react.tsx (1)
  • api (25-25)
src/lib/types.ts (1)
  • Article (1-11)
src/components/ui/button.tsx (1)
  • Button (59-59)
src/components/ui/input.tsx (1)
  • Input (21-21)
🔇 Additional comments (6)
drizzle/meta/_journal.json (1)

39-46: Migration journal entry looks correct.

The new migration entry follows the proper format and is consistent with existing entries.

src/app/api/auth/[...all]/route.ts (1)

1-4: Clean and correct better-auth integration.

The API route implementation follows the standard better-auth pattern for Next.js integration. The dynamic catch-all route will properly handle all authentication endpoints.

src/lib/auth-client.ts (1)

1-5: Proper client-side authentication setup.

The auth client configuration is clean and follows better-auth best practices. The commented baseURL is appropriate as it defaults to the current domain.

drizzle.config.ts (1)

6-6: Correct schema configuration for multiple files.

The update to include both schema files is necessary for Drizzle Kit to process the new authentication tables alongside existing schemas.

drizzle/0005_freezing_spyke.sql (1)

1-50: Authentication schema migration looks well-structured.

The migration properly defines the four core authentication tables with appropriate constraints, data types, and referential integrity. The cascade delete relationships ensure orphaned records are cleaned up when users are deleted.

src/server/db/auth-schema.ts (1)

21-21:

Details

✅ Verification successful

Verify foreign key relationships match migration.

The foreign key definitions look correct with proper cascade delete behavior. Ensure these match the SQL migration exactly to avoid schema drift.

Also applies to: 28-28


🏁 Script executed:

#!/bin/bash
# Verify that the TypeScript schema foreign keys match the SQL migration
echo "Checking foreign key consistency between schema and migration..."

# Extract foreign key definitions from migration
echo "=== Migration Foreign Keys ==="
grep -A 2 -B 2 "FOREIGN KEY" drizzle/0005_freezing_spyke.sql

# Extract foreign key references from TypeScript schema
echo "=== TypeScript Schema References ==="
grep -n "references.*onDelete" src/server/db/auth-schema.ts

Length of output: 970


Confirmed: Foreign key definitions match migration

  • In drizzle/0005_freezing_spyke.sql:
    • account.user_id → user.id ON DELETE cascade, ON UPDATE no action
    • session.user_id → user.id ON DELETE cascade, ON UPDATE no action
  • In src/server/db/auth-schema.ts (lines 21 & 28):
    .references(() => user.id, { onDelete: 'cascade' }) (Drizzle’s default onUpdate is no action)

No discrepancies found—schema and migration are in sync.

Comment on lines +17 to +20
google: {
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
},
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Guard against missing Google OAuth env-vars instead of type-casting them away

Using as string coerces potential undefined values to string, hiding mis-configuration until the first runtime call to the provider. Prefer an explicit assertion or validation step so the app fails fast and predictably:

-      clientId: process.env.GOOGLE_CLIENT_ID as string,
-      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
+      clientId: process.env.GOOGLE_CLIENT_ID!,
+      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,

or, better, centralise env-var validation with Zod / @bogey/envsafe and import from there.


🏁 Script executed:

#!/bin/bash
set -e

echo "=== Searching for Zod-based env schemas ==="
rg -n "z\\.object" || true

echo "=== Searching for @bogey/envsafe usage ==="
rg -n "envsafe" || true

echo "=== Locating GOOGLE_CLIENT_ID references ==="
rg -n "GOOGLE_CLIENT_ID" || true

echo "=== Inspecting raw process.env access patterns ==="
rg -n "process.env" || true

Length of output: 1612


🏁 Script executed:

sed -n '1,200p' src/env.js || true

Length of output: 1415


Add missing Google OAuth env vars to central env schema and use env import

To ensure fail-fast validation and eliminate unsafe casts, register your Google keys in the shared schema and consume them via the validated env:

• In src/env.js (or src/env.ts), under server and runtimeEnv:

 export const env = createEnv({
   server: {
     DATABASE_URL: z.string().url(),
     NODE_ENV: z.enum(["development","test","production"]).default("development"),
+    GOOGLE_CLIENT_ID: z.string(),
+    GOOGLE_CLIENT_SECRET: z.string(),
   },
   …
   runtimeEnv: {
     DATABASE_URL: process.env.DATABASE_URL,
     NODE_ENV: process.env.NODE_ENV,
+    GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID!,
+    GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET!,
   },
   …
 });

• In src/lib/auth.ts, import the validated env and replace the raw casts:

-import { … } from "next-auth";
+import { env } from "~/env";
…
 google: {
-  clientId: process.env.GOOGLE_CLIENT_ID as string,
-  clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
+  clientId: env.GOOGLE_CLIENT_ID,
+  clientSecret: env.GOOGLE_CLIENT_SECRET,
 },

This removes the unsafe as string, centralizes validation with Zod, and guarantees that missing vars break the build rather than fail at runtime.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
google: {
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
},
google: {
- clientId: process.env.GOOGLE_CLIENT_ID as string,
- clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
+ clientId: env.GOOGLE_CLIENT_ID,
+ clientSecret: env.GOOGLE_CLIENT_SECRET,
},
🤖 Prompt for AI Agents
In src/lib/auth.ts around lines 17 to 20, avoid using 'as string' to cast Google
OAuth environment variables directly from process.env, as this can hide missing
configuration until runtime. Instead, add these Google OAuth variables to the
central environment schema (e.g., in src/env.js or src/env.ts) using a
validation library like Zod or @bogey/envsafe, then import the validated env
object into auth.ts and use the validated variables from there. This ensures
fail-fast validation and removes unsafe casts, causing the app to fail at build
time if the variables are missing.

Comment on lines +8 to +14
const signIn = async () => {
const data = await authClient.signIn.social({
provider: "google",
callbackURL: "/articles",
});
}, [articles, searchQuery]);

const handleNewArticle = () => {
// Refresh articles list - in real app, this would refetch from API
console.log("Refreshing articles list...");
console.log(data);
// If ID token is provided no redirection will happen, and the user will be signed in directly.
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling around the async signIn flow

signIn.social() may reject (network error, popup blocked, provider error). A swallowed rejection bubbles to the console in development and is silent in prod UI:

-  const signIn = async () => {
-    const data = await authClient.signIn.social({
-      provider: "google",
-      callbackURL: "/articles",
-    });
-    console.log(data);
+  const signIn = async () => {
+    try {
+      const data = await authClient.signIn.social({
+        provider: "google",
+        callbackURL: "/articles",
+      });
+      console.log(data);
+    } catch (err) {
+      console.error("Google sign-in failed", err);
+    }
   };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const signIn = async () => {
const data = await authClient.signIn.social({
provider: "google",
callbackURL: "/articles",
});
}, [articles, searchQuery]);
const handleNewArticle = () => {
// Refresh articles list - in real app, this would refetch from API
console.log("Refreshing articles list...");
console.log(data);
// If ID token is provided no redirection will happen, and the user will be signed in directly.
const signIn = async () => {
try {
const data = await authClient.signIn.social({
provider: "google",
callbackURL: "/articles",
});
console.log(data);
} catch (err) {
console.error("Google sign-in failed", err);
}
// If ID token is provided no redirection will happen, and the user will be signed in directly.
};
🤖 Prompt for AI Agents
In src/app/articles/page.tsx around lines 8 to 14, the async signIn function
calls signIn.social() without error handling, which can cause unhandled promise
rejections on failures. Wrap the call to signIn.social() in a try-catch block to
catch any errors, log or handle them appropriately, and prevent silent failures
in production.

Comment on lines +65 to +71
const handleDeleteArticle = async (id: string) => {
try {
deleteArticle.mutateAsync({ id: id });
} catch (error) {
console.log("Failed to delete article", error);
}
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

mutateAsync is not awaited, so the catch never triggers

try/catch around an un-awaited promise only captures sync errors. Await the mutation (or attach .catch) to handle API failures correctly:

-      deleteArticle.mutateAsync({ id: id });
+      await deleteArticle.mutateAsync({ id });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleDeleteArticle = async (id: string) => {
try {
deleteArticle.mutateAsync({ id: id });
} catch (error) {
console.log("Failed to delete article", error);
}
};
const handleDeleteArticle = async (id: string) => {
try {
- deleteArticle.mutateAsync({ id: id });
+ await deleteArticle.mutateAsync({ id });
} catch (error) {
console.log("Failed to delete article", error);
}
};
🤖 Prompt for AI Agents
In src/app/articles/old-page.tsx around lines 65 to 71, the async function
handleDeleteArticle calls deleteArticle.mutateAsync without awaiting it, so the
try/catch block does not catch errors from the promise. Fix this by adding await
before deleteArticle.mutateAsync to properly handle and catch any asynchronous
errors during the mutation.

Comment on lines +18 to +23
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Missing foreign key constraint for flipside_article.user_id.

The flipside_article table has a user_id field but no foreign key constraint to the user table. This could lead to orphaned articles when users are deleted.

Consider adding a foreign key constraint:

ALTER TABLE "flipside_article" ADD CONSTRAINT "flipside_article_user_id_user_id_fk" 
FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
🤖 Prompt for AI Agents
In drizzle/meta/0005_snapshot.json around lines 18 to 23, the user_id field in
the flipside_article table lacks a foreign key constraint referencing the user
table, risking orphaned records. Add a foreign key constraint on user_id that
references the id column of the user table with ON DELETE cascade and ON UPDATE
no action to maintain referential integrity.

Comment on lines +45 to +46
createdAt: timestamp('created_at').$defaultFn(() => new Date),
updatedAt: timestamp('updated_at').$defaultFn(() => new Date)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Inconsistent timestamp nullability in verification table.

The verification table has nullable timestamps while other tables use non-null timestamps. This inconsistency could lead to confusion and potential issues.

- createdAt: timestamp('created_at').$defaultFn(() => new Date),
- updatedAt: timestamp('updated_at').$defaultFn(() => new Date)
+ createdAt: timestamp('created_at').defaultNow().notNull(),
+ updatedAt: timestamp('updated_at').defaultNow().notNull()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
createdAt: timestamp('created_at').$defaultFn(() => new Date),
updatedAt: timestamp('updated_at').$defaultFn(() => new Date)
createdAt: timestamp('created_at').defaultNow().notNull(),
updatedAt: timestamp('updated_at').defaultNow().notNull()
🤖 Prompt for AI Agents
In src/server/db/auth-schema.ts around lines 45 to 46, the timestamps for
createdAt and updatedAt are currently nullable in the verification table, which
is inconsistent with other tables that use non-nullable timestamps. Update the
timestamp definitions to be non-nullable by removing any nullable settings,
ensuring createdAt and updatedAt always have valid timestamp values to maintain
consistency across tables.

@Akashamba Akashamba changed the title better auth working but not fully integrated better auth working Jun 5, 2025
@Akashamba Akashamba marked this pull request as ready for review June 5, 2025 09:12
@Akashamba Akashamba merged commit 82de195 into main Jun 5, 2025
4 of 6 checks passed
@Akashamba Akashamba deleted the akash/clerk-to-betterauth branch June 5, 2025 09:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant