Quickstarts
Next.js Search Quickstart
Getting Started With Upstash Search and Next.js
1. Create a Search Database
Follow the instructions in the Getting Started guide to create a Search Database.
2. Project Setup
Let's create a new Next.js application and install the @upstash/search package:
npx create-next-app@latest search-appcd search-appnpm install @upstash/search3. Add Environment Variables
Find the environment variables from your database dashboard and add them to your .env file:
UPSTASH_SEARCH_REST_URL=<YOUR_SEARCH_REST_URL>UPSTASH_SEARCH_REST_TOKEN=<YOUR_SEARCH_REST_TOKEN>4. Create an API Route to Upsert Documents
Create an API route in app/api/upsert/route.ts:
app/api/upsert/route.ts
import { Search } from "@upstash/search"const client = new Search({ url: process.env.UPSTASH_SEARCH_REST_URL, token: process.env.UPSTASH_SEARCH_REST_TOKEN,})const index = client.index("my-index")export async function POST() { await index.upsert([ { id: "movie-1", content: { title: "Inception", description: "A thriller about dreams within dreams.", }, metadata: { genre: "sci-fi", year: 2010 }, }, { id: "movie-2", content: { title: "The Godfather", description: "A story about a powerful Italian-American crime family.", }, metadata: { genre: "crime", year: 1972 }, }, { id: "movie-3", content: { title: "The Dark Knight", description: "A tale of Batman's fight against the Joker.", }, metadata: { genre: "action", year: 2008 }, }, ]) return new Response("OK")}5. Create a Route to Search Documents
Create an API route in app/api/search/route.ts:
app/api/search/route.ts
import { Search } from "@upstash/search"const client = new Search({ url: process.env.UPSTASH_SEARCH_REST_URL, token: process.env.UPSTASH_SEARCH_REST_TOKEN,})const index = client.index("my-index")export async function POST(req: Request) { const { query } = (await req.json()) as { query: string } const results = await index.search({ query }) return new Response(JSON.stringify(results))}6. Create a Simple Page
Add the following code in app/page.tsx:
app/page.tsx
"use client";import { useState } from "react";interface SearchResult { id: string; content: Record<string, unknown>; metadata: Record<string, unknown>; score: number;}export default function Home() { const [searchResults, setSearchResults] = useState<SearchResult[]>([]); const [query, setQuery] = useState(""); const [isUpserting, setIsUpserting] = useState(false); const [upsertSuccess, setUpsertSuccess] = useState(false); const upsertData = async () => { setIsUpserting(true); setUpsertSuccess(false); await fetch("/api/upsert", { method: "POST" }); setIsUpserting(false); setUpsertSuccess(true); }; const search = async () => { const res = await fetch(`/api/search`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query }), }); const data = await res.json(); setSearchResults(data || []); }; return ( <main className="min-h-screen bg-emerald-50 flex flex-col items-center py-10"> <div className="w-full max-w-2xl bg-white shadow-md rounded-lg p-6"> <header className="mb-6 text-center"> <h1 className="text-2xl font-bold text-emerald-800">Search App</h1> <p className="text-emerald-600"> Upsert data and search through the database. </p> </header> <div className="mb-6"> <button onClick={upsertData} disabled={isUpserting} className={`w-full py-2 px-4 rounded-md text-white ${ isUpserting ? "bg-emerald-300" : "bg-emerald-500 hover:bg-emerald-600" }`} > {isUpserting ? "Upserting..." : "Upsert Data"} </button> {upsertSuccess && ( <p className="mt-2 text-sm text-emerald-600"> Data upserted successfully! </p> )} </div> <div className="mb-6"> <div className="flex gap-2"> <input type="text" value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search..." className="flex-1 border border-emerald-300 rounded-md px-4 py-2 text-gray-800 focus:outline-none focus:ring-2 focus:ring-emerald-500" /> <button onClick={search} className="bg-emerald-500 text-white px-4 py-2 rounded-md hover:bg-emerald-600" > Search </button> </div> </div> <ul className="space-y-2"> {searchResults.map((result, index) => ( <li key={index} className="bg-emerald-100 p-4 rounded-md shadow-sm text-emerald-800" > <p className="font-bold">ID: {result.id}</p> <p className="text-sm">Content: {JSON.stringify(result.content)}</p> <p className="text-sm">Metadata: {JSON.stringify(result.metadata)}</p> <p className="text-sm">Score: {result.score}</p> </li> ))} </ul> </div> </main> );}7. Start the Project
Run the following command to start the development server:
npm run devOpen your browser and navigate to http://localhost:3000 to test the application.
You can click the Upsert Data button to add three movies to your database and use the search bar to make a query.
Next Steps
Learn more about: