Skip to main content

MeiLi Search for your Gatsby.js Blog

Shenzhen, China

MeiLi Search is an open-source search engine. And Instant Meilisearch is the search client that you should use to make MeiLi Search work with InstantSearch. InstantSearch, an open-source project developed by Algolia, is the tool that renders all the components needed to start searching in your front-end application.

If you did not setup the MeiLi backend - please do this first.

Installation

Start by scaffolding a Gatsby.js app and install the instant search dependencies:

npm install -g gatsby-cli
gatsby new
cd path-to-my-gatsby-site
npm install gatsby-plugin-meilisearch react-instantsearch-dom instantsearch.css @meilisearch/instant-meilisearch

Configuration

To make the plugin work, open the gatsby-config.js configuration file located at the root of your Gatsby project. All the configuration takes place in that file:

plugins: [
      {
        resolve: require.resolve(`gatsby-plugin-meilisearch`),
        options: {
          host: process.env.GATSBY_MEILI_HTTP_ADDR || 'http://localhost:7700',
          apiKey: process.env.GATSBY_MEILI_MASTER_KEY || 'RhTX1pLPSKSn7KW9yf9u_MNKC0v1YKkmx2Sc6qSwbLQ',
          batchSize: 1,
          indexes: [
            {
              indexUid: process.env.GATSBY_MEILI_INDEX_NAME || 'my_blog',
              settings: {
                searchableAttributes: ['title'],
              },
              transformer: data =>
                data.allMdx.edges.map(({ node }) => ({
                  ...node,
                  title: node.frontmatter.title,
                  cover: node.frontmatter.cover,
                })),
              query: `
                query MyQuery {
                  allMdx {
                    edges {
                      node {
                        id
                        slug
                        frontmatter {
                          title
                          cover
                        }
                        tableOfContents
                      }
                    }
                  }
                }
              `,
            },
        ],
      },
    }
  ],
}

The file above has the MeiLi variables hardcoded - you can also put them into a .env file in your Gatsby root and they will be picked up from there.

The Plugin is using the Gatsby GraphQL API to query all your blog entries and generates a search index my_blog for you on build time!

Build the Frontend

Now we can change the content of src/App.js to start building our MeiLi user interface - Note: I will start by using the Master Key to interact with the MeiLi Search API - this needs to be changed later:

import React from 'react'
import { InstantSearch, Hits, SearchBox } from 'react-instantsearch-dom'
import { Link } from 'gatsby'
import 'instantsearch.css/themes/algolia-min.css'
import { instantMeiliSearch } from '@meilisearch/instant-meilisearch'

const SERVER_ADDRESS =
  process.env.GATSBY_MEILI_HTTP_ADDR || 'http://localhost:7700'
const API_KEY = process.env.GATSBY_MEILI_MASTER_KEY || 'RhTX1pLPSKSn7KW9yf9u_MNKC0v1YKkmx2Sc6qSwbLQ'
const INDEX_NAME = process.env.GATSBY_MEILI_INDEX_NAME || 'my_blog'

const searchClient = instantMeiliSearch(SERVER_ADDRESS, API_KEY, {
  primaryKey: 'id',
})

const App = () => (
  <div className="ais-InstantSearch">
    <h1>MeiLi Search Gatsby.js Frontend</h1>
    <h2>Search for Articles</h2>
    <InstantSearch indexName={INDEX_NAME} searchClient={searchClient}>
      <div style={{ margin: "16px 0px"}}>
        <SearchBox />
      </div>
      <Hits hitComponent={Hit} />
    </InstantSearch>
  </div>
)

const Hit = ({ hit }) => (
  <div
    key={hit.id}
    style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}
  >
    {hit.title && (
      <h3 className="hit-title" style={{ marginTop: 0 }}>
        {hit.title}
      </h3>
    )}
    {hit.cover && (
      <img src={hit.cover} alt={hit.title || ''} style={{ maxWidth: '100%' }} />
    )}
    <Link to={`/${hit.slug || ''}`}><button style={{cursor: "pointer", width: "100%", height: 35, padding: "0 1.5rem", color: "rgb(105, 107, 108)", fontSize: 15, fontWeight: 600, fontFamily: "'Roboto', sans-serif", letterSpacing: ".8px", textAlign: "center", textDecoration: "none", verticalAlign: "middle", whiteSpace: "nowrap", outline: "none", border: "none", userSelect: "none", borderRadius: 2, transition: "all .3s ease-out", boxShadow: "0 2px 5px 0 rgba(0,0,0,0.225)", marginTop: 15}}>Go to Article</button></Link>
  </div>
)

export default App

Reactive Search Starter