Loving Tina? us on GitHub0.0k

Docs

Learn

v.Latest
Documentation

Hybrid Fetching

Loading last updated info...

When using Static Site Generation (SSG), there may be occasions where a client-side approach or dynamic rendering is needed. However, with dynamic rendering, the first request can be slower because the page is built on demand, which can negatively impact the initial user experience.

To address this, we use a hybrid approach: SSG for existing pages and dynamic rendering for newly created pages.

// lib/tina.ts
import { client } from "@/tina/__generated__/client";
export async function getPageFromTina(slug: string, branch: string = "main") {
try {
const response = await client.queries.page({
relativePath: `${slug}.md`},
{
fetchOptions: {
headers: {
/* Retrieve the active branch from cookie */
'x-branch': branch,
},
},
}
);
return response?.data?.page ?? null;
} catch {
return null;
}
}
// app/[slug]/page.tsx
import { getPageFromTina} from "@/lib/tina";
import ClientFallback from "@/components/ClientFallback";
export const dynamic = "force-static";
type PageProps = {
params: {
slug: string;
};
};
// Next.js built-in function
export async function generateStaticParams() {
const response = await client.queries.pageConnection();
return (
response?.data?.pageConnection?.edges
?.map((edge) => ({
slug: edge?.node?.sys?.filename,
}))
.filter((param) => Boolean(param.slug)) ?? []
);
}
export default async function Page({ params }: PageProps) {
const page = await getPageFromTina(params.slug);
if (!page) {
return <ClientFallback />;
}
return (
<main>
<h1>{page.title}</h1>
<article
dangerouslySetInnerHTML={{ __html: page.body }}
/>
</main>
);
}
// components/ClientFallback.tsx
"use client";
import { notFound } from "next/navigation";
export default async function ClientFallback() {
const cookieStore = await cookies();
const branchValue = cookieStore.get("x-branch")?.value || "";
const page = await getPageFromTina(params.slug, branchValue );
if(!page?.data)
{
return notFound();
}
const { data } = useTina({
query: page.query,
variables: page.variables,
data: page.data,
});
return (
<main>
<h1>{data .title}</h1>
<article
dangerouslySetInnerHTML={{ __html: data.body }}
/>
</main>
);
}

Here are the two possible scenarios depicted in the diagram.

Figure: Flow when an existing page is requested

Figure: Flow when a new page is requested

Here is the documentation on fetching content across branches

Last Edited: January 20, 2026