Yak Docs
SDKs

Prismic

The @yak-io/prismic package adapts your Prismic content into Yak primitives. It produces standard RouteSource, ToolSource, and ToolAdapter values that compose with the existing framework SDKs — most commonly @yak-io/nextjs or @yak-io/nuxt.

What you get

  • createPrismicRouteAdapter — turn published Prismic documents into the route manifest the LLM uses for navigation.
  • createPrismicToolAdapter — expose prismic.getByUID, prismic.getAllByType, and prismic.search as tools the assistant can invoke.
  • createPrismicGraphQLToolAdapter — introspect your repo's GraphQL schema and return a browser-executed ToolAdapter (a graphql_prismic tool) so the assistant can query your content model directly.

Installation

npm install @yak-io/prismic @yak-io/javascript @prismicio/client
pnpm add @yak-io/prismic @yak-io/javascript @prismicio/client
yarn add @yak-io/prismic @yak-io/javascript @prismicio/client
bun add @yak-io/prismic @yak-io/javascript @prismicio/client

@prismicio/client (v7+) is a peer dependency. If you want to use the GraphQL adapter, also install graphql.

Quick Start

Create a Prismic client

Wherever you would normally configure Prismic — usually a shared prismicio.ts:

import * as prismic from "@prismicio/client";

export const prismicClient = prismic.createClient("your-repo-name", {
  accessToken: process.env.PRISMIC_ACCESS_TOKEN,
});

Build the adapters

Each factory takes the client plus a small config. Routes need a resolveRoute mapper from document → RouteInfo. Tools need an allowedTypes list — this is the security boundary for what the LLM can read.

import {
  createPrismicRouteAdapter,
  createPrismicToolAdapter,
} from "@yak-io/prismic";
import { prismicClient } from "./prismicio";

export const prismicRoutes = createPrismicRouteAdapter({
  client: prismicClient,
  documentTypes: ["page", "blog_post"],
  resolveRoute: (doc) => ({
    path: `/${doc.uid}`,
    title: doc.data.meta_title ?? doc.data.title,
    description: doc.data.meta_description,
  }),
});

export const prismicTools = createPrismicToolAdapter({
  client: prismicClient,
  allowedTypes: ["page", "blog_post"],
});

Plug them into your Yak handler

See the framework sections below — the exact wiring differs between Next.js and Nuxt, but in both cases you pass the adapters straight into the standard handler config.

Using with Next.js

Pair @yak-io/prismic with @yak-io/nextjs. The Next.js handler accepts route and tool sources as arrays, so you can combine Prismic-sourced routes with the filesystem auto-scan or with other tool adapters in the same handler.

app/api/yak/[[...yak]]/route.ts
import { createNextYakHandler } from "@yak-io/nextjs/server";
import {
  createPrismicRouteAdapter,
  createPrismicToolAdapter,
} from "@yak-io/prismic";
import { prismicClient } from "@/prismicio";

const prismicRoutes = createPrismicRouteAdapter({
  client: prismicClient,
  documentTypes: ["page", "blog_post"],
  resolveRoute: (doc) => ({
    path: `/${doc.uid}`,
    title: doc.data.meta_title ?? doc.data.title,
    description: doc.data.meta_description,
  }),
});

const prismicTools = createPrismicToolAdapter({
  client: prismicClient,
  allowedTypes: ["page", "blog_post"],
});

export const { GET, POST } = createNextYakHandler({
  appDir: "./src/app",
  routes: [prismicRoutes],
  tools: [prismicTools],
});

If you want filesystem routes and Prismic routes, just include both in the array — the handler merges and deduplicates by path:

import { scanRoutes } from "@yak-io/nextjs/server";

export const { GET, POST } = createNextYakHandler({
  routes: [
    () => scanRoutes("./src/app"),
    prismicRoutes,
  ],
  tools: [prismicTools],
});

GraphQL adapter on the client

The GraphQL adapter runs in the browser. Compose it with any server-relayed tools using createYakToolset, then wire the toolset's getConfig / onToolCall into your YakProvider:

app/providers.tsx
"use client";
import { createYakServerAdapter, createYakToolset, YakProvider, YakWidget } from "@yak-io/nextjs/client";
import { createPrismicGraphQLToolAdapter } from "@yak-io/prismic";
import { prismicClient } from "@/prismicio";

let toolset: ReturnType<typeof createYakToolset> | null = null;

async function getToolset() {
  if (!toolset) {
    const prismicGraphQL = await createPrismicGraphQLToolAdapter({
      client: prismicClient,
      headers: async () => ({ "Prismic-ref": await prismicClient.getMasterRef().then((r) => r.ref) }),
    });
    toolset = createYakToolset([createYakServerAdapter({ endpoint: "/api/yak" }), prismicGraphQL]);
  }
  return toolset;
}

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <YakProvider
      appId={process.env.NEXT_PUBLIC_YAK_APP_ID!}
      getConfig={async () => ({ routes, ...(await (await getToolset()).getConfig()) })}
      onToolCall={async (name, args) => (await getToolset()).onToolCall(name, args)}
    >
      {children}
      <YakWidget />
    </YakProvider>
  );
}

Cache the introspection result. The GraphQL schema rarely changes between sessions, and you don't want to re-introspect on every chat open.

Using with Nuxt

Pair @yak-io/prismic with @yak-io/nuxt. Nuxt's server side uses Nitro routes; you call the underlying createYakHandler from @yak-io/javascript/server and pass the adapters into it the same way.

server/api/yak.get.ts
import { createYakHandler } from "@yak-io/javascript/server";
import {
  createPrismicRouteAdapter,
  createPrismicToolAdapter,
} from "@yak-io/prismic";
import { prismicClient } from "~/prismicio";

const prismicRoutes = createPrismicRouteAdapter({
  client: prismicClient,
  documentTypes: ["page", "blog_post"],
  resolveRoute: (doc) => ({
    path: `/${doc.uid}`,
    title: doc.data.meta_title ?? doc.data.title,
    description: doc.data.meta_description,
  }),
});

const prismicTools = createPrismicToolAdapter({
  client: prismicClient,
  allowedTypes: ["page", "blog_post"],
});

const { GET } = createYakHandler({
  routes: [prismicRoutes],
  tools: [prismicTools],
});

export default defineEventHandler(async (event) => {
  const request = toWebRequest(event);
  const response = await GET(request);
  return response.json();
});
server/api/yak.post.ts
import { createYakHandler } from "@yak-io/javascript/server";
import { createPrismicToolAdapter } from "@yak-io/prismic";
import { prismicClient } from "~/prismicio";

const { POST } = createYakHandler({
  routes: [],
  tools: [
    createPrismicToolAdapter({
      client: prismicClient,
      allowedTypes: ["page", "blog_post"],
    }),
  ],
});

export default defineEventHandler(async (event) => {
  const request = toWebRequest(event);
  const response = await POST(request);
  return response.json();
});

GraphQL adapter on the client

In your .client.ts Nuxt plugin, compose the Prismic GraphQL adapter with the server adapter:

plugins/yak.client.ts
import { createYakProvider, createYakServerAdapter, createYakToolset } from "@yak-io/nuxt";
import { createPrismicGraphQLToolAdapter } from "@yak-io/prismic";
import { prismicClient } from "~/prismicio";

let toolset: ReturnType<typeof createYakToolset> | null = null;

export default defineNuxtPlugin((nuxtApp) => {
  const yak = createYakProvider({
    appId: useRuntimeConfig().public.yakAppId,
    getConfig: async () => {
      toolset ??= createYakToolset([
        createYakServerAdapter({ endpoint: "/api/yak" }),
        await createPrismicGraphQLToolAdapter({ client: prismicClient }),
      ]);
      return { routes, ...(await toolset.getConfig()) };
    },
    onToolCall: async (name, args) => toolset!.onToolCall(name, args),
  });

  nuxtApp.hook("app:mounted", () => yak.mount());
  return { provide: { yak } };
});

API Reference

createPrismicRouteAdapter

const routes = createPrismicRouteAdapter({
  client: prismicClient,
  documentTypes: ["page", "blog_post"],
  resolveRoute: (doc) => ({ path: `/${doc.uid}` }),
});
OptionTypeDescription
clientClientA @prismicio/client instance
documentTypesstring[]Which Prismic custom types to include in the route manifest
resolveRoute(doc) => RouteInfo | nullMap each document to a RouteInfo entry. Return null to skip a document (drafts, hidden pages, etc.)
filtersstring[]Optional additional Prismic filter expressions, appended after the type filter
idstringOptional source identifier (default: "prismic")

createPrismicToolAdapter

const tools = createPrismicToolAdapter({
  client: prismicClient,
  allowedTypes: ["page", "blog_post"],
});
OptionTypeDescription
clientClientA @prismicio/client instance
allowedTypesstring[]Document types the LLM is allowed to query. Required — this is the security boundary
fieldsRecord<string, string[]>Optional per-type field projection. Translated to Prismic's GraphQuery DSL on the wire
idstringOptional source identifier (default: "prismic")

The adapter exposes three tools:

Tool namePurpose
prismic.getByUIDFetch one document by (type, uid)
prismic.getAllByTypeList all documents of a given type (default limit: 20)
prismic.searchFull-text search across allowed types

createPrismicGraphQLToolAdapter

const prismicGraphQL = await createPrismicGraphQLToolAdapter({
  client: prismicClient,
});

Introspects your Prismic repo's /graphql endpoint once and returns a browser-executed ToolAdapter exposing a graphql_prismic tool.

OptionTypeDescription
clientClientA @prismicio/client instance
namestringTool name suffix — exposed as graphql_<name> (default: "prismic")
endpointstringOverride the GraphQL endpoint (defaults to the repo's derived /graphql URL)
headersHeadersInit | (() => HeadersInit | Promise<HeadersInit>)Execution headers, e.g. Prismic-ref. May be async to fetch the master ref per call
fetchFntypeof fetchOptional fetch override for the one-time introspection (testing)

GraphQL mode requires the graphql package to be installed alongside this adapter.

Composing with other sources

Route and tool sources merge cleanly. You can pair Prismic with anything else in the same handler:

import { createNextYakHandler } from "@yak-io/nextjs/server";
import { createTRPCToolAdapter } from "@yak-io/trpc";
import { createPrismicToolAdapter } from "@yak-io/prismic";
import { appRouter, createContext } from "@/server/trpc";
import { prismicClient } from "@/prismicio";

export const { GET, POST } = createNextYakHandler({
  appDir: "./src/app",
  tools: [
    createPrismicToolAdapter({
      client: prismicClient,
      allowedTypes: ["page", "blog_post"],
    }),
    createTRPCToolAdapter({
      router: appRouter,
      createContext: async ({ req }) => createContext({ req }),
      allowedProcedures: ["orders.list", "orders.getById"],
    }),
  ],
});

The route manifest merger dedupes by path, so a Prismic-sourced /about route won't conflict with a filesystem-sourced one.

Security

allowedTypes defines the read surface the LLM has into your Prismic repository. Without it, anyone using the assistant could ask it to fetch internal document types (settings, feature_flags, etc.). Always set this to the minimal list of public content types.

  • Restrict documentTypes (routes) and allowedTypes (tools) to the document types that are genuinely public.
  • Use resolveRoute returning null to filter unpublished drafts out of the route manifest.
  • Tool calls execute server-side via createYakHandler / createNextYakHandler — your Prismic access token never reaches the browser.

On this page