Reader API

The Reader API is a Node.js API that lets you read Keystatic content from a storage of your own choice. The storage can be any local directory / GitHub repository, and does not need to be the same as the one defined in the Keystatic config.

⚠️

The reader API code is meant to run on the server, and not in the browser. Be sure to use it accordingly.

Usage

Local Directory

To read from local storage, import the createReader function, as well as your Keystatic config file:

import { createReader } from '@keystatic/core/reader';
import keystaticConfig from 'relative/path/to/your/keystatic.config';

You can then create a new reader by calling createReader and passing it two arguments:

  1. Path to the root of your content repository
  2. The Keystatic config
const reader = createReader(process.cwd(), keystaticConfig);

GitHub Repository

To read from GitHub, import the createGitHubReader function, as well as your Keystatic config file:

import { createGitHubReader } from '@keystatic/core/reader/github';
import keystaticConfig from 'relative/path/to/your/keystatic.config';

You can then create a new reader by calling createGitHubReader and passing it the following arguments:

  1. The Keystatic config

  2. An options object containing:

    • repo: The name of the content repository on GitHub (e.g. Thinkmill/keystatic-data)
    • token: The Personal Access Token that allows read access to the repository. This is different from your GitHub App Client ID / Secret in .env. For information on how to generate PATs, see GitHub's documentation.
const reader = createGitHubReader(keystaticConfig, {
    repo: 'Thinkmill/keystatic-data',
    token: process.env.GITHUB_PAT,
});

Reading from collections

You can get an array of slugs for a given collection with:

const slugs = await reader.collections.{collectionName}.list();

// Example
const slugs = await reader.collections.posts.list();

You can get the data for a specific collection entry with:

const entry = await reader.collections.{collectionName}.read(slug);

// Example
const post = await reader.collections.post.read(slug);

You can get an array of objects containing both slug and entry data for a collection with:

const entries = await reader.collections.{collectionName}.all();

// Example
const posts = await reader.collections.blog.all();

Reading from singletons

You can get the data for a specific singleton with:

const data = await reader.singletons.{singletonName}.read();

// Example
const navigation = await reader.singletons.navigation.read();

Remember: this code cannot run in the browser, as it's using some Node.js APIs.

Good places to use the Reader API are:

  • getStaticProps in Next.js (Pages Router)
  • The frontmatter in Astro files
  • The loader() function in Remix
  • ReactServer Components

Data from linked files

If your collection or singleton contains a document field, that field will be returned as an asynchronous function that you'll need to call to get the data:

// The `posts` collection has a `document` field named `content`
const post = await reader.collections.posts.read(slug);

// Get the content data
const content = await post.content()

If you'd rather get the document field data immediately, you can pass resolveLinkedFiles: true as an option when reading the entry:

await reader.collections.posts.read(slug, { resolveLinkedFiles: true });

Using TypeScript

The Reader API exports an Entry type, which is useful when you need to define what props a UI component should receive:

import { Entry } from '@keystatic/core/reader';
import keystaticConfig from '../../keystatic.config';

type MovieProps = Entry<typeof keystaticConfig['collections']['movies']>

export function Movie(props: MovieProps) {
  // ...
}

If your data was read using the resolvedLinkedFiles option, you can use the EntryWithResolvedLinkedFiles type instead:

import { EntryWithResolvedLinkedFiles } from '@keystatic/core/reader';
import keystaticConfig from '../../keystatic.config';

type MovieProps = EntryWithResolvedLinkedFiles<typeof keystaticConfig['collections']['movies']>

Rendering content from the document field

The document field returns a JSON object with complex structured data. It can be a lot of work to turn this data object as HTML to render it on a page.

Luckily, Keystatic also provides a DocumentRenderer that does all the heavy lifting for you, and is highly customisable.


Screencast walk-through

This segment of the Keystatic Mini-Course on YouTube may help understand how the Reader API works:


Type signature

Find the latest version of the Reader type signature at: https://docsmill.dev/npm/@keystatic/core@latest#/.reader.Reader