Skip to content

Data Loading

τjs provides a route-first, declarative way to load data for SSR and streaming.

Data loading happens at the route level through the attr.data function. This function:

  • Runs on the server
  • Receives route parameters and request context
  • Returns data that’s injected into your page
taujs.config.ts
{
path: '/users/:id',
attr: {
render: 'ssr',
data: async (params, ctx) => {
const res = await fetch(`https://api.example.com/users/${params.id}`);
return await res.json();
}
}
}

Your data handler receives a context object:

type RequestContext = {
traceId: string; // Request trace ID
logger: Logger; // Scoped logger
headers: Record<string, string>; // Request headers
};

Example:

data: async (params, ctx) => {
ctx.logger.info({ userId: params.id }, "Loading user");
const res = await fetch(`/api/users/${params.id}`, {
headers: {
"x-trace-id": ctx.traceId,
authorization: ctx.headers.authorization || "",
},
});
return await res.json();
};

Delegate to registered services for better separation:

{
path: '/users/:id',
attr: {
render: 'ssr',
data: async (params) => ({
serviceName: 'UserService',
serviceMethod: 'getUser',
args: { id: params.id }
})
}
}

τjs calls the service automatically and returns the result. See theServices section for further information.

Data loads completely before rendering:

{
path: '/products',
attr: {
render: 'ssr',
data: async () => {
const products = await db.products.findAll();
return { products };
}
}
}

Characteristics:

  • Data fully available in headContent
  • Complete HTML in single response
  • Best for SEO-critical pages

Shell sent immediately, data may load progressively:

{
path: '/dashboard',
attr: {
render: 'streaming',
meta: { // Required for streaming
title: 'Dashboard',
description: 'User dashboard'
},
data: async () => {
const metrics = await fetchMetrics();
return { metrics };
}
}
}

Characteristics:

  • Faster Time to First Byte
  • Data may not be ready when headContent runs
  • Requires meta property for reliable SEO

Access server data in your components:

client/App.tsx
import { useSSRStore } from "@taujs/react";
export function App() {
const data = useSSRStore<{ products: Product[] }>();
return (
<div>
{data.products.map((product) => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}

For client-side updates after SSR, see Client Data Fetching.