# API Reference # Overview Complete reference documentation for all Peam APIs. Choose a section to get started.
Client API

AskAI components, providers, hooks, and transports.

Server API

Chat runtimes, summarizers, and search helpers.

Next.js Integration

Configure Next.js with Peam and related utilities.

Route Handler

Default Next.js route handler for API requests.

# Filters # Overview Filters prune discovered pages before indexing. The CLI exposes `exclude` patterns and robots.txt filtering. This mirrors [indexing filters](/docs/indexing/filters). ## Exclude patterns Use `--exclude` to drop paths that match glob patterns. You can repeat the flag: ```bash peam \ --source fileBased --projectDir . --sourceDir dist \ --exclude /admin/** --exclude /private/** \ --store fileBased --indexPath .peam/index.json ``` ## robots.txt filtering Enable robots.txt filtering or provide a custom path: ```bash peam \ --source fileBased --projectDir . --sourceDir dist \ --robotsTxt true \ --store fileBased --indexPath .peam/index.json ``` ```bash peam \ --source fileBased --projectDir . --sourceDir dist \ --robotsTxt ./public/robots.txt \ --store fileBased --indexPath .peam/index.json ``` ## Notes * `--robotsTxt true` attempts to discover `robots.txt` automatically. * `--robotsTxt false` disables robots.txt filtering. # CLI # Overview Peam’s CLI lets you discover content, apply filters, and export indexes from any framework or static output. Use it for static sites, CI builds, or frameworks without a native adapter. ## Continue with
Install

Add the CLI to your project.

Usage

Basic commands and examples.

Sources

Configure file-based or prerender sources.

Stores

Export indexes to a store.

Filters

Exclude paths and apply robots rules.

# Install # Overview Install the CLI as a dependency so you can run `peam` in local builds and CI. ## Install npm pnpm yarn bun ```bash npm install peam ``` ```bash pnpm add peam ``` ```bash yarn add peam ``` ```bash bun add peam ``` ## Usage The CLI builds a search index from one or more sources and exports it to one or more stores. ### Basic usage ```bash peam \ --source fileBased --projectDir . --sourceDir .next \ --exclude /admin/** \ --store fileBased --indexPath .peam/index.json ``` ### Multiple sources and stores ```bash peam \ --source fileBased --projectDir . --sourceDir dist \ --source prerender --projectDir . --prerenders ./out/prerender-manifest.json \ --exclude /drafts/** --exclude /private/** \ --store fileBased --indexPath .peam/index.json ``` ### Help and discovery ```bash peam --help peam --help sources peam --help stores peam --version ``` ### Notes * When `--source` or `--store` is omitted, the CLI uses the default `fileBased` type. * `--exclude` can be repeated to add multiple patterns. * `--robotsTxt` accepts `true`, `false`, or a file path. # Sources # Overview Sources discover pages or files to index. The CLI supports `fileBased` and `prerender` sources. ## File-based source Scans a build output directory for HTML files. It matches the [file-based source](/docs/indexing/file-based-source) behavior. ```bash peam \ --source fileBased --projectDir . --sourceDir dist --glob "**/*.html" \ --store fileBased --indexPath .peam/index.json ``` **Options** * `projectDir`: project root directory. * `sourceDir`: directory containing files to index (auto-detected if omitted). * `glob`: glob pattern for files (default `**/*.{html,htm}`). ## Prerender source Uses framework prerender manifests. It matches the [prerender source](/docs/indexing/prerender-source) behavior. ```bash peam \ --source prerender --projectDir . --prerenders ./out/prerender-manifest.json \ --store fileBased --indexPath .peam/index.json ``` **Options** * `projectDir`: project root directory. * `prerenders`: array of prerender pages (JSON) or a JSON string. # Stores # Overview Stores define where Peam writes the search index. The CLI currently supports `fileBased` stores. ## File-based store Writes a JSON index file to disk. It matches the [file-based store](/docs/storage/file-based-store) behavior. ```bash peam \ --source fileBased --projectDir . --sourceDir dist \ --store fileBased --indexPath .peam/index.json ``` **Options** * `indexPath`: path to the index file relative to `baseDir` (default `.peam/index.json`). * `baseDir`: base directory for the index file (defaults to `process.cwd()`). ## Multiple stores Repeat `--store` to export to multiple destinations: ```bash peam \ --source fileBased --projectDir . --sourceDir dist \ --store fileBased --indexPath .peam/index.json \ --store fileBased --indexPath public/.peam/index.json ``` # Usage # Overview The CLI builds a search index from one or more sources and exports it to one or more stores. ## Basic usage ```bash peam \ --source fileBased --projectDir . --sourceDir .next \ --exclude /admin/** \ --store fileBased --indexPath .peam/index.json ``` ## Multiple sources and stores ```bash peam \ --source fileBased --projectDir . --sourceDir dist \ --source prerender --projectDir . --prerenders ./out/prerender-manifest.json \ --exclude /drafts/** --exclude /private/** \ --store fileBased --indexPath .peam/index.json ``` ## Help and discovery ```bash peam --help peam --help sources peam --help stores peam --version ``` ## Notes * When `--source` or `--store` is omitted, the CLI uses the default `fileBased` type. * `--exclude` can be repeated to add multiple patterns. * `--robotsTxt` accepts `true`, `false`, or a file path. # AskAI.Chat import { Preview } from '@/components/preview'; # Overview Floating chat surface that adapts to device size, sliding up as a bottom sheet on mobile and anchoring as a compact popup on desktop. Pair it with [`AskAI.Trigger`](/docs/components/ask-ai-trigger). ## Demo ## Usage ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Props | Prop | Type | Default | Description | | ---------- | ---------------------- | ----------- | --------------------------------- | | `children` | `ReactNode` | `undefined` | Custom chat contents. | | *(all)* | `HTMLDivElement` props | — | Accepts all standard `div` props. | # AskAI.Dialog import { Preview } from '@/components/preview'; # Overview Centered modal surface that shows the AskAI chat UI in a focused overlay. Pair it with [`AskAI.Trigger`](/docs/components/ask-ai-trigger) or another custom control. ## Demo ## Usage ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Props | Prop | Type | Default | Description | | ---------- | ---------------------- | ----------- | --------------------------------- | | `children` | `ReactNode` | `undefined` | Custom dialog contents. | | *(all)* | `HTMLDivElement` props | — | Accepts all standard `div` props. | # AskAI.Header import { Preview } from '@/components/preview'; # Overview Header row with the Peam icon, title, and close/clear actions, designed to sit at the top of AskAI surfaces like [`AskAI.Dialog`](/docs/components/ask-ai-dialog), [`AskAI.Chat`](/docs/components/ask-ai-chat), or [`AskAI.Sidepane`](/docs/components/ask-ai-sidepane). ## Demo ## Props | Prop | Type | Default | Description | | ------------ | ---------------------- | ---------- | -------------------------------------- | | `heading` | `ReactNode` | `'Ask AI'` | Heading text or element. | | `closeLabel` | `string` | `'Close'` | Accessible label for the close action. | | *(all)* | `HTMLDivElement` props | — | Accepts all standard `div` props. | # AskAI.Inline import { Preview } from '@/components/preview'; # Overview Render the entire chat surface ([`AskAI.Header`](/docs/components/ask-ai-header), [`AskAI.Messages`](/docs/components/ask-ai-messages), [`AskAI.Suggestions`](/docs/components/ask-ai-suggestions), [`AskAI.Input`](/docs/components/ask-ai-input)) inline within any container, without needing a separate dialog or sheet wrapper. ## Demo ## Usage ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Props | Prop | Type | Default | Description | | ------- | ---------------------- | ------- | --------------------------------- | | *(all)* | `HTMLDivElement` props | — | Accepts all standard `div` props. | # AskAI.Input import { Preview } from '@/components/preview'; # Overview Prompt input area with text entry, optional speech input, and submit actions for sending messages. Often used with [`AskAI.Messages`](/docs/components/ask-ai-messages) and [`AskAI.Suggestions`](/docs/components/ask-ai-suggestions). ## Demo ## Props | Prop | Type | Default | Description | | ------- | ---------------------- | ------- | --------------------------------- | | *(all)* | `HTMLDivElement` props | — | Accepts all standard `div` props. | # AskAI.Messages import { Preview } from '@/components/preview'; # Overview Scrollable message list for the current chat session, including per-message actions and expandable source references. Typically used inside [`AskAI.Dialog`](/docs/components/ask-ai-dialog), [`AskAI.Chat`](/docs/components/ask-ai-chat), or [`AskAI.Sidepane`](/docs/components/ask-ai-sidepane). ## Demo ## Props | Prop | Type | Default | Description | | ------- | ---------------------- | ------- | --------------------------------- | | *(all)* | `HTMLDivElement` props | — | Accepts all standard `div` props. | # AskAIProvider # Overview `AskAIProvider` supplies the AskAI context so you can render [`AskAI`](/docs/components/ask-ai) surfaces or call [`useAskAI`](/docs/components/use-ask-ai) anywhere in your tree without needing a preset surface wrapper. This is useful when you want global access to chat actions (open, send, clear) while keeping the UI surfaces in a fixed place, such as a layout footer or floating panel. ## Usage ```tsx import { AskAIProvider, AskAI, useAskAI } from 'peam/client'; function AskAICTA() { const { sendMessage } = useAskAI(); return ( ); } export default function RootLayout({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` ## Context reuse By default, [`AskAI`](/docs/components/ask-ai) will reuse an existing provider when one is present. If you need a local, isolated chat state, set `reuseContext={false}` on a nested `AskAI`. ```tsx import { AskAIProvider, AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Props `AskAIProvider` accepts the same props as [`AskAI`](/docs/components/ask-ai), including `endpoint`, `chatTransport`, and `persistence`. # AskAI.Sidepane import { Preview } from '@/components/preview'; # Overview Sidepane surface that slides in from the right on desktop and from the bottom on mobile, giving you a persistent chat surface without blocking the page. Pair it with [`AskAI.Trigger`](/docs/components/ask-ai-trigger). ## Demo ## Usage ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Notes * Must be rendered inside `AskAI`. ## Props | Prop | Type | Default | Description | | ---------- | ---------------------- | ----------- | --------------------------------- | | `children` | `ReactNode` | `undefined` | Custom sidepane contents. | | *(all)* | `HTMLDivElement` props | — | Accepts all standard `div` props. | # AskAI.Suggestions import { Preview } from '@/components/preview'; # Overview Suggested prompt chips rendered above the input to help users start a conversation or explore common tasks. Usually paired with [`AskAI.Input`](/docs/components/ask-ai-input). ## Demo ## Props | Prop | Type | Default | Description | | --------------- | -------------------------- | -------------------------------------------------------------------------------------- | --------------------------------------- | | `prompts` | `string[]` | `['Summarize this page', 'Where should I get started?', 'What can you help me with?']` | Suggested prompts. | | `onPromptClick` | `(prompt: string) => void` | `undefined` | Handle prompt clicks. | | `onlyWhenEmpty` | `boolean` | `true` | Render only when there are no messages. | # AskAI.Trigger import { Preview } from '@/components/preview'; # Overview Button-like trigger that toggles the open state for [`AskAI.Dialog`](/docs/components/ask-ai-dialog), [`AskAI.Chat`](/docs/components/ask-ai-chat), or [`AskAI.Sidepane`](/docs/components/ask-ai-sidepane). Use the default floating Peam button or pass custom content (including `asChild`) to integrate with your UI. ## Demo ## Usage ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Props | Prop | Type | Default | Description | | -------------- | ----------------------- | ------------- | ----------------------------------------------------- | | `asChild` | `boolean` | `false` | Use a custom element via Radix `Slot`. | | `children` | `ReactNode` | `undefined` | Custom trigger contents. | | `inlineButton` | `boolean` | `false` | Renders the default button without fixed positioning. | | `variant` | `'icon' \| 'iconLabel'` | `'iconLabel'` | Default Peam button style. | # AskAI import { Preview } from '@/components/preview'; # Overview The top-level component that wires context, transport, and persistence, then renders the default preset ([`AskAI.Trigger`](/docs/components/ask-ai-trigger) + [`AskAI.Dialog`](/docs/components/ask-ai-dialog)). Use it as-is for a drop-in chat UI or compose the underlying pieces for custom layouts. Here is a basic example using the default [`AskAI.Trigger`](/docs/components/ask-ai-trigger) and [`AskAI.Dialog`](/docs/components/ask-ai-dialog): ```tsx ``` ## Anatomy * `AskAI` provides state, transport, and context. * [`AskAI.Trigger`](/docs/components/ask-ai-trigger) toggles open state (defaults to the floating Peam button). * [`AskAI.Dialog`](/docs/components/ask-ai-dialog), [`AskAI.Chat`](/docs/components/ask-ai-chat), or [`AskAI.Sidepane`](/docs/components/ask-ai-sidepane) render the surface. * [`AskAI.Header`](/docs/components/ask-ai-header), [`AskAI.Messages`](/docs/components/ask-ai-messages), [`AskAI.Suggestions`](/docs/components/ask-ai-suggestions), and [`AskAI.Input`](/docs/components/ask-ai-input) are layout primitives. * [`AskAI.Inline`](/docs/components/ask-ai-inline) renders the full inline surface without another wrapper. ```tsx ``` ## Overview ## Props | Prop | Type | Default | Description | | --------------- | ------------------------------ | ------------- | ---------------------------------------------------------- | | `endpoint` | `string` | `'/api/peam'` | API endpoint used by the chat transport. | | `open` | `boolean` | `undefined` | Controlled open state. | | `defaultOpen` | `boolean` | `false` | Uncontrolled initial open state. | | `chatTransport` | `HttpChatTransport` | `undefined` | Override the default transport. | | `persistence` | `boolean \| { key?: string }` | `true` | Configure chat persistence or disable it. | | `reuseContext` | `boolean` | `true` | Reuse an existing `AskAIContext` if present. | | `children` | `ReactNode` | `undefined` | Custom composition (if omitted, renders Trigger + Dialog). | | `className` | `string` | `undefined` | Class name applied to the root wrapper. | # Components # Overview Peam is built from small, composable pieces. You can use the preset [`AskAI`](/docs/components/ask-ai) for a complete chat UI, or compose individual surfaces like [`AskAI.Dialog`](/docs/components/ask-ai-dialog) and [`AskAI.Chat`](/docs/components/ask-ai-chat) with a [`AskAI.Trigger`](/docs/components/ask-ai-trigger). To customize the visuals, adjust theme tokens on the root using the [Styling](/docs/components/styling) guide. If you need to control chat actions from anywhere in your app, use [`useAskAI`](/docs/components/use-ask-ai) or the [`AskAIProvider`](/docs/components/ask-ai-provider). Start with [`AskAI`](/docs/components/ask-ai) for the quickest setup, then explore surfaces and primitives to tailor the experience. # Styling import { Preview } from '@/components/preview'; # Overview Peam client components are styled with shadcn/ui primitives and theme tokens. You can customize the look and feel by overriding the CSS variables listed below on any wrapper element (for example, the `AskAI` root). For dark mode, apply a `dark` class on the same element (or a parent) and override the variables again for the dark palette. ## CSS variables | Variable | Purpose | | -------------------------- | ----------------------------------- | | `--background` | Base surface background. | | `--foreground` | Base surface text color. | | `--card` | Card/surface background for panels. | | `--card-foreground` | Text color on cards/surfaces. | | `--popover` | Popover surface background. | | `--popover-foreground` | Text color on popovers. | | `--primary` | Primary brand/action color. | | `--primary-foreground` | Text color on primary elements. | | `--secondary` | Secondary surface/background color. | | `--secondary-foreground` | Text color on secondary surfaces. | | `--muted` | Muted surface/background color. | | `--muted-foreground` | Text color on muted surfaces. | | `--accent` | Accent surface/background color. | | `--accent-foreground` | Text color on accent surfaces. | | `--destructive` | Destructive/action color. | | `--destructive-foreground` | Text color on destructive elements. | | `--border` | Border color. | | `--input` | Input border color. | | `--ring` | Focus ring color. | | `--radius` | Base border radius. | ## Dark mode To customize the dark theme, add a `dark` class and override the same variables for the dark palette. The preview below uses `.peam-root` for the light theme and `.peam-root.dark` for the dark theme. ## Demo # useAskAI import { Preview } from '@/components/preview'; # Overview Access and control the AskAI state from any component inside [`AskAI`](/docs/components/ask-ai), including surfaces like [`AskAI.Dialog`](/docs/components/ask-ai-dialog) or [`AskAI.Chat`](/docs/components/ask-ai-chat). ## Demo This demo uses `useAskAI` to open [`AskAI.Dialog`](/docs/components/ask-ai-dialog) and send a predefined question when the button is clicked. ## Example ```tsx import { AskAI, useAskAI } from 'peam/client'; function UseAskAIButton() { const { sendMessage } = useAskAI(); return ( ); } export default function Page() { return ( ); } ``` ## Example with [`AskAIProvider`](/docs/components/ask-ai-provider) Use [`AskAIProvider`](/docs/components/ask-ai-provider) in a layout and call `useAskAI` from a page or nested component, then render [`AskAI`](/docs/components/ask-ai) to provide the surfaces (like [`AskAI.Trigger`](/docs/components/ask-ai-trigger) and [`AskAI.Dialog`](/docs/components/ask-ai-dialog)). ```tsx // app/layout.tsx import { AskAIProvider, AskAI } from 'peam/client'; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` ```tsx // app/page.tsx import { useAskAI } from 'peam/client'; function AskAICTA() { const { sendMessage } = useAskAI(); return ( ); } export default function Page() { return (
); } ``` ## Returns | Value | Type | Description | | --------------- | ---------------------------------------------------------- | ---------------------------------------------------------------------- | | `open` | `boolean` | Current open state. | | `setOpen` | `(open: boolean) => void` | Set open state. | | `toggleOpen` | `() => void` | Toggle open state. | | `input` | `string` | Current input text. | | `setInput` | `(value: string, options?: { open?: boolean }) => void` | Update input text and optionally open the surface. | | `messages` | `UIMessage[]` | Current chat messages. | | `status` | `ChatStatus` | Streaming status. | | `error` | `Error \| undefined` | Transport or streaming error. | | `isLoading` | `boolean` | Loading persisted history. | | `sendMessage` | `({ text: string }, options?: { open?: boolean }) => void` | Send a message and optionally open the surface. | | `handleSubmit` | `(message: PromptInputMessage) => void` | Submit handler used by [`AskAI.Input`](/docs/components/ask-ai-input). | | `regenerate` | `(options?: { messageId?: string }) => void` | Regenerate a response. | | `clearMessages` | `() => void \| Promise` | Clear message history. | # Architecture # Overview Peam is organized around a build-time pipeline and a runtime query stack. The builder ingests your content through [index sources](/docs/indexing/sources), applies [filters](/docs/indexing/filters), and produces index artifacts that are written to [index stores](/docs/storage). At runtime, the search engine loads those artifacts to serve AI-powered answers to your client. ## High-level architecture
Server Server --> SearchEngine SearchEngine --> Retriever Retriever --> LLM LLM --> Client end subgraph Build_Time[Build-time] direction TB Sources[Docs, files, APIs] IndexSources[Index sources] Filters[Filters] Indexers[Indexers] Stores[Index stores] Sources --> IndexSources IndexSources --> Filters Filters --> Indexers Indexers --> Stores end `} />
## What each part does * **Index sources** discover pages or content to index. See [Index sources](/docs/indexing/sources). * **Filters** prune or refine candidates before indexing. See [Filters](/docs/indexing/filters). * **Peam Builder** orchestrates ingestion, normalization, and indexing. * **Indexers** parse and structure content, producing embeddings, metadata, and search artifacts. * **Index stores** persist index artifacts for runtime search. See [Storage](/docs/storage). * **Search engine** loads stored artifacts and powers retrieval. * **Runtime server** handles user queries, retrieval, and answer composition. * **Client** renders [AskAI](/docs/components/ask-ai) surfaces and sends messages to the runtime API. Next, see [Data flow](/docs/core-concepts/data-flow) to understand how a single query moves through the system. # Data flow # Overview Peam uses a two-phase workflow: [indexing](/docs/indexing) at build time and querying at runtime. The builder creates artifacts once; the runtime reuses them for fast, consistent answers. ## Indexing flow >Source: Discover pages Source->>Filters: Apply filters Filters-->>Indexer: Filtered pages Filters->>Indexer: Normalize + chunk Indexer->>Indexer: Enrich metadata Indexer->>Store: Write index `} /> ## Query flow >Server: sendMessage() Server->>Search: search(query) Search->>Store: Load index artifacts Store-->>Search: Index data Search->>Retriever: Retrieve + rerank Retriever-->>Server: Ranked context Server->>LLM: Compose answer LLM-->>Client: Streamed response `} /> ## Notes * Index sources define where content is discovered from. See [Index sources](/docs/indexing/sources). * Filters narrow the candidate set before indexing. See [Filters](/docs/indexing/filters). * Index stores persist artifacts for runtime search. See [Storage](/docs/storage). * Client surfaces stay thin: they render [AskAI](/docs/components/ask-ai) UI and send messages to the server. # Core concepts # Overview This section explains how Peam is structured and how data moves through the platform. Start with the [architecture overview](/docs/core-concepts/architecture), then dive into the [data flow](/docs/core-concepts/data-flow) to understand [indexing](/docs/indexing), retrieval, and runtime answers. ## Continue with # Astro import { Step, Steps } from 'fumadocs-ui/components/steps'; import Link from 'fumadocs-core/link'; # Overview Use Astro with React islands to render AskAI where you need it, without turning the whole site into React. The API route lives in `src/pages/api/peam.ts`, keeping server logic clean and scoped. You get fast pages with a focused, AI-ready experience. ## Install Dependencies npm pnpm yarn bun ```bash npm install peam ``` ```bash pnpm add peam ``` ```bash yarn add peam ``` ```bash bun add peam ``` ## Add AskAI in the Base Layout ```astro --- import { AskAI } from 'peam/client'; import '../styles/global.css'; interface Props { title: string; description?: string; } const { title, description } = Astro.props as Props; --- ``` ## Add the API Route Create `src/pages/api/peam.ts` and add: ```ts // [!code highlight] export { POST } from 'peam/server'; export const prerender = false; ``` ## Export the OpenAI API Key Peam uses ChatGPT (OpenAI GPT-4o) by default, so `OPENAI_API_KEY` must be set in your environment. ```bash export OPENAI_API_KEY="your-api-key" ``` ## Examples Browse the full app in: * examples/astro-react See the [API Reference](/docs/api-reference) for all available options. ## Customize the model Define your own handler and pass a model to `createChat`. Peam uses the Vercel AI SDK, so import models from the provider package you choose. See the providers and models guide. ```ts import { createChat } from 'peam/server'; import { openai } from '@ai-sdk/openai'; export const POST = createChat({ model: openai('gpt-4o-mini'), }).handler; ``` # Getting Started import { Card, Cards } from 'fumadocs-ui/components/card'; import { AstroDark, AstroLight, Next, NuxtGray, ReactRouterDark, ReactRouterLight, Vite, } from '@/app/(home)/components/frameworks'; import Link from 'fumadocs-core/link'; import { Globe } from 'lucide-react'; # Frameworks Pick a guide below, or browse the full examples folder on GitHub: examples.
Next.js
Vite
Astro
React Router
Any website Coming soon
Nuxt Coming soon
# Next.js import { Step, Steps } from 'fumadocs-ui/components/steps'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; import Link from 'fumadocs-core/link'; # Overview Connect Peam to your Next.js app by adding the AskAI client and a single API route. Wrap your config with `withPeam()` so the build adapter can generate the search index. You’ll be running in minutes with a clean, production-ready setup. ## Setup ## Install Dependencies npm pnpm yarn bun ```bash npm install peam @peam-ai/next ``` ```bash pnpm add peam @peam-ai/next ``` ```bash yarn add peam @peam-ai/next ``` ```bash bun add peam @peam-ai/next ``` ## Add AskAI to the Root Layout ```tsx import type { Metadata } from 'next'; import { AskAI } from 'peam/client'; import './globals.css'; export const metadata: Metadata = { title: 'Next.js Example - Peam', description: 'A simple Next.js example application with Peam', }; export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( {/* ... */} {children} // [!code highlight] ); } ``` ## Add the Peam API Route Create `app/api/peam/route.ts` in your project and add: ```ts export const maxDuration = 30; // [!code highlight] export { POST } from '@peam-ai/next/route'; ``` ## Wrap Next.js Config with withPeam ```ts import withPeam from '@peam-ai/next'; const nextConfig = { /* config options here */ }; export default withPeam()(nextConfig); ``` ## Export the OpenAI API Key Peam uses ChatGPT (OpenAI GPT-4o) by default, so `OPENAI_API_KEY` must be set in your environment. ```bash export OPENAI_API_KEY="your-api-key" ``` Next.js 14 or older Next.js 15+ uses the build adapter configured by `withPeam()`. For Next.js 14 (or older), add a `postbuild` script that runs `peam` to generate the index after `next build`. ## Examples Browse the example apps for a complete setup: * examples/nextjs-14 * examples/nextjs-15 * examples/nextjs-16 See the [API Reference](/docs/api-reference) for all available options. ## Customize the model If you want a different model, define your own route handler and pass a model to `createChat`. Peam uses the Vercel AI SDK, so import models from the provider package you choose. See the providers and models guide. ```ts import { createChat } from '@peam-ai/next/route'; import { openai } from '@ai-sdk/openai'; export const POST = createChat({ model: openai('gpt-4o-mini'), }).handler; ``` # React Router import { Step, Steps } from 'fumadocs-ui/components/steps'; import Link from 'fumadocs-core/link'; # Overview Mount `AskAI` in your root route and expose a simple `/api/peam` action endpoint. Peam streams responses from the route action while keeping your React Router app fully client-driven. ## Install Dependencies npm pnpm yarn bun ```bash npm install peam ``` ```bash pnpm add peam ``` ```bash yarn add peam ``` ```bash bun add peam ``` ## Add AskAI to the Root Route In `app/root.tsx`: ```tsx import { AskAI } from 'peam/client'; export default function App() { return (
{/* ... */} // [!code highlight]
); } ```
## Add the Peam API Route Create `app/routes/api.peam.ts` and add: ```ts import { createChat } from 'peam/server'; const handler = createChat().handler; export async function action({ request }: { request: Request }) { return handler(request); } export function loader() { return new Response(JSON.stringify({ error: 'Method not allowed' }), { status: 405, headers: { 'Content-Type': 'application/json' }, }); } ``` ## Export the OpenAI API Key Peam uses ChatGPT (OpenAI GPT-4o) by default, so `OPENAI_API_KEY` must be set in your environment. ```bash export OPENAI_API_KEY="your-api-key" ```
## Examples Browse the full app in: * examples/react-router See the [API Reference](/docs/api-reference) for all available options. ## Customize the model Pass a custom model into `createChat`. Peam uses the Vercel AI SDK, so import models from the provider package you choose. See the providers and models guide. ```ts import { createChat } from 'peam/server'; import { openai } from '@ai-sdk/openai'; const handler = createChat({ model: openai('gpt-4o-mini'), }).handler; ``` # Vite import { Step, Steps } from 'fumadocs-ui/components/steps'; import Link from 'fumadocs-core/link'; # Overview Add Peam to a Vite + React SSR app by mounting AskAI in your layout and wiring a simple API route. Your server calls `createChat()` per request, while the client streams results from `/api/peam`. It’s a lightweight setup that keeps your stack fast and flexible. ## Install Dependencies npm pnpm yarn bun ```bash npm install peam ``` ```bash pnpm add peam ``` ```bash yarn add peam ``` ```bash bun add peam ``` ## Add AskAI to the Root Layout ```tsx export { Layout }; import { AskAI } from 'peam/client'; import type { ReactNode } from 'react'; import '../index.css'; function Layout({ children }: { children: ReactNode }) { return ( {/* ... */} {/* ... */} {children} // [!code highlight] ); } ``` ## Add an API Endpoint in the Express Server The server handler is built with `createChat()` from `peam/server` and invoked per request. Create or edit `api/server.ts` and add the /api/peam route: ```ts import { createChat } from 'peam/server'; // ... Express setup const chat = createChat(); // [!code highlight] app.post('/api/peam', async (req, res) => { // ... convert to Request const response = await chat.handler(request); // ... stream response }); // ... server startup ``` ## Export the OpenAI API Key Peam uses ChatGPT (OpenAI GPT-4o) by default, so `OPENAI_API_KEY` must be set in your environment. ```bash export OPENAI_API_KEY="your-api-key" ``` ## Examples Browse the full app in: * examples/vite-react See the [API Reference](/docs/api-reference) for all available options. ## Customize the model Pass a custom model to `createChat` when wiring your route. Peam uses the Vercel AI SDK, so import models from the provider package you choose. See the providers and models guide. ```ts import { createChat } from 'peam/server'; import { openai } from '@ai-sdk/openai'; const chat = createChat({ model: openai('gpt-4o-mini'), }); ``` # File-based source # Overview The file-based source scans a build output directory for HTML files and turns them into page candidates. It is the default source for most static or pre-rendered sites. See [Index sources](/docs/indexing/sources) for how sources fit into the pipeline. ## Options (CLI) | Option | Type | Default | Description | | ------------ | -------- | ----------------- | ------------------------------- | | `projectDir` | `string` | `process.cwd()` | Project root directory. | | `sourceDir` | `string` | auto-detected | Build output directory to scan. | | `glob` | `string` | `**/*.{html,htm}` | Glob pattern for HTML files. | ## Example (CLI) ```bash peam \ --source fileBased --projectDir . --sourceDir dist --glob "**/*.html" \ --store fileBased --indexPath .peam/index.json ``` ## Notes * The source auto-detects output folders like `.next`, `dist`, and `build` if `sourceDir` is not provided. * It normalizes paths by stripping common build prefixes and removing `.html` / `/index`. # Filters # Overview Filters receive a list of page candidates and return a refined list. They run after [sources](/docs/indexing/sources) and before indexing. Configure them via [withPeam](/docs/api-reference/next/with-peam) or the CLI. ## Built-in filters * **CommonFilter**: removes common framework error pages and internal routes. * **PrerenderPathFilter**: normalizes prerender paths (used when prerender sources are present). * **ExcludePatternFilter**: drops paths matching user-provided patterns. * **RobotsTxtFilter**: applies rules from `robots.txt` (optional, auto-discovered or custom path). ## Configuration (Next.js) ```ts // next.config.ts import withPeam from '@peam-ai/next'; export default withPeam({ exclude: ['/private', '/drafts/**'], robotsTxt: true, })(); ``` When `robotsTxt` is `true`, Peam automatically discovers `robots.txt` in your project. To use a custom location, pass a path instead. See [`robotsTxt`](/docs/api-reference/next/with-peam#robotstxt). ## Configuration (CLI) ```bash peam \ --source fileBased --projectDir . --sourceDir dist \ --exclude /private --exclude /drafts/** \ --robotsTxt true \ --store fileBased --indexPath .peam/index.json ``` ## Notes * `exclude` accepts a string or array, and supports glob-style patterns. * `robotsTxt` can be `true` for auto-discovery or a custom file path (for example, `--robotsTxt ./public/robots.txt`). See [`robotsTxt`](/docs/api-reference/next/with-peam#robotstxt). * If a prerender source is used, the prerender filter is added automatically. # Indexing import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; # Overview Indexing is the build-time pipeline that turns your content into searchable artifacts. Most teams configure it via [withPeam](/docs/api-reference/next/with-peam) (Next.js) or the **Peam CLI**. The builder and indexers are managed for you. Next.js 14 or older Automatic prerender discovery only works on Next.js 15+. For Next.js 14 (or older), add a `postbuild` script that runs `peam` to discover pages after `next build`. See the [Next.js getting started guide](/docs/getting-started/next). ## Quick start (Next.js) ```ts // next.config.ts import withPeam from '@peam-ai/next'; export default withPeam({ exclude: ['/admin/**', '/private/**'], robotsTxt: true, })(); ``` ## Quick start (CLI) ```bash peam \ --source fileBased --projectDir . --sourceDir .next \ --exclude /admin/** \ --store fileBased --indexPath .peam/index.json ``` ## How indexing runs At build time, Peam discovers pages via [index sources](/docs/indexing/sources), applies [filters](/docs/indexing/filters), then uses the indexing pipeline to produce artifacts that are exported to your configured [store](/docs/storage). ## Continue with # Prerender source # Overview The prerender source indexes framework-provided prerender manifests. It expects an array of prerendered pages (or a JSON string) and maps them to file paths. It is primarily used by [withPeam](/docs/api-reference/next/with-peam) on Next.js 15+ for automatic page discovery, but you can also supply it directly via the CLI. ## Options (CLI) | Option | Type | Default | Description | | ------------ | --------------------------- | ------- | ------------------------------------ | | `prerenders` | `PrerenderPage[] \| string` | — | Prerender pages list or JSON string. | | `projectDir` | `string` | — | Project root directory. | ## Example (CLI) ```bash peam \ --source prerender --projectDir . --prerenders ./out/prerender-manifest.json \ --store fileBased --indexPath .peam/index.json ``` ## Notes * If a fallback file path ends with `/.html` (Next.js 15), it is normalized to `/index.html`. * Paths are derived from prerender entries rather than filesystem scanning. # Index sources import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; # Overview Index sources discover pages or files that should be indexed. Each source produces a list of page candidates (path + file path) that the pipeline can [filter](/docs/indexing/filters) and index. Peam ships with two sources today: * [File-based source](/docs/indexing/file-based-source) * [Prerender source](/docs/indexing/prerender-source) The prerender source is primarily used by [withPeam](/docs/api-reference/next/with-peam) on Next.js 15+ to auto-discover pages, but it can also be selected manually via the CLI. Next.js 14 or older Automatic prerender discovery only works on Next.js 15+. For Next.js 14 (or older), add a `postbuild` script that runs `peam` to discover pages after `next build`. See the [Next.js getting started guide](/docs/getting-started/next). ## Configure sources ### Next.js (withPeam) When using Next.js, [withPeam](/docs/api-reference/next/with-peam) auto-detects build output and wires the default source for you. You typically only set [filters](/docs/indexing/filters) and [storage](/docs/storage) options: ```ts // next.config.ts import withPeam from '@peam-ai/next'; export default withPeam({ exclude: ['/admin/**'], robotsTxt: true, })(); ``` ### CLI Use the CLI to explicitly choose and configure sources: ```bash peam \ --source fileBased --projectDir . --sourceDir dist --glob "**/*.html" \ --source prerender --projectDir . --prerenders ./out/prerender-manifest.json \ --store fileBased --indexPath .peam/index.json ``` # File-based store # Overview The file-based store reads and writes index data to a JSON file on disk. Configure it through [withPeam](/docs/api-reference/next/with-peam) or the CLI. See [Storage](/docs/storage) for selecting a store. ## Options (withPeam) | Option | Type | Default | Description | | ----------- | -------- | ------------------ | ---------------------------------------------- | | `baseDir` | `string` | `process.cwd()` | Base directory for the index file. | | `indexPath` | `string` | `.peam/index.json` | Path to the index file, relative to `baseDir`. | ## Example (Next.js) ```ts // next.config.ts import withPeam from '@peam-ai/next'; export default withPeam({ searchStore: { type: 'fileBased', config: { indexPath: '.peam/index.json' }, }, })(); ``` ## Example (CLI) ```bash peam \ --source fileBased --projectDir . --sourceDir dist \ --store fileBased --indexPath .peam/index.json ``` # Storage # Overview Storage is where index artifacts are persisted and later loaded at runtime. Configure it through [withPeam](/docs/api-reference/next/with-peam) (Next.js) or the **Peam CLI**. ## Selecting a store Index stores define where Peam writes index artifacts and where the runtime reads them back. Use [`searchStore`](/docs/api-reference/next/with-peam#searchstore) (Next.js) or `--store` (CLI) to choose an implementation. ## Quick start (Next.js) ```ts // next.config.ts import withPeam from '@peam-ai/next'; export default withPeam({ searchStore: { type: 'fileBased', config: { indexPath: '.peam/index.json' }, }, })(); ``` ## Quick start (CLI) ```bash peam \ --source fileBased --projectDir . --sourceDir dist \ --store fileBased --indexPath .peam/index.json ``` ## Notes * `withPeam` uses a single [`searchStore`](/docs/api-reference/next/with-peam#searchstore) configuration at build time and runtime. * The CLI can export to multiple stores by repeating `--store` with different configs. ## Continue with # AskAI.Chat # Overview Popup chat surface that floats over the page. Pair it with [AskAI.Trigger](/docs/api-reference/client/ask-ai-trigger). ## Usage ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Notes * `AskAI.Chat` must be rendered inside [AskAI](/docs/api-reference/client/ask-ai). * For inline rendering, use [AskAI.Inline](/docs/api-reference/client/ask-ai-inline). # AskAI.Dialog # Overview Modal dialog chat surface. Pair it with [AskAI.Trigger](/docs/api-reference/client/ask-ai-trigger). ## Usage ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Notes * `AskAI.Dialog` must be rendered inside [AskAI](/docs/api-reference/client/ask-ai). * For inline rendering inside the dialog, use [AskAI.Inline](/docs/api-reference/client/ask-ai-inline). # AskAI.Header # Overview Header bar that shows the AskAI title and actions (clear conversation, close). Typically used with [AskAI.Messages](/docs/api-reference/client/ask-ai-messages) and [AskAI.Input](/docs/api-reference/client/ask-ai-input). ## Usage ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Props ```ts import type { ComponentPropsWithoutRef, ReactNode } from 'react'; export interface AskAIHeaderProps extends ComponentPropsWithoutRef<'div'> { heading?: ReactNode; closeLabel?: string; } ``` ## Notes * Uses `closeLabel` for the close button aria-label. * The delete button only shows when there are messages and the chat is idle. # AskAI.Inline # Overview Inline layout that composes [AskAI.Header](/docs/api-reference/client/ask-ai-header), [AskAI.Messages](/docs/api-reference/client/ask-ai-messages), [AskAI.Suggestions](/docs/api-reference/client/ask-ai-suggestions), and [AskAI.Input](/docs/api-reference/client/ask-ai-input). ## Usage ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Notes * Must be rendered inside [AskAI](/docs/api-reference/client/ask-ai) or [AskAIProvider](/docs/api-reference/client/ask-ai-provider). # AskAI.Input # Overview Text input for sending prompts, including optional speech input and submit button. It binds to [useAskAI](/docs/api-reference/client/use-ask-ai). ## Usage ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Notes * Binds to the AskAI context `input` and `handleSubmit`. * Disables submit when the input is empty and not streaming. # AskAI.Messages # Overview Message list that renders conversation history, sources, and retry/copy actions. Often paired with [AskAI.Header](/docs/api-reference/client/ask-ai-header) and [AskAI.Input](/docs/api-reference/client/ask-ai-input). ## Usage ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Notes * Renders sources when `source-url` parts are present in the assistant response. * Shows a retry action when the response fails. # AskAIProvider # Overview Provides AskAI context for composing surfaces manually or sharing context across multiple surfaces. Pair it with [AskAI.Trigger](/docs/api-reference/client/ask-ai-trigger) and a surface like [AskAI.Sidepane](/docs/api-reference/client/ask-ai-sidepane). ## Type Definition ```ts import type { ReactNode } from 'react'; import type { HttpChatTransport, UIMessage } from 'ai'; export type AskAIProviderProps = { children?: ReactNode; endpoint?: string; open?: boolean; defaultOpen?: boolean; chatTransport?: HttpChatTransport; persistence?: boolean | { key?: string }; }; ``` ## Usage ```tsx import { AskAI, AskAIProvider } from 'peam/client'; export default function Page() { return ( ); } ``` ## Notes * `AskAIProvider` does not render UI. It only supplies context. * [AskAI.Trigger](/docs/api-reference/client/ask-ai-trigger), [AskAI.Dialog](/docs/api-reference/client/ask-ai-dialog), [AskAI.Chat](/docs/api-reference/client/ask-ai-chat), [AskAI.Sidepane](/docs/api-reference/client/ask-ai-sidepane), and [AskAI.Inline](/docs/api-reference/client/ask-ai-inline) all rely on this context. # AskAI.Sidepane # Overview Sidepane chat surface that slides in from the right on desktop and from the bottom on mobile. Pair it with [AskAI.Trigger](/docs/api-reference/client/ask-ai-trigger). ## Usage ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Notes * `AskAI.Sidepane` must be rendered inside [AskAI](/docs/api-reference/client/ask-ai). * For inline rendering inside the sidepane, use [AskAI.Inline](/docs/api-reference/client/ask-ai-inline). # AskAI.Suggestions # Overview Renders a horizontal list of prompt suggestions that can be clicked to send a message. The suggestions call into [useAskAI](/docs/api-reference/client/use-ask-ai). ## Usage ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Props ```ts import type { ComponentPropsWithoutRef } from 'react'; export interface AskAISuggestionsProps extends ComponentPropsWithoutRef<'div'> { prompts?: string[]; onPromptClick?: (prompt: string) => void; onlyWhenEmpty?: boolean; } ``` ## Notes * Defaults to a small set of common prompts. * When `onlyWhenEmpty` is `true`, it renders only if there are no messages. # AskAI.Trigger # Overview Trigger button for opening and closing AskAI surfaces. Use it with [AskAI.Dialog](/docs/api-reference/client/ask-ai-dialog), [AskAI.Chat](/docs/api-reference/client/ask-ai-chat), or [AskAI.Sidepane](/docs/api-reference/client/ask-ai-sidepane). ## Usage ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Props ```ts import type { ComponentPropsWithoutRef, ReactNode } from 'react'; import type { PeamButtonVariant } from 'peam/client'; export interface AskAITriggerProps extends ComponentPropsWithoutRef<'button'> { asChild?: boolean; children?: ReactNode; inlineButton?: boolean; variant?: PeamButtonVariant; } ``` ## Notes * If `children` is not provided, a default floating button is rendered. * When `asChild` is `true`, the trigger renders a Radix `Slot`. * Must be rendered inside [AskAI](/docs/api-reference/client/ask-ai) or [AskAIProvider](/docs/api-reference/client/ask-ai-provider). # AskAI # Overview Composable AI chat primitives with a simple preset and full control through composition. Combine [AskAI.Trigger](/docs/api-reference/client/ask-ai-trigger) with surfaces like [AskAI.Dialog](/docs/api-reference/client/ask-ai-dialog), [AskAI.Chat](/docs/api-reference/client/ask-ai-chat), or [AskAI.Sidepane](/docs/api-reference/client/ask-ai-sidepane), or render an [AskAI.Inline](/docs/api-reference/client/ask-ai-inline) layout. ## Type Definition ```ts import type { ReactNode } from 'react'; import type { HttpChatTransport, UIMessage } from 'ai'; export interface AskAIProps { children?: ReactNode; className?: string; endpoint?: string; open?: boolean; defaultOpen?: boolean; chatTransport?: HttpChatTransport; persistence?: boolean | { key?: string }; reuseContext?: boolean; } ``` ## Usage ### Preset (Trigger + Dialog) ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ; } ``` ### Sidepane Composition ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ### Custom Trigger (asChild) ```tsx import { AskAI } from 'peam/client'; import { Button } from '@/components/ui/button'; export default function Page() { return ( ); } ``` ### Inline Chat ```tsx import { AskAI } from 'peam/client'; export default function Page() { return ( ); } ``` ## Props ### AskAI (Preset) | Prop | Type | Default | Description | | --------------- | ------------------------------ | ------------- | ------------------------------------------- | | `endpoint` | `string` | `'/api/peam'` | API endpoint used by the chat transport | | `open` | `boolean` | `undefined` | Controlled open state | | `defaultOpen` | `boolean` | `false` | Uncontrolled initial open state | | `chatTransport` | `HttpChatTransport` | `undefined` | Override the default chat transport | | `persistence` | `boolean \| { key?: string }` | `true` | Configure chat persistence or disable it | | `reuseContext` | `boolean` | `true` | Reuse an existing `AskAIContext` if present | | `className` | `string` | `undefined` | Root wrapper class name | ## Notes * `AskAI` renders a preset: `AskAI.Trigger` + `AskAI.Dialog`. * For other layouts, compose `AskAI` with the surface you want, or provide context manually with [AskAIProvider](/docs/api-reference/client/ask-ai-provider). * Use [useAskAI](/docs/api-reference/client/use-ask-ai) for direct access to state and actions, and [BoundedChatTransport](/docs/api-reference/client/bounded-chat-transport) to override transport behavior. # BoundedChatTransport # Overview A custom chat transport that sends only recent messages since the last summary, keeping the context window bounded. It pairs with [AskAI](/docs/api-reference/client/ask-ai) via the `chatTransport` prop. ## Type Definition ```ts import type { UIMessage } from 'ai'; import { DefaultChatTransport } from 'ai'; export interface BoundedChatTransportOptions { endpoint: string; } export declare class BoundedChatTransport extends DefaultChatTransport { constructor(options: BoundedChatTransportOptions); } ``` ## Usage ```tsx import { AskAI, BoundedChatTransport } from 'peam/client'; export default function Page() { return ( ); } ``` ## Notes * This is the default transport used by [AskAI](/docs/api-reference/client/ask-ai) when `chatTransport` is not provided. * It reads the summary markers in the request body to limit the message window. # useAskAI # Overview Accesses the AskAI context for state, messages, and actions. Use it inside [AskAI](/docs/api-reference/client/ask-ai) or [AskAIProvider](/docs/api-reference/client/ask-ai-provider). ## Type Definition ```ts import type { ChatStatus, UIMessage } from 'ai'; export type AskAIActionOptions = { open?: boolean; }; export interface AskAIContextValue { open: boolean; setOpen: (open: boolean) => void; toggleOpen: () => void; input: string; setInput: (value: string, options?: AskAIActionOptions) => void; messages: UIMessage[]; status: ChatStatus; error: Error | undefined; isLoading: boolean; sendMessage: (message: { text: string }, options?: AskAIActionOptions) => void; handleSubmit: (message: { text?: string }) => void; regenerate: (options?: { messageId?: string }) => void; clearMessages: () => void | Promise; } export declare function useAskAI(): AskAIContextValue; ``` ## Usage ```tsx import { useAskAI } from 'peam/client'; export function AskButton() { const { sendMessage, setOpen } = useAskAI(); return ( ); } ``` ## Notes * `setInput` and `sendMessage` accept `options.open` (default `true`) to control whether the UI opens. * The hook must be used inside [AskAI](/docs/api-reference/client/ask-ai) or [AskAIProvider](/docs/api-reference/client/ask-ai-provider). # createChat # Overview Creates a chat runtime that automatically injects the `searchIndexStore` resolved by [withPeam](/docs/api-reference/next/with-peam). It pairs with the [route handler](/docs/api-reference/next/route) export. ## Type Definition ```ts import type { ChatRuntimeOptions, DefaultChatRuntime } from 'peam/server'; export declare function createChat(options?: ChatRuntimeOptions): DefaultChatRuntime; ``` ## Usage ```ts import { createChat } from '@peam-ai/next/route'; import { openai } from '@ai-sdk/openai'; export const POST = createChat({ model: openai('gpt-4o-mini'), }).handler; ``` ## Notes * [withPeam](/docs/api-reference/next/with-peam) must run during build so `searchIndexStore` can be resolved. * You can override `searchIndexStore` by passing it in `options`. # POST # Overview Exports a ready-to-use `POST` handler for Next.js route handlers. The handler uses the Next.js [createChat](/docs/api-reference/next/create-chat) wrapper and the configuration produced by [withPeam](/docs/api-reference/next/with-peam). ## Source ```ts import { createChat } from './createChat'; export const POST = createChat().handler; ``` ## Usage ```ts export const maxDuration = 30; export { POST } from '@peam-ai/next/route'; ``` ## Notes * [withPeam](/docs/api-reference/next/with-peam) must run during build so `getConfig()` can resolve the search store settings. * The handler reads the search index via the configured `SearchIndexStore` injected by the Next.js [createChat](/docs/api-reference/next/create-chat) wrapper. # withPeam # Overview Wraps your Next.js config to enable Peam content extraction during build. It sets configuration for the adapter, search store, and output file tracing, which are consumed by [createChat](/docs/api-reference/next/create-chat) and the [route handler](/docs/api-reference/next/route). ## Type Definition ```ts import type { NextConfig } from 'next'; import type { SearchStoreConfig } from 'peam/search'; export interface PeamConfig { /** * Search store configuration * @default { type: 'fileBased', config: { indexPath: '.peam/index.json' } } */ searchStore?: SearchStoreConfig; /** * Auto-discover robots.txt when true, use a custom path when string, or false to disable * @default undefined */ robotsTxt?: string | boolean; /** * Array of wildcard patterns to exclude from indexing * @default [] */ exclude?: string[]; } export declare function withPeam(peamConfig?: PeamConfig): (nextConfig?: NextConfig) => NextConfig; ``` ## Usage Examples ### Basic Usage ```ts // next.config.ts import withPeam from '@peam-ai/next'; const nextConfig = { // your Next.js config }; export default withPeam()(nextConfig); ``` ### With Custom Index Path ```ts // next.config.ts import withPeam from '@peam-ai/next'; const nextConfig = { // your Next.js config }; export default withPeam({ searchStore: { type: 'fileBased', config: { indexPath: 'public/.peam/index.json', }, }, })(nextConfig); ``` ### CommonJS (JavaScript) ```js // next.config.js const withPeam = require('@peam-ai/next'); module.exports = withPeam()({ // your Next.js config }); ``` ### With Existing Next.js Plugins ```ts // next.config.ts import withPeam from '@peam-ai/next'; import withBundleAnalyzer from '@next/bundle-analyzer'; const nextConfig = { // your Next.js config }; // Compose multiple config wrappers export default withPeam()( withBundleAnalyzer({ enabled: process.env.ANALYZE === 'true', })(nextConfig) ); ``` ## Configuration Options ### searchStore Controls how the search index is stored during the build process. Currently, the only supported store type is `fileBased`. ```ts const peamConfig: PeamConfig = { searchStore: { type: 'fileBased', config: { indexPath: '.peam/index.json', }, }, }; ``` ### robotsTxt Controls robots.txt filtering. When `true`, Peam auto-discovers `robots.txt` in your project. When a string, it uses that path. If `false`, robots filtering is disabled. ```ts const peamConfig: PeamConfig = { robotsTxt: 'custom/robots.txt', }; ``` ### exclude Wildcard patterns to exclude from indexing. ```ts const peamConfig: PeamConfig = { exclude: ['/admin/**', '/api/*', '/private-*'], }; ``` ## How It Works The `withPeam` function enhances your Next.js configuration by: 1. **Adding a Build Adapter**: For Next.js 15+, configures the adapter to extract content during build 2. **Configuring File Tracing**: Adds output file tracing for the search index 3. **Creating Stub Index**: Creates an empty index file in production if missing ## Requirements * **Next.js 15+**: The adapter feature requires Next.js 15 or higher * For Next.js 14, use the postbuild CLI approach (see [Next.js guide](/docs/getting-started/next)) ## Deployment When deploying to Vercel or other platforms, the `withPeam` configuration ensures that: * The search index is properly traced and included in the deployment * The index is accessible to your API routes at runtime * File paths are correctly resolved in serverless environments ## See Also * [Next.js guide](/docs/getting-started/next) * [createChat](/docs/api-reference/next/create-chat) * [route](/docs/api-reference/next/route) * [Next.js Configuration](https://nextjs.org/docs/app/api-reference/next-config-js) # createChat # Overview Creates a [DefaultChatRuntime](/docs/api-reference/server/default-chat-runtime) instance with a `.handler` function for HTTP requests. ## Type Definition ```ts import type { LanguageModel } from 'ai'; import type { SearchEngine, SearchIndexStore } from '@peam-ai/search'; import type { ConversationSummarizer, DefaultChatRuntime, SummarizationOptions } from 'peam/server'; export interface ChatRuntimeOptions { /** * The language model to use for generating responses and summarization. * Defaults to OpenAI GPT-4o if not provided. */ model?: LanguageModel; /** * Maximum allowed length for a single message. * @default 30000 */ maxMessageLength?: number; /** * Search index store to use for loading the search index. */ searchIndexStore?: SearchIndexStore; /** * SearchEngine to use for retrieving relevant documents. */ searchEngine?: SearchEngine; /** * Options for message summarization. */ summarization?: SummarizationOptions | false; /** * Custom summarizer implementation. */ summarizer?: ConversationSummarizer; } export declare function createChat(options?: ChatRuntimeOptions): DefaultChatRuntime; ``` ## Request Body The handler expects the following JSON payload: ```ts import type { UIMessage } from 'ai'; export interface Summary { text: string; lastSummarizedMessageId: string; } export interface ChatRequestBody { messages: UIMessage[]; summary?: Summary; } ``` ## Usage ### Basic Usage ```ts import { createChat } from 'peam/server'; export const POST = createChat().handler; ``` ### With Custom Model ```ts import { createChat } from 'peam/server'; import { openai } from '@ai-sdk/openai'; export const POST = createChat({ model: openai('gpt-4o'), }).handler; ``` ### With Custom Search Store ```ts import { createChat } from 'peam/server'; import { FileBasedSearchIndexStore } from '@peam-ai/search'; export const POST = createChat({ searchIndexStore: new FileBasedSearchIndexStore({ indexPath: '.peam/index.json', }), }).handler; ``` ### Disable Summarization ```ts import { createChat } from 'peam/server'; export const POST = createChat({ summarization: false, }).handler; ``` ## Notes * If `searchIndexStore` is not provided, [DefaultChatRuntime](/docs/api-reference/server/default-chat-runtime) uses a `FileBasedSearchIndexStore` pointing to `.peam/index.json`. * If `searchEngine` is provided, it is used directly instead of loading from a store (see [getSearchEngine](/docs/api-reference/server/get-search-engine)). * If `summarization` is not set to `false`, [WindowedConversationSummarizer](/docs/api-reference/server/windowed-conversation-summarizer) is used with `maxMessages` defaulting to 10. # DefaultChatRuntime # Overview The default implementation of `ChatRuntime`. It powers the server-side chat behavior, including streaming responses and request handling. For most cases, use [createChat](/docs/api-reference/server/create-chat) to configure it. ## Type Definition ```ts import type { ChatExecutionContext, ChatRuntime, ChatRuntimeOptions, ChatStreamInput } from 'peam/server'; import type { InferUIMessageChunk, UIMessage } from 'ai'; export declare class DefaultChatRuntime implements ChatRuntime { constructor(options?: ChatRuntimeOptions); stream(input: ChatStreamInput, context: ChatExecutionContext): ReadableStream>; handler(request: Request): Promise; } ``` ## Usage ```ts import { DefaultChatRuntime } from 'peam/server'; const runtime = new DefaultChatRuntime(); export const POST = runtime.handler; ``` ## Notes * If `searchIndexStore` is not provided, it uses a file-based store at `.peam/index.json`. * The handler expects the `ChatRequestBody` payload (see [createChat](/docs/api-reference/server/create-chat)). * Summarization defaults to [WindowedConversationSummarizer](/docs/api-reference/server/windowed-conversation-summarizer). # getSearchEngine # Overview Loads and caches a `SearchEngine` instance from a `SearchIndexStore`. This is used by [DefaultChatRuntime](/docs/api-reference/server/default-chat-runtime) when no `searchEngine` is provided. ## Type Definition ```ts import type { SearchEngine, SearchIndexStore } from '@peam-ai/search'; export declare function getSearchEngine(store: SearchIndexStore): Promise; ``` ## Notes * Returns `undefined` if the index is missing or empty. * Caches the `SearchEngine` instance in memory. # POST # Overview A ready-to-use HTTP handler exported from `peam/server`. It is equivalent to [createChat](/docs/api-reference/server/create-chat) with default options: ```ts import { createChat } from 'peam/server'; export const POST = createChat().handler; ``` ## Usage ```ts export { POST } from 'peam/server'; ``` ## Notes * Uses the default chat runtime configuration. * Expects a POST request with the `ChatRequestBody` shape (`messages` and optional `summary`). # WindowedConversationSummarizer # Overview Summarizes conversations after a fixed number of messages to keep the context window bounded. ## Type Definition ```ts import type { SummarizationOptions, SummarizerInput, SummaryUpdate } from 'peam/server'; export declare class WindowedConversationSummarizer { constructor(options: SummarizationOptions); summarize(input: SummarizerInput): Promise; } ``` ## Usage Create a summarizer and pass it to the chat runtime with [createChat](/docs/api-reference/server/create-chat): ```ts import { createChat, WindowedConversationSummarizer } from 'peam/server'; import { openai } from '@ai-sdk/openai'; const summarizer = new WindowedConversationSummarizer({ model: openai('gpt-4o'), maxMessages: 12, }); export const POST = createChat({ summarizer, }).handler; ``` You can also pass summarization options directly and let [createChat](/docs/api-reference/server/create-chat) construct it: ```ts import { createChat } from 'peam/server'; import { openai } from '@ai-sdk/openai'; export const POST = createChat({ summarization: { model: openai('gpt-4o'), maxMessages: 12, }, }).handler; ``` ## Notes * Uses `maxMessages` with a default of 10. * Used automatically by [DefaultChatRuntime](/docs/api-reference/server/default-chat-runtime) unless `summarization` is set to `false`.