Adding Search with Algolia
Once you’ve added some content to your site, you’ll want to make it easy for your visitors to find what they’re looking for. This guide will run you through the process of setting up a custom search experience powered by Algolia on any Gatsby site. You’ll be writing functional components that rely on React Hooks so following this guide requires you to be using React 16.8 or higher.
Two things before you begin:
- Beyond this guide, you may also want to checkout Algolia’s extensive docs on how to get started in React.
- If you’re looking to add search to a documentation site, you can let Algolia handle most of the steps outlined below by using their Docsearch functionality. For other types of sites and more fine-grained control over exactly what data should be indexed, read on.
Algolia is a site search hosting platform that hosts page index information for you, and then returns the results to wherever you have the site search located on your site. You tell Algolia what pages you have, where they are, and how to navigate to them, and Algolia returns those results to the user based on whatever search terms they use.
To implement Algolia search on your Gatsby site, you’ll need to install the plugin, tell it what information to query, provide your Algolia credentials, and a few other configuration steps. This means that after the queries have run when you
gatsby build, Algolia will have the entire index of your site available and can serve results to users very quickly. To learn more about the benefits of using Algolia, check out this blog post from Netlify, who recently switched their site search to Algolia.
First, you’ll need to add
react-instantsearch-dom to your project.
react-instantsearch is Algolia’s library containing off-the-shelf React components which you can import to save yourself a lot of work. You’ll also be using
dotenv which gets shipped with Gatsby by default. You’re going to need it to specify your Algolia app ID and both the search and admin API keys without committing them to version control.
You will be using
styled-components to design the search UI in this guide but you can use whichever CSS solution you prefer. If you’d like to start using
styled-components as well, you also need to install
gatsby-plugin-styled-components to your
Notice that you’re loading
queries from a file at
./src/utils/algolia.js (you can of course put it wherever you like) and your Algolia ID and API key from
.env so add those files.
For this, you will need to navigate to the ‘API Keys’ section of your Algolia profile. If you already have an account, you will find your API keys here. If not, you will need to sign up for one and then navigate to this link. It should look something like this screenshot, only with actual numbers instead of redacted ones:
Once you have your App ID, Search-Only API Key, and Admin API Key, place the following code into your
.env file, replacing the placeholder keys with your keys:
The placeholder keys in the previous code snippet are random character sequences but the ones you copy from your Algolia profile should be the same length. One of the benefits of using this method of querying your API keys is that they all get stored in one file, on the server, and are therefore never exposed to the client-side, which increases security.
Since your .env file contains your real private API keys, it is considered a security risk to commit your actual
.env file. It’s good practice to commit a
.env.example to git or other version control so that if someone forks your repo, they know which environment variables they need to supply, without committing your private keys.
queries allow you to grab the data you want Algolia to index directly from Gatsby’s GraphQL layer by exporting from
src/utils/algolia.js an array of objects, each containing a required GraphQL query and an optional index name, transformer function and settings object.
It might look a little intimidating at first, but basically you’re just letting
gatsby-plugin-algolia know how to acquire the data with which to populate your indices on their servers. The example above uses separate queries passing data to separate indices for pages and blog posts.
Transformers allow you to modify the data returned by the queries to bring it into a format ready for searching. All you’re doing here is ‘flattening’ posts and pages to ‘unnest’ the frontmatter fields (such as
tags) but transformers could do much more for you if required. This makes the whole process of indexing your data really flexible and powerful. You could for instance use them to filter the results of your queries, format fields, add or merge them, etc.
If you’ve come this far, then the “backend” is done. You should now be able to run
gatsby build and see your indices in Algolia’s webinterface be flooded with your data.
Next, build a user-facing search interface for your site. It needs a way for the user to enter a search string, send that string to Algolia, receive matching results (hits in Algolia speak) from your indices and finally display those to the user.
You’re going to assemble everything you need into a React
Search component that you call from anywhere on your site where you want the user to be able to search. Even though design varies strongly from site to site, you’ll note the styles implemented with
styled-components in this guide since working out the CSS transitions to have the search field slide out as the user clicks on it and the results pane to appear once Algolia returns matches took some time.
Search components is made up of the following files:
index.js: the main component
input.js: the text input field
hitComps.js: the components that will render matching posts/pages
styles.js: the styled components
There’s quite a lot happening in these files so break them down one by one and piece by piece.
At the top, you import
react-instantsearch-dom which is the root component that allows your whole search experience to connect to Algolia’s service. As the name suggests,
Index allows you to tap into an individual index and
Hits provides you with the data returned for a user’s search input. Finally
connectStateResults wraps around custom React components and provides them with high-level stats about the current search state such as the query, the number of results and how long it took to fetch them.
You then import the styled components that make up the UI and the
Input component into which the user enters the query.
PoweredBy renders the string “Powered by Algolia” with a small logo and link. If you’re using Algolia’s generous free tier, they ask you to acknowledge them in this way below the search results.
react-instantsearch-dom also provides a
PoweredBy component specifically for this purpose, but you can build your own. You’ll get back to these styled components once you’re done with
The last thing you need for the
Search component to work are hit components for every type of result you want to display to the user. The hit component determines how attributes of matching results (such as author, date, tags and title in the case of a blog post) are displayed to the user.
Next you define two connected components.
Results informs the user that no matches could be found for a query unless the number of hits is positive, i.e.
searchResults.nbHits > 0.
Stats just displays
Now comes the actual
Search component. It starts off with some state initialization, defining handler functions and event listeners to trigger them. All they do is make the search input slide out when the user clicks a search icon and disappear again when the user clicks or touches (on mobile) anywhere.
Search returns JSX that renders a dynamic array of
indices passed as a prop. Each array item should be an object with keys
hitComp that specifies the name of the index in your Algolia account to be queried, the title to display above the results shown to the user and the component
hitComp that renders the data returned for each match.
indices array as a prop allows you to reuse the same
Search component in different parts of your site and have each of them query different indices. As an example, besides a primary search box in the header used for finding pages and/or posts, your site might have a wiki and you want to offer your visitors a second search box that displays only wiki articles.
Note that you fed
algoliasearch with the same app ID you specified in our
.env file and used in
src/utils/algolia.js as well as with your search-only API key to generate a search client which connects to your backend. Don’t paste in your Algolia admin API key here!
algoliasearch only needs to read your indices. Pasting your admin key here would allow others to obtain it once your site is deployed. They could then start messing with your indexed data on Algolia.
Input component is where the user enters the search string. It is quite short since the grunt work is done by Algolia’s
Now look at the styled components
Input as well as the ones imported in
Styles will of course be different from one site to the next so these components are listed here for completeness and because they implement the dynamic behavior of the search interface, i.e. that the input field only slides out once the user clicks the
SearchIcon (a magnifier) and that the pane displaying search (
HitsWrapper) results only appears once Algolia’s server returned matches, both of you which you might want to keep.
Now you’re almost done, two small steps remain. First you need to put together a hit component for every type of result you want to display. In this example, these are blog posts and pages. And second, you need to call your
Search component somewhere on your site. Here are the hit components.
Snippet imported from
react-instantsearch-dom both display attributes of matching search results to the user. Their distinction is that the former renders it in full (e.g. a title, date or list of tags) whereas the latter only shows a snippet, i.e. a text passage of given length surrounding the matching string (e.g. for body texts). In each case the
attribute prop should be the name of the property as it was assigned in
src/utils/algolia.js and as it appears in your Aloglia indices.
Now all you need to do is import
Search somewhere. The obvious place is the
Header component so add it there.
Note that this is where you define your array of search indices and pass it as a prop to
If everything works as expected, running
gatsby develop should now give you some instant search magic looking something like in the video below! You can also play around with it here.
If you have any issues or if you want to learn more about using Algolia for search, check out this tutorial from Jason Lengstorf:
You can also find stories of companies using Gatsby + Algolia together in the Algolia section of the blog.
Edit this page on GitHub