From 2b098c5d33f69aa09aa63c52855ec8a50cbff8a2 Mon Sep 17 00:00:00 2001 From: Marco Sadjadi Date: Thu, 21 May 2026 00:36:56 +0200 Subject: [PATCH] fix(web): wrap useSearchParams in Suspense so next build can prerender MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /servers/new and /login/callback call useSearchParams() directly, which bails the page out of static rendering and fails `next build` during prerender. Split each into a thin Suspense wrapper + inner component. Latent since `next dev` never prerenders — only surfaces in a prod build. Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/web/app/(dashboard)/servers/new/page.tsx | 24 +++++++++++++++++-- apps/web/app/login/callback/page.tsx | 20 ++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/apps/web/app/(dashboard)/servers/new/page.tsx b/apps/web/app/(dashboard)/servers/new/page.tsx index 3479ed1..7b87977 100644 --- a/apps/web/app/(dashboard)/servers/new/page.tsx +++ b/apps/web/app/(dashboard)/servers/new/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useEffect, useState } from 'react'; +import { Suspense, useEffect, useState } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; import { apiFetch } from '@/lib/api'; import { Button } from '@/components/ui/button'; @@ -82,7 +82,7 @@ function specToEditable(spec: PreviewResponse['spec']): EditableSpec { }; } -export default function NewServerPage() { +function NewServerPageInner() { const router = useRouter(); const [step, setStep] = useState('prompt'); @@ -708,6 +708,26 @@ export default function NewServerPage() { ); } +// useSearchParams() forces client-side rendering — Next requires a Suspense +// boundary around it, or `next build` bails out of static generation. +export default function NewServerPage() { + return ( + +

New MCP server

+
+ +

Loading…

+
+ + } + > + +
+ ); +} + const SHARE_CATEGORIES = [ 'productivity', 'developer-tools', diff --git a/apps/web/app/login/callback/page.tsx b/apps/web/app/login/callback/page.tsx index 6c1e1ea..1ae25b1 100644 --- a/apps/web/app/login/callback/page.tsx +++ b/apps/web/app/login/callback/page.tsx @@ -1,11 +1,11 @@ 'use client'; -import { useEffect, useState } from 'react'; +import { Suspense, useEffect, useState } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; import { Logo } from '@/components/logo'; import { apiFetch } from '@/lib/api'; -export default function CallbackPage() { +function CallbackInner() { const router = useRouter(); const params = useSearchParams(); const token = params.get('token'); @@ -53,3 +53,19 @@ export default function CallbackPage() { ); } + +// useSearchParams() requires a Suspense boundary or `next build` cannot +// statically render this route. +export default function CallbackPage() { + return ( + +

Verifying your magic link…

+ + } + > + +
+ ); +}