How to add AI-powered search to a Next.js app

Add semantic document search to a Next.js app using Ragex — set up a server-side route handler, upload documents, and return search results to your React frontend. Works with App Router and Pages Router.

TL;DR: Install the ragex package, create a Ragex client in a server-side route handler, and proxy search requests from your React frontend. Ragex handles document parsing, embedding, and reranking — you write the search UI and API route. Setup takes under 5 minutes.

Why use a server-side route handler?

Ragex requires an API key for authentication. Exposing this key in client-side code would let anyone search or modify your knowledge base. Instead, create a Next.js API route that holds the key server-side and proxies search requests from your frontend.

This pattern works with both the App Router (app/api/search/route.ts) and Pages Router (pages/api/search.ts).

Step 1: Install the SDK and set up the client

npm install ragex

Create a shared client instance:

// lib/rag.ts
import { RagexClient } from 'ragex';

export const ragexClient = new RagexClient({
  apiKey: process.env.RAGEX_API_KEY!,
});

export const KB_ID = process.env.RAG_KB_ID!;

Add RAGEX_API_KEY and RAG_KB_ID to your .env.local file.

Step 2: Create a search API route

// app/api/search/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { ragexClient, KB_ID } from '@/lib/rag';

export async function POST(req: NextRequest) {
  const { query } = await req.json();

  if (!query || typeof query !== 'string') {
    return NextResponse.json({ error: 'Query required' }, { status: 400 });
  }

  const results = await ragexClient.search(KB_ID, {
    query,
    top_k: 5,
  });

  return NextResponse.json({ results: results.results });
}

This route accepts a search query, calls Ragex, and returns ranked results to the frontend. Reranking is enabled by default.

Step 3: Build the search UI

// components/SearchBox.tsx
'use client';
import { useState } from 'react';

export function SearchBox() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);

  async function handleSearch(e: React.FormEvent) {
    e.preventDefault();
    const res = await fetch('/api/search', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ query }),
    });
    const data = await res.json();
    setResults(data.results);
  }

  return (
    <div>
      <form onSubmit={handleSearch}>
        <input value={query} onChange={e => setQuery(e.target.value)} />
        <button type="submit">Search</button>
      </form>
      {results.map((r: any) => (
        <div key={r.chunk_id}>
          <p>{r.text}</p>
          <small>Source: {r.document_name} | Score: {r.score.toFixed(2)}</small>
        </div>
      ))}
    </div>
  );
}

This is a minimal implementation. In production, add loading states, debounced input, and error handling.

How do you populate the knowledge base?

Upload documents via the SDK or REST API. You can do this from a script, an admin page, or a CI/CD pipeline:

import { ragexClient, KB_ID } from './lib/rag';

// Upload docs from a script
const file = new File([buffer], 'docs.pdf', { type: 'application/pdf' });
await ragexClient.uploadDocument(KB_ID, file);

The API supports 16 file types — PDF, DOCX, PPTX, XLSX, images, markdown, HTML, and more. Documents process asynchronously and become searchable once processing completes.

FAQ

Does this work with Next.js middleware?

The Ragex client should not run in Edge middleware because the SDK requires Node.js APIs. Use standard Node.js API routes (runtime: 'nodejs') for search endpoints. Edge middleware can handle authentication or rate limiting before the request reaches your search route.

Can I use server components instead of an API route?

Yes. In a Server Component, you can call ragexClient.search() directly and render results server-side. This avoids an extra API hop but means search queries are triggered on page load rather than user interaction. For interactive search (typing and getting results), an API route with a client-side form is the better pattern.

How do I add search to an existing Next.js project?

Install the SDK, add environment variables, create the API route, and add the search component to any page. You do not need to restructure your existing app. The integration is additive — it does not affect your existing routes, data fetching, or rendering patterns.


Last updated: 2026-03-09