From b41b03644809c567ec02da3cfcbd06379e4dd270 Mon Sep 17 00:00:00 2001 From: jvcbyte Date: Sat, 25 Oct 2025 13:32:30 +0100 Subject: [PATCH 1/3] fix: resolve Vercel deployment configuration issues - Add vercel.json configuration for proper deployment - Fix tsconfig.json noEmit setting for production builds - Fix package.json lint script to use next lint - Create .env.example with required environment variables - Ensure all builds pass locally before deployment --- frontend/.env.example | 15 +++++++++++++++ frontend/package.json | 2 +- frontend/tsconfig.json | 2 +- frontend/vercel.json | 9 +++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 frontend/.env.example create mode 100644 frontend/vercel.json diff --git a/frontend/.env.example b/frontend/.env.example new file mode 100644 index 0000000..06a3831 --- /dev/null +++ b/frontend/.env.example @@ -0,0 +1,15 @@ +# Frontend Environment Variables +# Copy this to your Vercel project settings + +# Backend API URL (required for API proxy) +NEXT_PUBLIC_BACKEND_URL=https://your-backend-api.com + +# Thirdweb Configuration (required for wallet functionality) +NEXT_PUBLIC_THIRDWEB_CLIENT_ID=your_thirdweb_client_id + +# Blockchain RPC URLs (optional - defaults provided) +NEXT_PUBLIC_RPC_LISK=https://rpc.lisk.com +NEXT_PUBLIC_RPC_LISK_SEPOLIA=https://sepolia-rpc.lisk.com + +# Other environment variables as needed +NODE_ENV=production diff --git a/frontend/package.json b/frontend/package.json index ac87fd2..f40abbb 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,7 +6,7 @@ "dev": "next dev --turbopack", "build": "next build --turbopack", "start": "next start", - "lint": "eslint" + "lint": "next lint" }, "dependencies": { "@hookform/resolvers": "^5.2.2", diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index c133409..ee38357 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -5,7 +5,7 @@ "allowJs": true, "skipLibCheck": true, "strict": true, - "noEmit": true, + "noEmit": false, "esModuleInterop": true, "module": "esnext", "moduleResolution": "bundler", diff --git a/frontend/vercel.json b/frontend/vercel.json new file mode 100644 index 0000000..63c6810 --- /dev/null +++ b/frontend/vercel.json @@ -0,0 +1,9 @@ +{ + "buildCommand": "pnpm build", + "outputDirectory": ".next", + "framework": "nextjs", + "installCommand": "pnpm install", + "env": { + "NODE_ENV": "production" + } +} From 3a95a40d1d66c2eceea123b40e54ee1e770f3efd Mon Sep 17 00:00:00 2001 From: jvcbyte Date: Sat, 25 Oct 2025 13:33:39 +0100 Subject: [PATCH 2/3] rm frontend/.env.example --- frontend/.env.example | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 frontend/.env.example diff --git a/frontend/.env.example b/frontend/.env.example deleted file mode 100644 index 06a3831..0000000 --- a/frontend/.env.example +++ /dev/null @@ -1,15 +0,0 @@ -# Frontend Environment Variables -# Copy this to your Vercel project settings - -# Backend API URL (required for API proxy) -NEXT_PUBLIC_BACKEND_URL=https://your-backend-api.com - -# Thirdweb Configuration (required for wallet functionality) -NEXT_PUBLIC_THIRDWEB_CLIENT_ID=your_thirdweb_client_id - -# Blockchain RPC URLs (optional - defaults provided) -NEXT_PUBLIC_RPC_LISK=https://rpc.lisk.com -NEXT_PUBLIC_RPC_LISK_SEPOLIA=https://sepolia-rpc.lisk.com - -# Other environment variables as needed -NODE_ENV=production From 17ecace57257a61831e7debdcf2998e5294b8a18 Mon Sep 17 00:00:00 2001 From: jvcbyte Date: Sat, 25 Oct 2025 15:27:28 +0100 Subject: [PATCH 3/3] feat: isAuthenticated >= true, redirect / --- frontend/src/app/(app)/layout.tsx | 22 +++++++++++++++++++ frontend/src/components/layout/app-header.tsx | 2 +- frontend/src/providers/auth-context.tsx | 16 +++++++++----- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/frontend/src/app/(app)/layout.tsx b/frontend/src/app/(app)/layout.tsx index b2afcc9..319c8ad 100644 --- a/frontend/src/app/(app)/layout.tsx +++ b/frontend/src/app/(app)/layout.tsx @@ -1,8 +1,30 @@ 'use client'; import type { ReactElement, ReactNode } from 'react'; +import { useEffect } from 'react'; import { AppShell } from '@/components/layout/app-shell'; +import { useAuth } from '@/providers/auth-context'; +import { useRouter } from 'next/navigation'; +import { Loader2 } from 'lucide-react'; export default function ProtectedLayout({ children }: { children: ReactNode }): ReactElement { + const { isAuthenticated } = useAuth(); + const router = useRouter(); + + useEffect(() => { + if (!isAuthenticated) { + router.push('/'); + } + }, [isAuthenticated, router]); + + if (!isAuthenticated) { + return ( +
+

Loading

+ +
+ ); + } + return {children}; } diff --git a/frontend/src/components/layout/app-header.tsx b/frontend/src/components/layout/app-header.tsx index 3a4ae49..edfa98c 100644 --- a/frontend/src/components/layout/app-header.tsx +++ b/frontend/src/components/layout/app-header.tsx @@ -141,7 +141,7 @@ export function AppHeader({ onMobileMenuToggle }: AppHeaderProps = {}): ReactEle variant="ghost" size="md" onClick={() => { - void signOut(); + signOut(); }} leftIcon={} className={cn('border border-transparent text-slate-300 hover:border-rose-500/50 hover:bg-rose-500/10 hover:text-rose-200', isLoading && 'pointer-events-none opacity-60')} diff --git a/frontend/src/providers/auth-context.tsx b/frontend/src/providers/auth-context.tsx index 3b2bdf4..d58b6b1 100644 --- a/frontend/src/providers/auth-context.tsx +++ b/frontend/src/providers/auth-context.tsx @@ -5,6 +5,7 @@ import type { BackendUser } from '@/types/api'; import { useCallback, useMemo } from 'react'; import { useActiveAccount, useActiveWallet } from 'thirdweb/react'; import { client } from '@/lib/thirdweb'; +import { useRouter } from 'next/navigation'; export type AuthContextValue = { user: BackendUser | null; @@ -28,6 +29,7 @@ export function useAuth(): AuthContextValue { // Always call hooks first, then handle the conditional logic const account = useActiveAccount(); const wallet = useActiveWallet(); + const router = useRouter(); const address = account?.address ?? null; @@ -46,11 +48,15 @@ export function useAuth(): AuthContextValue { const signOut = useCallback(async () => { try { - await wallet?.disconnect?.(); - } catch { - // ignore + if (wallet) { + await wallet.disconnect?.(); + } + await new Promise(resolve => setTimeout(resolve, 100)); + router.push('/'); + } catch (error) { + router.push('/'); } - }, [wallet]); + }, [wallet, router]); const refreshProfile = useCallback(async (): Promise => { return user; @@ -58,13 +64,11 @@ export function useAuth(): AuthContextValue { const signInWithEmail = useCallback(async (_email: string): Promise => { // TODO: Implement email authentication when backend is ready - console.log('Email sign-in attempted:', _email); return false; }, []); const resendVerification = useCallback(async (_email: string): Promise => { // TODO: Implement email verification when backend is ready - console.log('Email verification requested:', _email); return false; }, []);