Skip to content

Next.js

Add cited search to a Next.js app. Register the search element from a client component; for content behind a login, keep the key on the server in a route handler and point the widget at it.

On this page

1Install

TerminalShell
# Needs @docslurp/sdk 0.2.0 or newer (0.1.x lacks these exports).
npm install @docslurp/sdk@^0.3.0

# Then register the element once in the browser:
# import { defineDocSlurpSearch } from '@docslurp/sdk/widget';

2Public or private?

Public content

Docs, manuals, a help center. The browser calls DocSlurp directly with a browser key, which is search-only and works only on your allowed websites. No server code needed.

Private content

Anything behind a login. A route handler authenticates the viewer, picks the workspace they may read, and searches with a server key.

3aSearch public content

components/document-search.tsx
'use client';
import { useEffect, useRef } from 'react';
import { defineDocSlurpSearch } from '@docslurp/sdk/widget';

export function DocumentSearch() {
  const host = useRef<HTMLDivElement>(null);
  useEffect(() => {
    defineDocSlurpSearch(); // SSR-safe: a no-op on the server
    const element = document.createElement('docslurp-search-box');
    element.setAttribute('client-key', process.env.NEXT_PUBLIC_DOCSLURP_CLIENT_KEY!);
    // Optional: a workspace slug or UUID. Omitted = the default workspace.
    if (process.env.NEXT_PUBLIC_DOCSLURP_WORKSPACE) element.setAttribute('workspace-id', process.env.NEXT_PUBLIC_DOCSLURP_WORKSPACE);
    host.current?.append(element);
    return () => element.remove();
  }, []);
  return <div ref={host} />;
}
.env.local
# .env.local — NEXT_PUBLIC_ values ship to every visitor.
NEXT_PUBLIC_DOCSLURP_CLIENT_KEY=dslp_pub_…   # browser key: search-only, allowed websites only
NEXT_PUBLIC_DOCSLURP_WORKSPACE=product-docs   # optional

Render <DocumentSearch /> from any page or layout. A runnable copy lives at packages/sdk/examples/next-search.tsx.

3bSearch private content

app/api/search/route.ts
// app/api/search/route.ts — runs on the server; the key never reaches the browser.
import { createDocSlurpClient } from '@docslurp/sdk';
import { getViewer } from '@/lib/auth'; // your existing session check

const docslurp = createDocSlurpClient(); // DOCSLURP_API_KEY: server key, search scope

export async function POST(request: Request) {
  const viewer = await getViewer(request);
  if (!viewer) return Response.json({ error: 'Sign in to search' }, { status: 401 });

  const { q } = await request.json();
  if (typeof q !== 'string' || !q.trim() || q.length > 500) return Response.json({ results: [] });

  // Fix the workspace on the server from what this viewer may read.
  const { results } = await docslurp.search({ q, workspaceId: viewer.workspace, limit: 6 });
  return Response.json({ results });
}
components/private-document-search.tsx
'use client';
import { useEffect, useRef } from 'react';
import { defineDocSlurpSearch } from '@docslurp/sdk/widget';

export function PrivateDocumentSearch() {
  const host = useRef<HTMLDivElement>(null);
  useEffect(() => {
    defineDocSlurpSearch();
    const element = document.createElement('docslurp-search-box');
    // No key in the browser: the widget POSTs { q } to your route
    // and renders the returned { results } with citations.
    element.setAttribute('search-endpoint', '/api/search');
    host.current?.append(element);
    return () => element.remove();
  }, []);
  return <div ref={host} />;
}
.env.local
# .env.local — server only. Never prefix with NEXT_PUBLIC_.
DOCSLURP_API_KEY=dslp_priv_… # search scope

Notes

Importing the widget is SSR-safe: defineDocSlurpSearch() does nothing on the server, and registration happens in the client effect. This is a documented recipe rather than a dedicated Next.js package, so it works the same with the Pages Router. For custom result markup, use a search adapter or the Node SDK directly.

Hand off to an agent

Working in a real codebase? Copy a prompt that tells a coding agent exactly what to change for Next.js: which entry point to use, the supported contract, and what to validate before shipping. It contains no keys or secrets.

Review agent instructions

Before switching traffic, run through the go-live checklist. Stuck? See troubleshooting.

Jump to