📚 API Reference: Components & Utilities
Comprehensive reference for Dinou's built-in components, hooks, and utilities available in both server and client environments.
1. Components (dinou)
<Link>
The primary way to navigate between pages with client-side transitions, automatic prefetching, and cache control.
import { Link } from "dinou";
// Absolute path
<Link href="/dashboard">Home</Link>
// Relative path (go deeper)
<Link href="./settings">Settings</Link>
// Relative path (sibling)
<Link href="../profile">Profile</Link>
// With options
<Link href="/volatile-data" fresh prefetch={false}>
Live Status
</Link>| Prop | Type | Default | Description |
|---|---|---|---|
| href | string | — | Target path. Supports absolute and relative paths. |
| prefetch | boolean | true | Preload code and data on hover/viewport |
| fresh | boolean | false | Bypass client-side cache, fetch fresh data |
| ...props | HTMLAnchor | — | Standard anchor attributes (className, target, etc.) |
Path Resolution
- Absolute: Starts with
/(e.g./about) - Relative (Child): No slash or
./(e.g.,teamfrom/about→/about/team) - Relative (Sibling): Starts with
../(e.g.,../contactfrom/about/team→/about/contact)
<ClientRedirect>
Utility component that triggers immediate client-side navigation when rendered. Recommended to use redirect() helper instead for better server-side handling.
import { ClientRedirect } from "dinou";
// Forces navigation to home
return <ClientRedirect to="/" />;Useful when you need to trigger navigation from within component rendering logic, but redirect() is generally preferred.
2. Hooks & Utilities (dinou)
Functions available in both Server and Client environments.
redirect(destination)
A polymorphic redirect utility that immediately halts execution and redirects the user. Works everywhere across the framework: in Server Components, Client Components, Server Functions (Server Actions), and page functions lifecycle hooks (like getProps).
| Context | Behavior |
|---|---|
| Initial SSR (Headers unsent) | Performs a native HTTP 307 redirect directly on the server (critical for SEO and fast hard-navigations). |
| Active Stream / Client-side | Renders <ClientRedirect> to perform a fast client-side transition without browser reloads. |
- Absolute Paths: Supports routing to absolute paths (e.g.
/dashboard) and fully qualified external URLs (e.g.https://google.com). - Relative Paths: Resolves relative paths automatically relative to the current route (e.g., redirecting to
./successfrom/checkoutnavigates to/checkout/success). - Server Functions: Can be thrown or returned in Server Functions to trigger redirects in response to client interactions.
- Lifecycle Hooks: Can be used within
getPropsinpage_functions.tsto shield pages and redirect users before they render.
import { redirect } from "dinou";
// 1. In a Server Component or Client Component
export default function Page() {
if (!isAuthenticated) {
return redirect("/login");
}
return <div>Welcome!</div>;
}
// 2. In a page_functions.ts hook
export async function getProps() {
const user = await checkSession();
if (!user) {
return redirect("../login"); // Relative redirect
}
return { user };
}
// 3. In a Server Function ("use server")
export async function handleFormSubmit() {
"use server";
await savePreferences();
return redirect("./profile"); // Redirect relative to the form route
}useSearchParams() (Client Only)
Returns a standard URLSearchParams object to read query string parameters inside Client Components.
"use client";
import { useSearchParams } from "dinou";
export default function SearchPage() {
const searchParams = useSearchParams();
const query = searchParams.get("q");
return <div>Result: {query}</div>;
}⚠️ Hydration Behavior & Mismatch Warning
On statically pre-rendered pages (SSG), the server renders Client Components with empty search parameters at build time. On the client, they will hydrate with the actual browser URL search parameters.
If the UI immediately renders elements or text depending on the search parameters, this will trigger a React hydration mismatch error (Error #418).
- Option 1 (Defer State - Recommended): Defer rendering or using the search parameters until the component has mounted in the browser (by copying the search params to local state inside a
useEffect):"use client"; import { useSearchParams } from "dinou"; import { useState, useEffect } from "react"; export default function SearchPage() { const rawSearchParams = useSearchParams(); const [searchParams, setSearchParams] = useState(new URLSearchParams()); useEffect(() => { // Only updates in the client after hydration is complete setSearchParams(rawSearchParams); }, [rawSearchParams]); const query = searchParams.get("q"); return <div>Result: {query}</div>; } - Option 2 (Forced Dynamic Rendering): Switch the route to dynamic rendering on every request by exporting
export function dynamic() { return true; }from itspage_functions.ts. This ensures the server always generates the content dynamically with the actual query parameters, avoiding mismatches.
At server startup in production, Dinou pre-renders static pages. If a Server Component reads dynamic request data (like search params or cookies), Dinou automatically bails out and marks the route as Dynamic. However, since Client Components do not execute their component functions on the server during pre-rendering, their hooks cannot trigger a bailout. As a result, routes using search params only in Client Components remain static, rendering with empty params at build time and causing hydration mismatches in the browser unless handled properly (e.g. using Option 1).
Show Technical Details (for Ejected Code)
Dinou executes a three-phase static generation pipeline (via the generateStatic process in generate-static.js):
- Phase 1: Analysis & Bailout Discovery (
buildStaticPagesinbuild-static-pages.js)The generator crawls all routes and resolves their layout/page component tree. It mock-renders the tree using
asyncRenderJSXToClientJSXin-memory.- Server Components: If a Server Component accesses the request context (e.g.,
getContext().req.query), a Proxy trap intercepts the access and triggers an Automatic Static Bailout. The route is marked as Dynamic and no static files are generated. - Client Components: Client Components represent client-side code. During layout nesting and component resolution via
asyncRenderJSXToClientJSX, they are treated as reference points and their function bodies are not executed. Because their component logic is not run, they cannot trigger the request context Proxy traps, and no static bailout occurs (the route remains marked as Static).
- Server Components: If a Server Component accesses the request context (e.g.,
- Phase 2: RSC Payload Generation (
generateStaticRSCsingenerate-static-rscs.js)For all routes successfully marked as static in Phase 1, the generator renders the JSX tree using React's native
renderToPipeableStreamand saves the React Flight binary payload to disk asrsc.rsc. - Phase 3: Static HTML Generation (
generateStaticPagesingenerate-static-pages.js)Finally, the generator reads each
rsc.rscfile from disk, reconstructs the JSX tree using React'screateFromNodeStream, renders the markup to static HTML using React'srenderToPipeableStream(fromreact-dom/server), and writes it to disk asindex.html.
This hook cannot be called in Server Components because React Flight prohibits running Client Module functions on the server. To read query parameters in a Server Component, use getContext() instead:
import { getContext } from "dinou";
export default async function Page() {
const ctx = getContext();
const query = ctx.req.query; // Object containing query params
const q = query.q;
return <div>Result: {q}</div>;
}usePathname() (Client Only)
Returns the current URL pathname as a string (e.g., /blog/post-1) inside Client Components.
"use client";
import { usePathname } from "dinou";
export default function Navigation() {
const pathname = usePathname();
return <div>Current path: {pathname}</div>;
}This hook cannot be called in Server Components. To read the pathname in a Server Component, use getContext():
import { getContext } from "dinou";
export default async function Page() {
const ctx = getContext();
const pathname = ctx.req.path; // Current URL path
return <div>Current path: {pathname}</div>;
}useRouter() (Client Only)
Provides programmatic navigation methods inside Client Components.
"use client";
import { useRouter } from "dinou";
export default function Controls() {
const router = useRouter();
return (
<div>
<button onClick={() => router.push("/home")}>Push</button>
<button onClick={() => router.replace("/home")}>Replace</button>
<button onClick={() => router.back()}>Back</button>
<button onClick={() => router.forward()}>Forward</button>
<button onClick={() => router.refresh()}>Refresh Data</button>
</div>
);
}| Method | Description |
|---|---|
| push(href, options?) | Navigates to new URL (adds to history). Supports options.fresh (boolean) to bypass the cache. |
| replace(href, options?) | Replaces current URL in history. Supports options.fresh (boolean) to bypass the cache. |
| back() | Goes back in history |
| forward() | Goes forward in history |
| refresh() | Soft reload: refetches server data without browser refresh |
3. Server-Only Utilities (dinou)
getContext()
Retrieves the request/response context. Server-side execution contexts only (Server Components, page_functions/getProps, and "use server" Server Functions).
import { getContext } from "dinou";
export default async function Profile() {
const ctx = getContext();
// Access request data
const token = ctx.req.cookies.session_token;
const userAgent = ctx.req.headers["user-agent"];
// Set response headers
ctx.res.setHeader("Cache-Control", "public, max-age=3600");
return <div>...</div>;
}⚠️ Security Warning: `getContext` in Client Components
"use client";
import { getContext } from "dinou";
// ❌ DANGEROUS PATTERN - Data leaks to HTML!
export default function UserProfile() {
const ctx = getContext(); // Runs on server during SSR
return <div>{ctx.req.headers["authorization"]}</div>;
// ⚠️ The sensitive header is now visible in page source!
}
// ✅ CORRECT PATTERN
// Fetch in Server Component, pass safe props
export default function Page() {
const ctx = getContext();
const safeUser = { name: ctx.req.cookies.username };
return <ClientProfile user={safeUser} />;
}4. Revalidation (dinou/server)v5.1.0+
Server-only APIs to purge and regenerate the static page cache of your application. These must be imported from the "dinou/server" entrypoint.
revalidatePath(path)
Cleans the static cache files for a given route and triggers a background regeneration. Supports both absolute and relative paths.
- Arguments:
path(string) - The absolute path (e.g."/blog") or relative path (e.g."./","../") to revalidate. - Returns:
Promise<void>
import { revalidatePath } from "dinou/server";
// Revalidate absolute route path
await revalidatePath("/products");
// Revalidate relative route path
await revalidatePath("./");revalidateTag(tag)
Revalidates all static pages associated with the specified cache tag.
- Arguments:
tag(string) - The cache tag name to invalidate (e.g."products"). - Returns:
Promise<void>
import { revalidateTag } from "dinou/server";
// Purge and regenerate all pages tagged with "catalog"
await revalidateTag("catalog");