Tutorial

How to Add Full-Text Search to a Next.js App in 10 Minutes

April 15, 2026

Most Next.js apps start with basic filtering or client-side string matching. That works until your data grows beyond a few hundred items. At that point you need real full-text search with relevance ranking. Here's how to add it with LumoSearch in about 10 minutes.

What you'll build

A search-as-you-type interface that queries a LumoSearch collection and displays results with highlighted matching text. The search runs client-side using a public API key — no server-side proxy needed.

Step 1: Prepare your data

LumoSearch accepts JSON arrays. Each object becomes a searchable document. Decide which fields should be searchable and what weights they should have.

// articles.json
[
  {
    "id": "1",
    "title": "Getting Started with Next.js",
    "body": "Next.js is a React framework...",
    "tags": ["react", "nextjs", "tutorial"]
  },
  // ... more articles
]

Step 2: Create a collection

Create a project and collection via the API or dashboard. Specify searchable fields with weights:

// Field configuration
{
  "title": { "weight": 3 },
  "body": { "weight": 1 },
  "tags": { "weight": 2 }
}

Titles are weighted 3x because a title match is a strong relevance signal. Tags at 2x because they're curated keywords. Body at 1x as the baseline.

Step 3: Upload your documents

Use the admin API key to upload your JSON array. LumoSearch indexes it asynchronously — for most datasets under 10K documents, indexing completes in seconds.

const response = await fetch(
  `${API_URL}/v1/collections/${collectionId}/documents:replace`,
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${adminKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(articles),
  }
);

Step 4: Install the SDK

npm install @lumosearch/cloud

Step 5: Build the search component

'use client';
import { useState } from 'react';
import { LumoCloud } from '@lumosearch/cloud';

const client = new LumoCloud({
  apiKey: process.env.NEXT_PUBLIC_LUMO_SEARCH_KEY,
  host: process.env.NEXT_PUBLIC_LUMO_API_URL,
});

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

  async function handleSearch(value: string) {
    setQuery(value);
    if (value.length < 2) {
      setResults([]);
      return;
    }
    const res = await client.search('your-collection-id', value, {
      limit: 5,
      attributesToHighlight: ['title', 'body'],
    });
    setResults(res.hits);
  }

  return (
    <div>
      <input
        type="text"
        value={query}
        onChange={(e) => handleSearch(e.target.value)}
        placeholder="Search articles..."
      />
      <ul>
        {results.map((hit) => (
          <li key={hit.id}>
            <strong>{hit.title}</strong>
          </li>
        ))}
      </ul>
    </div>
  );
}

Step 6: Deploy

The public search key is safe to expose in client-side code — it can only perform search and autocomplete on the scoped collection. Deploy your Next.js app as usual.

Next steps

  • Add debouncing to reduce API calls while typing
  • Use the autocomplete endpoint for faster prefix suggestions
  • Display highlight ranges to show matching snippets
  • Re-index on content changes via a webhook or CI step

Get started with LumoSearch

The open-source engine runs locally for development. When you're ready for production, LumoSearch Cloud handles hosting and scaling. View pricing.