Server-side search without hydration issues. Route-handler proxies, SSG caching, and edge-compatible fetch — the headless option for teams who own their UI.
This is what your Next.js route handler will return. Type a query below.
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{
// Run a query above to see the live
// JSON response from the SearchJet API.
// Edge-cached, typo-tolerant, sub-50ms.
}Search keys live in a route handler (server-only), never in the client bundle. Your index and quota stay protected.
Fetch search results inside a React Server Component or ISR-revalidate them at build time. No client-side waterfall, no hydration mismatch.
Tell Next.js to cache responses with revalidate / cache tags. Edge-cached SearchJet responses answer in single-digit milliseconds.
// 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);
}'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>
</>
);
}// 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>
);
}10,000 free searches/month. Built for the App Router.