fix: Wrap useSearchParams in Suspense boundary
Build and Push Docker Image / lint-and-typecheck (push) Successful in 1m1s Details
Build and Push Docker Image / build (push) Failing after 2m31s Details

Next.js 15 requires useSearchParams() to be wrapped in a
Suspense boundary for static page generation.

- Split LoginForm into separate component
- Add Suspense wrapper with loading skeleton
- Fixes build error on /login page

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Matt 2026-01-06 12:52:41 +01:00
parent 56b919fe4a
commit d21dc88812
1 changed files with 100 additions and 72 deletions

View File

@ -1,6 +1,6 @@
'use client' 'use client'
import { useState } from 'react' import { Suspense, useState } from 'react'
import { useRouter, useSearchParams } from 'next/navigation' import { useRouter, useSearchParams } from 'next/navigation'
import { signIn } from 'next-auth/react' import { signIn } from 'next-auth/react'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
@ -15,7 +15,7 @@ import {
CardTitle, CardTitle,
} from '@/components/ui/card' } from '@/components/ui/card'
export default function LoginPage() { function LoginForm() {
const router = useRouter() const router = useRouter()
const searchParams = useSearchParams() const searchParams = useSearchParams()
const callbackUrl = searchParams.get('callbackUrl') || '/' const callbackUrl = searchParams.get('callbackUrl') || '/'
@ -55,7 +55,6 @@ export default function LoginPage() {
} }
return ( return (
<div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
<Card className="w-full max-w-md"> <Card className="w-full max-w-md">
<CardHeader className="space-y-1"> <CardHeader className="space-y-1">
<CardTitle className="text-2xl font-bold text-center"> <CardTitle className="text-2xl font-bold text-center">
@ -128,6 +127,35 @@ export default function LoginPage() {
</CardFooter> </CardFooter>
</form> </form>
</Card> </Card>
)
}
function LoginFormSkeleton() {
return (
<Card className="w-full max-w-md">
<CardHeader className="space-y-1">
<CardTitle className="text-2xl font-bold text-center">
LetsBe Hub
</CardTitle>
<CardDescription className="text-center">
Loading...
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="h-10 bg-gray-200 rounded animate-pulse" />
<div className="h-10 bg-gray-200 rounded animate-pulse" />
<div className="h-10 bg-gray-200 rounded animate-pulse" />
</CardContent>
</Card>
)
}
export default function LoginPage() {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
<Suspense fallback={<LoginFormSkeleton />}>
<LoginForm />
</Suspense>
</div> </div>
) )
} }