Hi,
I’m building a project in v0 that includes login functionality. I’m using Supabase to manage authentication. When I set everything up in v0, it asks for the two Supabase keys. After providing them, I test the app in v0’s preview, and everything works fine: I log in using the credentials of a user I created in Supabase, and the login is successful. I’m redirected to the home page of the app.
The issue arises after deploying the app through v0. Once the deployment is complete, I visit the project’s URL, which takes me to /login
. I enter the credentials, and according to the logs, the authentication is successful. However, I’m not redirected to /
. Instead, the app remains stuck on /login
, continuously throwing a 307 Redirect.
Does anyone know why this happens?
Here’s some of the code generated by v0:
middleware.ts
import { createMiddlewareClient } from "@supabase/auth-helpers-nextjs"
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
export async function middleware(req: NextRequest) {
const res = NextResponse.next()
const supabase = createMiddlewareClient({ req, res })
await supabase.auth.getSession()
return res
}
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}
supabase.ts
import { createClient } from "@supabase/supabase-js"
export const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
page.tsx
import { createServerComponentClient } from "@supabase/auth-helpers-nextjs"
import { cookies } from "next/headers"
import { redirect } from "next/navigation"
export default async function DashboardPage() {
const supabase = createServerComponentClient({ cookies })
const {
data: { session },
} = await supabase.auth.getSession()
if (!session) {
redirect("/")
}
return (
<div className="min-h-screen flex items-center justify-center">
<h1 className="text-4xl font-bold">Hello, how are you?</h1>
</div>
)
}
login-form.tsx
"use client"
import { useState } from "react"
import { useRouter } from "next/navigation"
import { createClientComponentClient } from "@supabase/auth-helpers-nextjs"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
export default function LoginForm() {
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const [error, setError] = useState<string | null>(null)
const router = useRouter()
const supabase = createClientComponentClient()
const handleLogin = async (e: React.FormEvent) => {
e.preventDefault()
try {
const { error } = await supabase.auth.signInWithPassword({
email,
password,
})
if (error) throw error
router.refresh()
} catch (error) {
setError("Error logging in. Please check your credentials.")
}
}
return (
<div className="min-h-screen flex items-center justify-center">
<Card className="w-[350px]">
<CardHeader>
<CardTitle className="text-2xl text-center">Login</CardTitle>
</CardHeader>
<CardContent>
<form onSubmit={handleLogin} className="space-y-4">
<div className="space-y-2">
<Input
type="email"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>
<div className="space-y-2">
<Input
type="password"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
{error && <p className="text-red-500 text-sm">{error}</p>}
<Button type="submit" className="w-full">
Login
</Button>
</form>
</CardContent>
</Card>
</div>
)
}
page.tsx
import { createServerComponentClient } from "@supabase/auth-helpers-nextjs"
import { cookies } from "next/headers"
import { redirect } from "next/navigation"
import LoginForm from "./login-form"
export default async function LoginPage() {
const supabase = createServerComponentClient({ cookies })
const {
data: { session },
} = await supabase.auth.getSession()
if (session) {
redirect("/dashboard")
}
return <LoginForm />
}
Any help is greatly appreciated!