genko.meDocs
SDK and CLI

Plugins and Next.js integration

Add preview, webhook revalidation, and custom plugins.

Add features through the plugins option in createGenko. You can then use them through genko.preview or genko.revalidate. Import Next.js App Router plugins from @genko-me/sdk/next.

Apps that do not use Next.js do not need to import this subpath. The core SDK fetches data independently of any framework.

When installing with List / View, no preview plugin is required. For instructions on placing View on a regular page and passing searchParams, please refer to Draft Preview. The helpers below are for apps that manage fetching and integration routes directly.

Preview: nextPreview

ts
import { nextPreview } from "@genko-me/sdk/next";
const preview = nextPreview({  redirectTo: (id, key) =>    `/blog/${encodeURIComponent(id)}?draftKey=${encodeURIComponent(key)}`,  enableDraftMode: true,});
OptionDescription
redirectToA function that returns the destination within the site from the ID and key
enableDraftModeWhether to enable Draft Mode of Next.js. Default is true

The provided GET handler reads id and draftKey from the URL, optionally enables Draft Mode, and returns a 307 redirect. Missing parameters return 400.

This handler does not fetch the entry or validate the key. Pass draftKey to the fetch method at the destination. See the complete example in Draft preview.

Revalidate: nextRevalidate

lib/client.ts
import { createGenko } from "@genko-me/sdk";import { nextRevalidate } from "@genko-me/sdk/next";import { blog } from "./schema";
export const genko = createGenko({  workspace: "your-workspace",  apiKey: process.env.GENKO_API_KEY!,  apis: { blog },  plugins: [    nextRevalidate({      secret: process.env.GENKO_WEBHOOK_SECRET!,      revalidate: (event) => {        if (event.api !== "blog" || event.workspace !== "your-workspace") return [];        if (event.event === "webhook.test") return ["/blog"];        return event.entry ? ["/blog", `/blog/${event.entry.id}`] : ["/blog"];      },    }),  ],});
app/api/revalidate/route.ts
import { genko } from "@/lib/client";
export const POST = genko.revalidate.POST;

Set GENKO_WEBHOOK_SECRET to the webhook secret configured in the dashboard. An empty secret will result in an error when initializing the client.

The plugin verifies x-genko-signature as sha256=HMAC-SHA256(secret, "<timestamp>.<raw body>"), using the Unix seconds in x-genko-timestamp. The default tolerance is 300 seconds; set toleranceSeconds in nextRevalidate to change it. SDK 0.6.0 requires both headers and does not accept the previous body-only signature.

When the signature matches, the plugin runs the callback and calls revalidatePath() for each returned path. On success, it returns JSON such as { "revalidated": ["/blog"] }. Missing or invalid signatures and timestamps return 401.

This plugin does not create caches or rebuild your deployed app. Make sure the returned paths match what your app caches. For webhook delivery, please refer to Webhook.

Custom plugins

Give your plugin a unique id. You can add functionality to the client with extend and wrap HTTP processing with wrapRequest.

ts
import type { GenkoPlugin } from "@genko-me/sdk";
export function timingPlugin(): GenkoPlugin<"timing", undefined> {  return {    id: "timing",    wrapRequest: (next) => async (path, query) => {      const started = Date.now();      const response = await next(path, query);      console.log("genko request", response.status, Date.now() - started);      return response;    },  };}

Add it as plugins: [timingPlugin()]. This example does not log credentials or preview keys, only results and times.

  • Duplicate id and reserved names apis/client cannot be used.
  • The return value of extend is available from genko.<id>.
  • Earlier wrapRequest plugins in the array wrap later ones.
  • If you add caching or retries, also design for preview isolation and retry limits.

Last updated: October 16, 2026

On this page