Introduction
Upstash Search makes it easy to add a fast, ready-to-use search bar to
your docs site, no complex setup needed. In this tutorial, you’ll learn
how to quickly integrate a modern search experience that helps your users
find what they need. With just a few tweaks, you can use this solution in
any project and deliver great search lightning fast.
1. Project Setup
First, create an Upstash Search Database
if you don’t already have one (Getting Started guide)
and then create a new Next.js application and install the related packages:
npx create-next-app@latest search-docs-app
cd search-docs-app
npm install @upstash/search @upstash/search-ui lucide-react
2. Add Environment Variables
Find the environment variables from your database dashboard and add them to your .env
file:
NEXT_PUBLIC_UPSTASH_SEARCH_URL=<YOUR_SEARCH_REST_URL>
NEXT_PUBLIC_UPSTASH_READONLY_TOKEN=<YOUR_SEARCH_READONLY_TOKEN>
3. Create the Component
Create the search component in app/components/search-bar.tsx
:
app/components/search-bar.tsx
"use client"
import { SearchBar } from "@upstash/search-ui"
import "@upstash/search-ui/dist/index.css"
import { Search } from "@upstash/search"
import { FileText } from "lucide-react"
const client = new Search({
url: process.env.NEXT_PUBLIC_UPSTASH_SEARCH_URL! ,
token: process.env.NEXT_PUBLIC_UPSTASH_SEARCH_READONLY_TOKEN!,
})
// 👇 your search index name
const index = client.index<{ title: string }>("default")
export default function SearchComponent() {
return (
<div className="max-w-sm mt-24 mx-auto">
<SearchBar.Dialog>
<SearchBar.DialogTrigger placeholder="Search..." />
<SearchBar.DialogContent>
<SearchBar.Input placeholder="Type to search..." />
<SearchBar.Results
searchFn={(query) => {
// 👇 100% type-safe: whatever you return here is
// automatically typed as `result` below
return index.search({ query, limit: 10, reranking: true })
}}
>
{(result) => (
<div key={result.id} onClick={() => {
window.open(result.metadata?.url as string, "_blank")
}}>
<SearchBar.Result
value={result.id}
className="cursor-pointer hover:bg-gray-50 transition-colors duration-200"
>
<SearchBar.ResultIcon>
<FileText className="text-gray-600" />
</SearchBar.ResultIcon>
<SearchBar.ResultContent>
<SearchBar.ResultTitle>
{result.content.title}
</SearchBar.ResultTitle>
<p className="text-xs text-gray-500 mt-0.5">Docs</p>
</SearchBar.ResultContent>
</SearchBar.Result>
</div>
)}
</SearchBar.Results>
</SearchBar.DialogContent>
</SearchBar.Dialog>
</div>
)
}
4. Crawl Docs to Feed the Component
Call npx @upstash/search-crawler
in your command line and follow the CLI, you will be prompted to provide:
- Upstash Search URL (as set in your environment variables)
- Upstash Search Rest Token (as set in your environment variables)
- Upstash Search Index Name (Go for
default
for convenience)
- Docs URL to crawl (Let’s go for
https://upstash.com/docs
)
If you prefer not to choose default
index name,
don’t forget to update the line in the SearchComponent
where you provide the index name.
5. Prepare the UI
Replace the following code snippet with the code in app/page.tsx
:
import SearchComponent from "./components/search-bar";
export default function Home() {
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 via-white to-indigo-50">
<main className="flex-1">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 pt-20 pb-16">
<div className="text-center mb-12">
<h2 className="text-4xl md:text-5xl font-bold text-gray-900 mb-6">
Search Upstash Documentation
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto leading-relaxed">
Find exactly what you're looking for in our comprehensive documentation.
Search through guides, APIs, tutorials, and more with lightning-fast results.
</p>
</div>
{/* Search Component */}
<div className="max-w-2xl mx-auto">
<SearchComponent />
</div>
<div className="mt-20 grid md:grid-cols-3 gap-8">
<div className="text-center">
<div className="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg className="w-6 h-6 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
</div>
<h3 className="text-lg font-semibold text-gray-900 mb-2">Lightning Fast</h3>
<p className="text-gray-600">Get instant search results powered by advanced indexing</p>
</div>
<div className="text-center">
<div className="w-12 h-12 bg-green-100 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg className="w-6 h-6 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<h3 className="text-lg font-semibold text-gray-900 mb-2">Accurate Results</h3>
<p className="text-gray-600">Reranking ensures the most relevant content appears first</p>
</div>
<div className="text-center">
<div className="w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center mx-auto mb-4">
<svg className="w-6 h-6 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168
18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5
5c1.746 0 3.332.477 4.5 1.253v13C19.832 18.477 18.246 18 16.5 18c-1.746
0-3.332.477-4.5 1.253" />
</svg>
</div>
<h3 className="text-lg font-semibold text-gray-900 mb-2">Comprehensive</h3>
<p className="text-gray-600">Search across all documentation, guides, and API references</p>
</div>
</div>
</div>
</main>
</div>
);
}
6. Start the Project
Run the following command to start the development server:
Open your browser and navigate to http://localhost:3000
to test the application.
You can search through Upstash docs, and results will redirect you to the page you are looking for.
Next Steps
Learn more about: