This tutorial uses PRISM file-based routing: every folder under src/app/ becomes a URL, with nested layouts and server-side loaders.
Read the routing docs →Components come from bext/ui — a faithful shadcn/ui port for bext and PRISM, styled through route_css tokens.
Explore bext/ui →Load data in a loader and render it as a table — all on the server, no client fetch.
Now the data. A loader runs on the server before the page renders; whatever it returns arrives as the page's data prop. Because it runs server-side, you can read a database, call an API, or — here — just sort an array.
export async function loader() {
const products = [...CATALOGUE].sort((a, b) => a.name.localeCompare(b.name));
return { products };
}
export default function Products({ data }) {
return (
<table>
{data.products.map((p) => (
<tr key={p.id}><td>{p.name}</td><td>${p.price}</td></tr>
))}
</table>
);
}There's no fetch on the client and no loading spinner — the HTML arrives complete, with the rows already in it. The full table (with SKU and a stock badge) is rendering live in the preview.
request; see data & loaders.