Rendering Strategies
Dinou is Static by Default. It intelligently adapts its rendering strategy based on your code and configuration, from pure SSG to full SSR.
Automatic Static Bailout
You don't need to manually configure pages as "Static" or "Dynamic". Dinou analyzes your code to determine the appropriate strategy. By default, pages are pre-rendered (Static Rendering) at server startup.
However, if your component accesses request-specific data (cookies, headers, or search params), Dinou automatically "bails out" of static generation and switches to Dynamic Rendering for that specific route.
// src/profile/page.tsx
import { getContext } from "dinou";
export default async function Profile() {
const ctx = getContext();
// ⚠️ Accessing cookies triggers the Automatic Static Bailout
// This page will now be rendered on every request (dynamic)
const token = ctx.req.cookies.session_token;
const user = await fetchUser(token);
return <h1>Hello, {user.name}</h1>;
}Triggers
getContext() (to read cookies, headers, or query parameters) in a Server Component.Forced Dynamic Rendering
Sometimes you want a page to be rendered on every request even if you don't use cookies or headers (e.g., displaying random data, or always-fresh DB content without caching).
You can force dynamic rendering by exporting a dynamic function from your page_functions.ts file.
// src/random/page_functions.ts
export function dynamic() {
return true; // Forces Dynamic Rendering on every request
}// src/random/page.tsx
// Note: Server Components do not need to be async if they don't use await
export default function Page() {
return <div suppressHydrationWarning>Random: {Math.random()}</div>;
}Incremental Static Regeneration (ISR)
ISR allows you to update static pages after the server has started. You can rebuild specific pages in the background as traffic comes in, ensuring users always see relatively fresh content without restarting the server or rebuilding the entire project.
// src/blog/page_functions.ts
export function revalidate() {
return 60000; // Time in milliseconds (1 minute)
}revalidate returns 0 or is undefined, the page remains static indefinitely (standard SSG).Incremental Static Generation (ISG)
While ISR updates existing pages, ISG allows you to generate new pages that weren't pre-rendered at server startup.
This is particularly useful for large e-commerce sites or blogs where building thousands of pages upfront is too slow. You can pre-render the most popular pages at server startup and let the rest be generated on demand.
Implementation
Simply omit the paths you want to defer from getStaticPaths. Dinou will handle the routing automatically.
// src/products/[id]/page_functions.ts
export async function getStaticPaths() {
// Only generate the top 10 products at server startup
const topProducts = await db.getTopProducts(10);
return topProducts.map(p => p.id);
// Any ID not in this list will be generated
// on-demand when a user visits /products/999
}The First Visit & Revalidation
When a user requests a path that wasn't pre-rendered at server startup, Dinou renders it on the server (like SSR), caches the result, and serves it as static HTML for all future visitors.
Important: These pages are fully integrated with ISR. If a revalidate function is defined in page_functions.ts (returning > 0), the generated page will not be static forever—it will regenerate in the background when stale.
Advanced Control APIs for ISG
Dinou v5 introduces advanced validation exports in page_functions.ts to secure dynamic route parameters and generation:
Validates route parameters before serving or generating. Returning false aborts the request with a 404, preventing invalid generation.
export function validateParams(params) {
// Reject route parameter and return 404 instantly
return typeof params.id === "string" && /^\d+$/.test(params.id);
}Optionally disables ISG completely. If it returns false, any route parameters not returned by getStaticPaths yield a 404 instantly.
export function allowISG() {
// Disable dynamic on-demand generation; serve getStaticPaths ONLY
return false;
}