🤔 Context
Gatsby currently has two options for adding a search bar to your site:
- Using a Javascript-based search library like Lunr / ElasticLunr
- Using a proprietary Search-as-A-Service like Algolia
😞 The Problem
While a JS-based search library works great for small sites with limited content, for large Gatsby sites, it ends up bloating your bundle size because the entire search index needs to be bundled with your site’s assets. This large bundle needs to be downloaded to your visitors’ browser which unfortunately increases your site’s page load times.
Algolia works great for documentation sites, since Algolia offers a free DocSearch service. However for Gatsby sites with a large amount of traffic or content or both, Algolia can become expensive quickly. It is also a proprietary solution and the Gatsby plugin for Algolia is currently in beta and not officially supported.
✨ The Solution
Enter Typesense, an open source search engine that is simple to use, run and scale, with clean APIs and documentation. Think of it as an open source alternative to Algolia and an easier-to-use, batteries-included alternative to ElasticSearch.
Read more about Typesense’s out-of-the-box features here.
The Gatsby-Typesense plugin helps you to index data from your Gatsby site to a Typesense Search cluster and then quickly build a powerful instant search interface using InstantSearch.js.
The cool thing about this plugin is that it works for both static and dynamic Gatsby sites. It does not depend on you using Markdown, React or any particular plugin. It scans the output of your Gatsby public folder for HTML files and directly indexes content from the markup.
How to add Search to a Gatsby site
The rest of this article will walk you through how you can add an Instant Search bar to your Gatsby site with Typesense.
I’m going to assume that you already have a working Gatsby site. If not, here is a good place to learn how to.
👣 Step 1: Install the Typesense plugin for Gatsby
From your Gatsby site’s root:
npm install gatsby-plugin-typesense @babel/runtime
👣 Step 2: Start a Typesense server
The simplest way to run a Typesense server is using Docker:
mkdir /tmp/typesense-server-data
docker run -i -p 8108:8108 -v/tmp/typesense-server-data/:/data typesense/typesense:0.15.0 --data-dir /data --api-key=xyz --listen-port 8108 --enable-cors
You can also download native binaries from the downloads page.
If you’d prefer a hosted version of Typesense, you can also spin up a cluster on Typesense Cloud.
👣 Step 3: Configure the Plugin
In your gatsby-config.js
file, configure the gatsby-plugin-typesense
plugin:
// gatsby-config.js
module.exports = {
plugins: [
{
resolve: `gatsby-plugin-typesense`,
options: {
publicDir: `${__dirname}/public`, // Required
collectionSchema: { // Required
name: "pages_v1",
fields: [
{
name: "title",
type: "string",
},
{
name: "description",
type: "string",
},
{
name: "tags",
type: "string[]",
optional: true,
facet: true,
},
{
name: "page_path", // Required
type: "string",
},
{
name: "page_priority_score", // Required
type: "int32",
},
],
default_sorting_field: "page_priority_score", // Required
},
server: { // Required
apiKey: "xyz",
nodes: [
{
host: "localhost",
port: "8108",
protocol: "http",
},
],
},
},
},
],
}
To learn more about what the different configuration options mean, read this section of the plugin's documentation.
👣 Step 4: Markup your content
Add a data attribute called data-typesense-field
to any HTML elements that contain the data you want to be indexed for that page.
For example, if you have the following HTML snippet in a file:
<!-- ./public/about/index.html -->
...
<h1 data-typesense-field="title">About Us</h1>
<p data-typesense-field="description">
Hello, we are Stark Industries.
</p>
<div>
<span data-typesense-field="tags">about</span>
<span data-typesense-field="tags">misc</span>
</div>
...
When you build your site, the plugin will index this page as the following structured document in Typesense:
{
"title": "About Us",
"description": "Hello, we are Stark Industries.",
"tags": ["about", "misc"],
"page_path": "/about/",
"page_priority_score": 10
}
You can also add any arbitrary fields to the document, by adding the data-typesense-field
data attribute to any HTML element and adding the corresponding field to the schema under the plugin’s configuration options.
Now, you want to run gatsby build
and the plugin will automatically be triggered post-build and it will index the content you’ve marked up into Typesense 🎉
👣 Step 5: Build your Search UI
The good folks over at Algolia have built and open-sourced Instantsearch.js which is a powerful collection of out-of-the-box UI components that you can use to compose interactive search experiences quickly.
Typesense has an integration with InstantSearch.js (and its React cousin), that lets you use a Typesense cluster with InstantSearch.js UI components:
https://github.com/typesense/typesense-instantsearch-adapter
First, install the react-instantsearch and the adapter:
npm install typesense-instantsearch-adapter react-instantsearch-dom @babel/runtime
Here’s a quick minimal example of a search interface using react-instantsearch:
import { InstantSearch, SearchBox, Hits, Stats } from "react-instantsearch-dom"
import TypesenseInstantSearchAdapter from "typesense-instantsearch-adapter"
const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
server: {
apiKey: "xyz", // Be sure to use the search-only-api-key
nodes: [
{
host: "localhost",
port: "8108",
protocol: "http",
},
],
},
// The following parameters are directly passed to Typesense's search API endpoint.
// So you can pass any parameters supported by the search endpoint below.
// queryBy is required.
additionalSearchParameters: {
queryBy: "title,description,tags",
},
})
const searchClient = typesenseInstantsearchAdapter.searchClient
export default function SearchInterface() {
const Hit = ({ hit }) => (
<p>
{hit.title} - {hit.description}
</p>
)
return (
<InstantSearch searchClient={searchClient} indexName="pages_v1">
<SearchBox />
<Stats />
<Hits hitComponent={Hit} />
</InstantSearch>
)
}
InstantSearch.js supports a variety of additional search widgets. Read more about how to use them in their documentation here.
🔥 And that’s it! 🚀
You now have a working search bar, with Instant Search, typo tolerance and more, powered by Typesense and InstantSearch.js.
Please let me know if you run into any issues in the comments.
Top comments (0)