HonestPDF introduces full static site generation across all 38 routes and 20 locales in this update, replacing on-demand server-side rendering with pre-built, CDN-cached pages.
TL;DR
All tool, legal, and comparison pages now use SSG via force-static. The blog uses ISR with a 1-hour revalidation window. The build process generates 1,148 static pages at deploy time, meaning visitors get CDN-cached responses instead of waiting on server renders. The root cause of unintended SSR was next-intl reading Accept-Language headers at request time, which setRequestLocale corrects.
What's New
- Added
setRequestLocaleto 35+ page components across the app to prevent next-intl from forcing SSR via Accept-Language header detection - Applied
export const dynamic = 'force-static'to all tool, legal, and comparison route segments to enforce static generation at the Next.js level - Migrated the blog from SSR to Incremental Static Regeneration (ISR) with a
revalidate: 3600(1-hour) cadence - Build now successfully pre-generates 1,148 static pages (38 routes x 20 locales) during
next build - All statically generated pages are now eligible for CDN edge caching, reducing origin server load
How to Use
If you are running a multilingual Next.js app with next-intl and your pages are not static despite using generateStaticParams, the fix is adding setRequestLocale at the top of each page component:
import { setRequestLocale } from 'next-intl/server';
export default async function Page({ params }: { params: { locale: string } }) {
setRequestLocale(params.locale);
// rest of your component
}
For ISR with a revalidation interval:
export const revalidate = 3600; // revalidate every hour
For fully static routes with no revalidation:
export const dynamic = 'force-static';
FAQ
Why were pages still SSR even after adding generateStaticParams?
next-intl reads the Accept-Language request header by default to detect locale. That header only exists at request time, which forces Next.js into SSR mode even when static params are defined. Calling setRequestLocale explicitly bypasses that detection and tells next-intl to use the locale from the route segment instead.
What is the difference between SSG and ISR here?
Tool, legal, and comparison pages use pure SSG: they are generated once at build time and never change until the next deploy. The blog uses ISR, which generates pages at build time but re-generates them in the background if a request comes in after the revalidation window (1 hour). This means new blog posts go live within an hour without a full site rebuild.
Does this affect all 20 supported languages?
Yes. Every route is generated for all 20 locales at build time. The 1,148 page count is 38 routes multiplied by 20 locales.
Will users see stale content after this change?
For static pages (tool, legal, comparison): content updates on the next deploy. For blog pages on ISR: content refreshes within 1 hour of a change being published. There is no meaningful staleness risk for the static pages since they do not change frequently.