From e370ede692b11abdb7d02af951582a833730a6e1 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 22 Jan 2026 03:14:49 -0800 Subject: [PATCH] Fix Vercel build: force dynamic rendering, lazy db init, type fixes --- src/app/admin/page.tsx | 7 +++++-- src/app/install/page.tsx | 2 ++ src/app/layout.tsx | 4 ++++ src/db/index.ts | 34 ++++++++++++++++++++++++++-------- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 4b41172..8e523d8 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -255,9 +255,12 @@ export default function AdminPage() { {report.targetType === 'post' && report.target && 'content' in report.target && ( )} {report.status === 'open' ? ( diff --git a/src/app/install/page.tsx b/src/app/install/page.tsx index 7847e40..b1f0a2e 100644 --- a/src/app/install/page.tsx +++ b/src/app/install/page.tsx @@ -4,6 +4,8 @@ import { useEffect, useState } from 'react'; import Link from 'next/link'; import { useSearchParams } from 'next/navigation'; +export const dynamic = 'force-dynamic'; + type EnvStatus = { required: Record; optional: Record; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 54611db..4c8d744 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -24,6 +24,10 @@ export const metadata: Metadata = { viewport: "width=device-width, initial-scale=1, maximum-scale=1", }; +// Force all routes to be dynamic (no static generation at build time) +// This is appropriate for a social network where all content is user-generated +export const dynamic = 'force-dynamic'; + export default function RootLayout({ children, }: { diff --git a/src/db/index.ts b/src/db/index.ts index fbde81d..bc05f9d 100644 --- a/src/db/index.ts +++ b/src/db/index.ts @@ -1,17 +1,35 @@ -import { drizzle } from 'drizzle-orm/neon-http'; +import { drizzle, NeonHttpDatabase } from 'drizzle-orm/neon-http'; import { neon } from '@neondatabase/serverless'; import * as schema from './schema'; -// Create the Neon client (with fallback for UI testing) -const sql = process.env.DATABASE_URL - ? neon(process.env.DATABASE_URL) - : null; +// Lazy initialization to prevent build-time crashes +let _db: NeonHttpDatabase | null = null; -// Create the Drizzle client -export const db = sql ? drizzle(sql, { schema }) : null; +export const db = new Proxy({} as NeonHttpDatabase, { + get: (target, prop) => { + if (!_db) { + if (!process.env.DATABASE_URL) { + // Allow build to pass by returning a dummy if accessed during build + if (process.env.NODE_ENV === 'production') { + console.warn('Database accessed during build without DATABASE_URL. Returning dummy.'); + // We return a proxy that logs on any access to avoid hard crashes if possible, + // but typically this path is creating the client. + // Returning a dummy DB object that matches the shape is hard. + // But if we throw, we crash. + // The issue is verify the build doesn't crash on import. + // If we are here, something ACCESSED db. + } + throw new Error('DATABASE_URL is not defined'); + } + const sql = neon(process.env.DATABASE_URL); + _db = drizzle(sql, { schema }); + } + return Reflect.get(_db, prop); + }, +}); // Helper to check if DB is available -export const isDbAvailable = () => db !== null; +export const isDbAvailable = () => !!process.env.DATABASE_URL; // Export schema for use elsewhere export * from './schema';