Data sources
Feed real Payload collection data into Olgax DXP page-builder blocks with @olgax.com/datasource - resolvers, route handlers and the RelatedPages example.
@olgax.com/datasource is a deliberately narrow resolver layer. A block declares "pull N items from a Payload
collection, filtered by one field", and receives them as a resolved items prop.
It supports one equality filter and a limit. It is not a query language.
How it works
The editor sets three things on the block: collection, optionally filterField and filterValue, and limit.
When they change, Puck's resolveData fetches the items and writes them into a read-only items prop.
import { createCollectionResolverFetch } from "@olgax.com/datasource";
import { registerRelatedPages } from "@olgax.com/components";
registerRelatedPages(createCollectionResolverFetch("/api/related-pages"));import { NextResponse } from "next/server";
import { queryCollectionFromSearchParams } from "@olgax.com/datasource";
import { getPayloadClient } from "@/lib/payload";
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const items = await queryCollectionFromSearchParams(getPayloadClient, searchParams);
return NextResponse.json(items);
}The scaffolded site already includes this route and registration, so the RelatedPages block works out of the box.
Which resolver should I use?
| Function | Use when |
|---|---|
createCollectionResolverFetch(endpoint) | Default. The config is shared with the client-side editor. It only calls fetch(), so payload never reaches the browser bundle. |
createCollectionResolver(getPayload) | Only for a config that exclusively backs server-rendered output and never ships to the client |
Build a data-backed block
Spread collectionQueryFields into your block's fields, and use the matching resolver as resolveData:
import type { ComponentConfig } from "@puckeditor/core";
import {
collectionQueryFields,
createCollectionResolverFetch,
type CollectionQueryProps,
} from "@olgax.com/datasource";
type Item = { id: string | number; title?: string };
type LatestPagesProps = CollectionQueryProps & { items?: Item[] };
export const latestPagesBlock: ComponentConfig<{ props: LatestPagesProps }> = {
fields: { ...collectionQueryFields },
defaultProps: { collection: "pages", limit: 3 },
resolveData: createCollectionResolverFetch<LatestPagesProps>("/api/related-pages"),
render: ({ items }) => (
<ul>
{(items ?? []).map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
),
};Register it in components/blocks/index.ts like any other block. RelatedPages in @olgax.com/components is the
reference implementation.
See the datasource reference for every export.
Think about access
The route handler runs a real Payload query. Keep your collection access rules strict, and do not expose a collection through a public endpoint unless its data is safe to show to anyone.
Questions, ideas or something not working?
Ask in our official Discord, open an issue on GitHub, or edit this page.
Analytics
Built-in privacy-friendly page view counts for Olgax DXP, a dashboard with the last 7 days of traffic, and optional Umami integration with Docker Compose.
Webhooks
Notify any URL when an Olgax DXP page is published or deleted. Configure webhooks in the admin and verify the HMAC-SHA256 signature on your receiver.