Prismic CMS
The @yak-io/prismic package adapts your Prismic content into Yak primitives. It produces standard RouteSource, ToolSource, and SchemaSource 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— exposeprismic.getByUID,prismic.getAllByType, andprismic.searchas tools the assistant can invoke.createPrismicSchemaSource— return a GraphQL schema source describing your content model, so the assistant knows which document types and fields exist.
Installation
npm install @yak-io/prismic @yak-io/javascript @prismicio/clientpnpm add @yak-io/prismic @yak-io/javascript @prismicio/clientyarn add @yak-io/prismic @yak-io/javascript @prismicio/clientbun add @yak-io/prismic @yak-io/javascript @prismicio/client@prismicio/client (v7+) is a peer dependency. If you want to use the GraphQL schema source, 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.
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],
});Schema source on the client
Schema sources flow through the client-side getConfig provider (not the server handler). Wire them into your YakProvider:
"use client";
import { YakProvider, YakWidget } from "@yak-io/nextjs/client";
import { createPrismicSchemaSource } from "@yak-io/prismic";
import { prismicClient } from "@/prismicio";
let cachedSchema: Awaited<ReturnType<typeof createPrismicSchemaSource>> | null = null;
async function getConfig() {
const res = await fetch("/api/yak");
const config = await res.json();
cachedSchema ??= await createPrismicSchemaSource({
client: prismicClient,
mode: "graphql",
});
return { ...config, schemaSources: [cachedSchema] };
}
export function Providers({ children }: { children: React.ReactNode }) {
return (
<YakProvider appId={process.env.NEXT_PUBLIC_YAK_APP_ID!} getConfig={getConfig}>
{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.
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();
});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();
});Schema source on the client
In your .client.ts Nuxt plugin, return the schema source from getConfig:
import { createYakProvider } from "@yak-io/nuxt";
import { createPrismicSchemaSource } from "@yak-io/prismic";
import { prismicClient } from "~/prismicio";
let cachedSchema: Awaited<ReturnType<typeof createPrismicSchemaSource>> | null = null;
export default defineNuxtPlugin((nuxtApp) => {
const yak = createYakProvider({
appId: useRuntimeConfig().public.yakAppId,
getConfig: async () => {
const config = await $fetch("/api/yak");
cachedSchema ??= await createPrismicSchemaSource({
client: prismicClient,
mode: "graphql",
});
return { ...config, schemaSources: [cachedSchema] };
},
onToolCall: async (name, args) => {
const res = await $fetch("/api/yak", { method: "POST", body: { name, args } });
return res.result;
},
});
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}` }),
});| Option | Type | Description |
|---|---|---|
client | Client | A @prismicio/client instance |
documentTypes | string[] | Which Prismic custom types to include in the route manifest |
resolveRoute | (doc) => RouteInfo | null | Map each document to a RouteInfo entry. Return null to skip a document (drafts, hidden pages, etc.) |
filters | string[] | Optional additional Prismic filter expressions, appended after the type filter |
id | string | Optional source identifier (default: "prismic") |
createPrismicToolAdapter
const tools = createPrismicToolAdapter({
client: prismicClient,
allowedTypes: ["page", "blog_post"],
});| Option | Type | Description |
|---|---|---|
client | Client | A @prismicio/client instance |
allowedTypes | string[] | Document types the LLM is allowed to query. Required — this is the security boundary |
fields | Record<string, string[]> | Optional per-type field projection. Translated to Prismic's GraphQuery DSL on the wire |
id | string | Optional source identifier (default: "prismic") |
The adapter exposes three tools:
| Tool name | Purpose |
|---|---|
prismic.getByUID | Fetch one document by (type, uid) |
prismic.getAllByType | List all documents of a given type (default limit: 20) |
prismic.search | Full-text search across allowed types |
createPrismicSchemaSource
const schema = await createPrismicSchemaSource({
client: prismicClient,
mode: "graphql",
});| Option | Type | Description |
|---|---|---|
client | Client | A @prismicio/client instance |
mode | "graphql" | Currently only GraphQL is supported. Introspects your Prismic repo's /graphql endpoint |
name | string | Optional override for the schema source name (default: "prismic") |
fetchFn | typeof fetch | Optional fetch override for testing or custom transport |
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) andallowedTypes(tools) to the document types that are genuinely public. - Use
resolveRoutereturningnullto filter unpublished drafts out of the route manifest. - Tool calls execute server-side via
createYakHandler/createNextYakHandler— your Prismic access token never reaches the browser.