Hi everyone,
I’m setting up a bilingual Next.js app (German/English) with next-intl. Locally everything works perfectly, including the language switcher and localized routes. However, when I deploy to Firebase App Hosting, the build fails during prerendering of one route.
Environment
-
Next.js: 15.3.3 (App Router)
-
Node.js (from Firebase buildpack): 22.19.0
-
next-intl: (v3.x)
-
Hosting: Firebase App Hosting (buildpacks)
-
Routing:
appdirectory with locale segment (e.g.,app/[locale]/...)
What I’m trying to do
-
Two locales:
deanden -
Server Components by default, Client Components where needed
-
Using
next-intl’suseLocalein client components and server APIs (getTranslations) in server components -
Works locally:
npm run buildandnpm run startsucceed; language switcher behaves correctly.
What actually happens on deploy
Firebase build starts fine, but crashes while prerendering /sell:
> next build
▲ Next.js 15.3.3
Creating an optimized production build ...
✓ Compiled successfully
Generating static pages (0/120) ...
Error occurred prerendering page "/sell". Read more: https://nextjs.org/docs/messages/prerender-error
Error:
at s (/workspace/.next/server/chunks/1622.js:28:89259)
at t.useLocale (/workspace/.next/server/chunks/1622.js:28:89331)
at t.default (/workspace/.next/server/chunks/1622.js:28:114344)
...
Export encountered an error on /sell/page: /sell, exiting the build.
⨯ Next.js build worker exited with code: 1
So the build fails with a prerender error seemingly related to useLocale being evaluated at build time.
Project structure (relevant bits)
app/
[locale]/
layout.tsx
sell/
page.tsx
components/
LocaleSwitcher.tsx // 'use client' + useLocale()
next-intl usage (simplified)
// app/[locale]/layout.tsx
import {unstable_setRequestLocale} from 'next-intl/server';
export function generateStaticParams() {
return [{locale: 'en'}, {locale: 'de'}];
}
export default function RootLayout({
children,
params: {locale}
}: {
children: React.ReactNode;
params: {locale: string};
}) {
unstable_setRequestLocale(locale);
return <html lang={locale}><body>{children}</body></html>;
}
// app/[locale]/sell/page.tsx (Server Component)
import {getTranslations} from 'next-intl/server';
export default async function SellPage() {
const t = await getTranslations('Sell');
return <h1>{t('title')}</h1>;
}
// components/LocaleSwitcher.tsx (Client Component)
'use client';
import {useLocale} from 'next-intl';
export default function LocaleSwitcher() {
const locale = useLocale();
return <span>{locale}</span>;
}
What I’ve tried so far
-
Disable prerender for the failing route
Adding toapp/[locale]/sell/page.tsx:export const dynamic = 'force-dynamic'; export const revalidate = 0;➜ This avoids build-time evaluation and lets the route render at request time, which works. But I’d prefer to keep SSG if possible.
-
Audit imports on
/sell
Ensured there’s no directwindow,document,localStorage,headers(), orcookies()usage in server code. Any client-only logic is behind'use client'anduseEffect. -
Static params & locale segment
ConfirmedgenerateStaticParamsreturns both locales and the route is under[locale]. -
Local reproduction under Node 22
Built locally with Node 22.19 vianvmand couldn’t reproduce the crash—the error only appears in Firebase’s build environment.
Questions
-
Is there a known issue with
next-intl+ Next 15 on Firebase App Hosting whereuseLocale(or related code) gets executed during static export unexpectedly? -
Are there Firebase buildpack settings that force static generation of certain routes even if they depend on request locale?
-
What’s the recommended way to keep
/sellstatically generated while usingnext-intl—and avoiduseLocalebeing evaluated at build time? -
Any guidance on diagnosing which import in the
/selltree is causinguseLocaleto run on the server during prerender? (The stack trace points into compiled chunks.)
Ideal outcome
-
Keep
/sellas SSG for bothdeanden. -
Ensure
useLocaleis only used in client components at runtime. -
Successful
next buildin Firebase without needingdynamic = 'force-dynamic'.
Thanks a lot for any pointers! I can share more snippets if needed.