genko.meDocs
SDK and CLI

Display content with List and View

Build schema-based lists and detail views with states, pagination, and draft preview.

These Next.js App Router components fetch and display content. This page covers @genko-me/[email protected] with Next.js 16 or later, React 19, and the Node.js runtime.

The SDK handles fetching, rendering, and pagination. Your app supplies the page URL and layout. The CLI generates two files and configuration for the connection, but does not generate a template page. For the first list and details, please place the example in Quick Start.

To record and display views, use PageView and ViewCount; see Page views.

Set up

sh
npx @genko-me/cli init

In a Next.js project, the CLI installs the SDK and React components and generates lib/schema.ts and lib/client.ts. Set the API key to GENKO_API_KEY on the server. You do not need a Route Handler or Proxy.

The example list below is when blog has title and image fields. Replace with your actual field ID.

tsx
import { client } from '@/lib/client';import { List, ListItem, Pagination, Error, Null } from '@genko-me/react/next';
export default function Page() {  return <List api={client.blog} limit={6} orders="-publishedAt" href="/blog/{id}">    <article>      <h2><ListItem id="title" /></h2>      <ListItem id="image" fallback={<span>No image</span>} />    </article>    <Pagination />    <Error template />    <Null>No posts yet.</Null>  </List>;}

The regular child of List defines the layout for one entry. Pagination, Loading, Error, and Null are placed directly below and are not repeated. If you omit a state component, nothing will be displayed in that state. Displays standard messages only when template is specified.

Details and drafts

tsx
import { client } from '@/lib/client';import { View, ViewItem, Error, Null } from '@genko-me/react/next';
type Props = {  params: Promise<{ id: string }>;  searchParams: Promise<Record<string, string | string[] | undefined>>;};
export default async function Page({ params, searchParams }: Props) {  const { id } = await params;  return <View api={client.blog} id={id} searchParams={searchParams}>    <h1><ViewItem id="title" /></h1>    <ViewItem id="body" />    <Error template />    <Null>Post not found.</Null>  </View>;}

Set the preview URL in the dashboard to https://your-site.example/blog/{id}?draftKey={key}. Passing searchParams retrieves the saved draft without caching it, displays a preview and displays an exit button. An invalid key does not fall back to the published version. You can hide it with previewNotice={false} or adjust it with previewNotice={{position:'bottom',className:'...'}}.

Omit id for object APIs. Missing entries render Null; notFound switches to the Next.js 404 page. After streaming starts, the HTTP status may become 200 due to Next.js specifications.

Server and browser boundary

Make pages that use client.ts and List / View server components. Do not mark your page with "use client" or pass the API client to client component props. Processing required by the browser, such as pagination, is handled within the SDK.

When surrounding it with client parts such as animations, you can pass the List / View assembled on the server side as the children of that part.

Style components in your app

List, View, field components, pagination, and states have no default styling. Apply the site design with className, style and HTML such as headings and divs. Please also set the main text headings, paragraph spacing, and image size using CSS on the site. If you want to display line breaks in multi-line text, specify white-space: pre-wrap etc.

template is a specification that selects a standard message for the status, without adding borders or margins. unstyled is accepted for compatibility with existing code, but does not change the decoration of these parts. Even if unstyled={false}, the standard design will not be attached.

The standard messages, pagination labels, and draft preview bar follow the lang you pass to List or View: Japanese for ja or no lang, English for any other language (en, fr, and so on). You can also pass lang to each component.

Only the draft preview notification and exit button display the standard design regardless of the unstyled parent. Specify previewNotice={{ unstyled: true }} to remove the decoration only for the notification, and previewNotice={false} to hide the notification itself.

Links around an entire entry use minimal CSS for their click target and keyboard focus. This is a necessary process for operation, separate from the visual theme.

Choose what to display

  • Display items are specified using ListItem / ViewItem. The type of text, image, HTML, etc. is determined from the generated schema.
  • className and style can be passed to each component. You can create layouts using wrappers such as <h1> and <div>.
  • The date and time is id="publishedAt" format="yyyy/MM/dd HH:mm" timeZone="Asia/Tokyo". The default time zone is UTC.
  • Reference is id="author.name". Multiple references display values ​​in order of reference. Standard reference expansion is up to 2 levels.
  • Unentered values are not displayed. You can pass JSX to fallback. False or 0 is not treated as not entered.
  • Set the link to the entire article with href="/blog/{id}" in List, or put <ListLink href="/blog/{id}">Read</ListLink> inside. You can manipulate nested links without breaking them.
  • Field IDs are validated at runtime. There is no ability to infer the child's string ID from the parent's api in TypeScript.

Pagination and caching

The default Pagination changes only the list without changing the URL. <Pagination mode="url" param="page" /> works with the URL and also supports back operations. If you also pass searchParams to List, the page specified by the URL will be drawn on the server from the beginning. If not passed, it will be synchronized in the browser. Please specify separate param for multiple URL linked lists.

List can specify limit (1 to 100), offset, filters, orders, and q. The default is to retrieve it every time, and cache the first retrieve only if you specify the number of seconds, such as cache={60}. Retrieving and displaying drafts by paging is always the latest version.

For pagination, use Server Action in the SDK. Instead of sending the API key to the browser, only server-issued fetch destinations and options are accepted. Signatures expire in 1 hour. Please reload the page after expiration or key exchange. The key for clients using pagination should match GENKO_API_KEY. Custom fetch / wrapRequest does not support pagination. Static export and Edge runtime are not applicable.

Main props

List / View

You can specify api for both, children for display, className, style, and unstyled. Display fields are not automatically selected.

propApplies toDefault and usage
apiBothA generated client such as client.blog. List requires a list API
cachebothfalse. Positive number of seconds to cache
depthboth2. Depth of reference expansion. 0, 1, or 2
searchParamsBothPromise or resolved value. Used for determining View drafts and paging linked to List URLs
idViewRequired in list format, omitted in object format
notFoundViewfalse. Set true to show the Next.js 404 page for a missing entry
previewNoticeViewDisplayed during preview. Hide with false, adjust position and decoration with object
limitList10. integer between 1 and 100
offsetList0. Number of items to skip from the beginning
orders / filters / qListSort/Conditions/Search
hrefListLink destination of an entire item, such as /blog/{id}

ListItem / ViewItem

propHow to use
idRequired. title, publishedAt, author.name, etc.
fallbackAlternative JSX when no input
formatDate and time format. Default is yyyy.MM.dd. Use yyyy, MM, dd, HH, mm, ss
locale / timeZoneDate and time display. Default is ja-JP / UTC
className / styleSite-side field decoration

If you want to use text as a heading, wrap it in HTML like <h1><ViewItem id="title" /></h1>. Rich text displays headings and paragraphs from saved HTML. Even if you write HTML in a normal text field, it will not be rendered as HTML.

States and pagination

Specify free JSX or template for Error, Null, and Loading. 404 response of View is subject to Null, failure of authentication/communication etc. is subject to Error. An empty array of List will be Null, and a retrieval error will be Error.

Loading…
No content yet.

Pagination receives mode (default local), param (default page), previousLabel, nextLabel and decorative props. Place one status component and one pagination directly under the parent. Don't hide it inside your own component or div.

Schema synchronization

sh
npx @genko-me/cli pull# Optional automatic sync during development (in another terminal)npx @genko-me/cli pull --watch

The API list in schema.ts is also synchronized, so there is no need to edit client.ts when adding an API. If you have limited synchronization targets, use pull --select-apis to add them to the selection. --watch checks every 10 seconds and updates the file only when it changes.

Manually deploy without using CLI

sh
npm install @genko-me/sdk @genko-me/react

Set GENKO_API_KEY in .env.local and create the following two files. The example assumes your dashboard has a blog API and title and body fields. Please match the type and ID to the actual schema.

lib/schema.ts
import { listApi } from '@genko-me/sdk';export type Blog = { title: string; body: string };export const apis = {  blog: listApi<Blog>({ fields: [    { id: 'title', type: 'text' },    { id: 'body', type: 'richtext' },  ] }),};
lib/client.ts
import 'server-only';import { createGenko } from '@genko-me/sdk';import { apis } from './schema';export const client = createGenko({  workspace: 'your-workspace',  apiKey: process.env.GENKO_API_KEY!,  apis,}).apis;

Next, import client and parts from the page. With manual installation, you will also be able to reflect schema changes yourself. If you want to automate synchronization, please use CLI.

Low level parts

If you want to handle the retrieval yourself, you can also use the classic RichText (@genko-me/react) and ShareButtons (@genko-me/react/share-buttons).

Last updated: October 19, 2026

On this page