Reading content
Get a document, list a collection, or search it. The same three calls work in every framework.
Once your content is compiled, your app reads it through a Graft client. This page covers the three reads you will use everywhere, the options they take, and how to read from a branch or from another server.
Your framework guide shows where to create the client. Every example below
assumes one called graft.
Read one document
getContent takes a collection and a slug, and returns the document or
null if it does not exist:
const home = await graft.getContent("pages", "home");
if (home) {
home.data.title; // string, typed from your schema
home.body; // the Markdown or MDX body, as written
}
List a collection
listContent returns every document in a collection. Pass limit and
offset to page through a long one:
const posts = await graft.listContent("posts", { limit: 20, offset: 0 });
Search a collection
searchContent runs a full-text search and returns the best matches first,
each with a highlighted snippet of the matching text:
const hits = await graft.searchContent("docs", "preview branch");
Search explains the query syntax and how results are ranked.
Every read checks each document against your schema on the way out. Deleted
documents are skipped. A document that fails the check is not: the read throws
SCHEMA_VALIDATION_FAILED, naming the document and the field, and a list or
search that includes it fails as a whole. You never receive a document whose
fields do not match its type. graft compile runs the same check, so this only
happens when the index was built from files that no longer match the schema.
Why the names differ outside a framework
The framework packages call these reads getContent, listContent, and
searchContent. Underneath, they all use @usegraft/sdk-core, whose methods
are named getDocument, listDocuments, and searchDocuments. They take
the same arguments and return the same types. Use the sdk-core names only
when you call it directly, in a script or a tool with no framework.
Read from a preview branch
Pass branch to any read to get content from a preview branch
instead of main:
const page = await graft.getContent("pages", "pricing", { branch: "preview-pricing" });
Branches need the Postgres engine. On the static engine the option is accepted and ignored, because each Git checkout compiles its own index.
Read from another server
Sometimes the app that renders pages cannot open the index itself, for example
when it runs on a different host from your content. In that case, point the
client at a Content API served by graft serve. Your
reads stay exactly the same:
import { createContentApiReader } from "@usegraft/content-api";
import { createGraft } from "@usegraft/sdk-astro";
import { collections } from "../../graft.config";
export const graft = createGraft({
index: createContentApiReader({
endpoint: "https://cms.example.com/api/content/v1",
headers: { authorization: `Bearer ${process.env.GRAFT_CONTENT_TOKEN}` },
}),
collections,
});
Each Content API endpoint serves one branch, so a production app cannot be switched onto preview content by a request parameter.
Your framework
Server Components, MDX rendering, and cache refresh.
Frontmatter reads with no client JavaScript.
Server load functions and server routes.
Server functions, never isomorphic loaders.
Framework-mode loaders and resource routes.
Hooks that read over HTTP.