SearchJetEngine
Headless Search API for Next.js

Search API Calls from App Router & Server Components

Server-side search without hydration issues. Route-handler proxies, SSG caching, and edge-compatible fetch — the headless option for teams who own their UI.

The Headless API — Live

This is what your Next.js route handler will return. Type a query below.

app.js
const searchjet = new SearchJet({
  apiKey: 'sj_live_demo_index_key',
  indexName: 'docs'              // your index name
});

// Search as you type → instant results
const res = await searchjet.search('laptop deals');
console.log(res.results);        // ← live JSON below
@searchjet/connect · <10KBStep 1 · init client
Try:
Step 2 · response.json()
{
  // Run a query above to see the live
  // JSON response from the SearchJet API.
  // Edge-cached, typo-tolerant, sub-50ms.
}
Type a query → watch the JSON update
This sandbox queries the live SearchJet API — real index, real JSON, no setup.
Run it on your own index
Why Go Headless?

Full Control, Zero Search Infrastructure

Keep the API key secret

Search keys live in a route handler (server-only), never in the client bundle. Your index and quota stay protected.

Server components stay fast

Fetch search results inside a React Server Component or ISR-revalidate them at build time. No client-side waterfall, no hydration mismatch.

Cache at the edge

Tell Next.js to cache responses with revalidate / cache tags. Edge-cached SearchJet responses answer in single-digit milliseconds.

Copy-Paste Integration

Three Files. That's the Whole Setup.

1 · Route handler (key stays server-side)

app/api/search/route.ts
// app/api/search/route.ts — server-only, key stays private
import { NextResponse } from 'next/server';

const SEARCHJET_API = 'https://app.searchjetengine.com/api/v1/search';

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const q = searchParams.get('q');
  if (!q) return NextResponse.json({ error: 'Missing q' }, { status: 400 });

  const res = await fetch(`${SEARCHJET_API}?q=${encodeURIComponent(q)}&limit=8`, {
    headers: {
      Authorization: `Bearer ${process.env.SEARCHJET_API_KEY}`,
    },
    // Edge-cache repeat queries — 60s revalidation
    next: { revalidate: 60 },
  });

  const data = await res.json();
  return NextResponse.json(data.results);
}

2 · Client SearchBox

components/SearchBox.tsx
'use client';

import { useState, useEffect } from 'react';

export default function SearchBox() {
  const [query, setQuery] = useState('');
  const [hits, setHits] = useState([]);

  useEffect(() => {
    if (!query.trim()) { setHits([]); return; }
    let cancelled = false;
    const timer = setTimeout(async () => {
      const res = await fetch(`/api/search?q=${query}`);
      const data = await res.json();
      if (!cancelled) setHits(data);
    }, 200); // debounce
    return () => { cancelled = true; clearTimeout(timer); };
  }, [query]);

  return (
    <>
      <input
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search…"
      />
      <ul>
        {hits.map((hit) => (
          <li key={hit.id}>
            <a href={hit.url}>{hit.title}</a>
          </li>
        ))}
      </ul>
    </>
  );
}

3 · React Server Component (optional SSR)

app/page.tsx
// app/page.tsx — React Server Component
import { search } from '@searchjet/connect';

export default async function Home() {
  // Runs on the server — key never reaches the browser
  const { results } = await search({
    indexName: 'docs',
    query: 'getting started',
    limit: 10,
  });

  return (
    <main>
      <h1>Docs search</h1>
      <ul>
        {results.map((hit) => (
          <li key={hit.id}>
            <a href={hit.url}>{hit.title}</a>
          </li>
        ))}
      </ul>
    </main>
  );
}

Frequently Asked Questions

What does "headless" search mean for Next.js?
Headless means SearchJet provides plain search API endpoints and fetch clients — no UI imposed. You call the API from route handlers or server components and render results with your own components, exactly how you want them.
How do I avoid exposing my API key in the browser?
Put the key in an environment variable and call SearchJet from an App Router route handler (/app/api/search/route.ts). The client only ever sees your own endpoint. The example below shows the complete pattern.
Does headless search work with React Server Components?
Yes. Fetch search results inside a server component using the same fetch client. Combine with Next.js stale-while-revalidate caching so repeated queries hit the cache instead of the origin.
Can I cache search results with ISR / SSG?
Yes — the search route example includes a revalidate option. A 5-minute revalidation window gives you near-instant repeat searches while keeping results fresh.
Is there a simpler, UI-bundled option?
If you prefer drop-in components, use the standard SDK (Autocomplete, SearchBox, Hits). The headless approach is for teams that want total control over rendering and caching.

Headless Search, Delivered

10,000 free searches/month. Built for the App Router.

More Search Recipes