Home

Awesome

<p align="center"> <img src="https://raw.githubusercontent.com/meilisearch/integration-guides/main/assets/logos/meilisearch_gatsby.svg" alt="Meilisearch Gatsby" width="200" height="200" /> </p> <h1 align="center">Gatsby plugin Meilisearch</h1> <h4 align="center"> <a href="https://github.com/meilisearch/meilisearch">Meilisearch</a> | <a href="https://www.meilisearch.com/cloud?utm_campaign=oss&utm_source=github&utm_medium=gatsby-plugin-meilisearch">Meilisearch Cloud</a> | <a href="https://www.meilisearch.com/docs">Documentation</a> | <a href="https://discord.meilisearch.com">Discord</a> | <a href="https://www.meilisearch.com">Website</a> | <a href="https://www.meilisearch.com/docs/faq">FAQ</a> </h4> <p align="center"> <a href="https://ms-bors.herokuapp.com/repositories/47"><img src="https://bors.tech/images/badge_small.svg" alt="Bors enabled"></a> <a href="https://github.com/meilisearch/gatsby-plugin-meilisearch/actions"><img src="https://github.com/meilisearch/gatsby-plugin-meilisearch/workflows/Tests/badge.svg" alt="Tests"></a> <a href="https://github.com/meilisearch/gatsby-plugin-meilisearch/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-informational" alt="License"></a> </p> <br/> <p align="center" style="font-weight:bold;" >A plugin to index your Gatsby content to Meilisearch based on graphQL queries</p> <br/>

Table of Contents

📖 Documentation

To understand Meilisearch and how it works, see the Meilisearch's documentation.

To understand Gatsby and how it works, see Gatsby's documentation.

⚡ Supercharge your Meilisearch experience

Say goodbye to server deployment and manual updates with Meilisearch Cloud. Get started with a 14-day free trial! No credit card required.

🔧 Installation

Inside your Gatsby app, add the package:

With npm:

npm install gatsby-plugin-meilisearch

With yarn:

yarn add gatsby-plugin-meilisearch

🏃‍♀️ Run Meilisearch

There are many easy ways to download and run a Meilisearch instance.

For example, if you use Docker:

docker pull getmeili/meilisearch:latest # Fetch the latest version of Meilisearch image from Docker Hub
docker run -it --rm -p 7700:7700 getmeili/meilisearch:latest meilisearch --master-key=masterKey

With this command, your Meilisearch instance host is http://localhost:7700 and your master key is masterKey

🚀 Run Gatsby

If you don't have a running Gatsby, you can either launch the [playground present in this project)(./playground/README.md) or create a Gatsby project.

Run your app if it is not running yet:

gatsby develop

Now that your Gatsby app is running you have access to the following URLs:

🎬 Getting started

Now you should have a running Gatsby app with gatsby-plugin-meilisearch installed and a running Meilisearch instance.

Let's configure our plugin to make it work! In this example, we will fetch every page's URL of our Gatsby website, and index them to Meilisearch.

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.

⚙️ Configure your plugin options

🔑 Add your Meilisearch credentials

First, you need to add your Meilisearch credentials.

The credentials are composed of:

⚠️ Keys with permissions other than search should never be used on your front end. For searching, use the Default Search Key key available on the key route or create a custom API key with only search rights.

Add the credentials the following way in your gatsby-config.js file:

{
  plugins: [
    {
      resolve: 'gatsby-plugin-meilisearch',
      options: {
        host: 'http://localhost:7700',
        apiKey: 'masterKey',
      },
    },
  ]
}

See this section if you don't know what your credentials are.

☝️ Fill in the indexes field

The next step is to define which data we want to add in Meilisearch and how. This happens in the indexes field.

The indexes field is an array that can be composed of multiple index objects. Each index object contains the following information:

indexUid: The name of the index in which the data is added.

Let's define the index uid to pages_url. On build, the pages_url index is created inside Meilisearch.

indexUid: 'pages_url'

if pages_url already existed, it is deleted and recreated on build

query: GraphQL query fetching the data to add in Meilisearch

Let's provide the graphQL query that retrieves the URL's of the pages of our application.

query: `
  query MyQuery {
    allSitePage {
      nodes {
        path
      }
    }
  }
`,

After executing this query, we receive a data object containing the following:

{
  data: {
    allSitePage: {
      nodes: [
        {
          path: '/404/'
        },
        {
          path: '/404.html'
        },
        {
          path: '/'
        }
      ]
    }
  }
}

transformer: Transform the data fetched to a format compatible to Meilisearch.

Now that we have fetched the data with the query field, it is not yet ready to be sent to Meilisearch.

Using a transformer function, we can transform the fetched data to a compatible format.

The first problem of the fetched data is that the documents to send to Meilisearch are nested, while they should be at the root in an array. So the content of nodes should be at the root.

{
  data: {
    allSitePages: {
     nodes: [
       {
        'path': '/404/'
      },
     ]
    }
  }
}

should become:

[
  {
    'path': '/404/'
  },
  {
    'path': '/'
  },
]

The second problem is that each document in Meilisearch requires an unique indentifier called primary key.

Thus every document needs a unique field called id. For example:

{
  'id': 1
  'path': '/404/'
},

To do so, we need to use the transformer method to create the final compatible array of objects:

{
  transformer: data =>
    data.allSitePage.nodes.map((node, index) => ({
      id: index,
      ...node,
    })),
}

In this function, we map on data.allSitePage.nodes in order to return an array of objects that can be indexed by Meilisearch. We add an id field as Meilisearch needs it for the indexation. As we don't have any field here that can be used as an id, we use the index of the current element in the array.

If you want to learn more about these options (indexUid, query and transformer) see indexes options

🎉 Complete configuration

After filling in those fields, your Meilisearch configuration should look like this:

plugins: [
  {
    resolve: 'gatsby-plugin-meilisearch',
    options: {
      host: 'http://localhost:7700',
      apiKey: 'masterKey',
      indexes: [
        {
          indexUid: 'pages_url',
          transformer: (data) =>
            data.allSitePage.nodes.map((node, index) => ({
              id: index,
              ...node,
            })),
          query: `
            query MyQuery {
              allSitePage {
                nodes {
                  path
                }
              }
            }
          `,
        },
      ],
    },
  },
];

🥁 Build your project

The gatsby-plugin-meilisearch fetches and adds your data to Meilisearch on your Gatsby build.

gatsby build

After the build, a message in your terminal confirms that your content was successfully indexed:

success gatsby-plugin-meilisearch - x.xxxs - Documents added to Meilisearch

🪄 Integrate search components

If you need tools to integrate a search experience on your app, we have tools that might help you:

🛼 Usage

In the gatsby-config.js file, the Meilisearch plugin accepts the following options:

host (required)

The host field is the address where your Meilisearch instance is running. gatsby-plugin-meilisearch needs it in order to communicate with your Meilisearch instance, and send your data to it.

apiKey (optional)

The apiKey field contains the API key if the Meilisearch instance is password protected.

skipIndexing (optional)

This option allows you to build your website without indexing to Meilisearch. Default to false

batchSize (optional)

The number of documents that should be included in each batch. Default to 1000

settings (optional)

If you want to pass settings to your Meilisearch instance, you can do it here. Read more about Meilisearch settings

indexes (required)

The indexes field is an array of objects, each of them represents how to add data to a specific index

You can have one or multiple index objects in indexes, which can be useful if you want to index different content in different indexes (or multiple different data to the same index).

Each index object should contain the following fields:

indexUid (required)

This is the name of your Meilisearch index. This is a required field as it is where the retrieved data is added inside Meilisearch. For example if your indexUid is pages_url, your content will be indexed inside the pages_url index in Meilisearch. If you provide an index name that already exists, the index will be deleted and recreated.

Example:

indexUid: 'pages_url'

You can learn more about indexes on our documentation.

query (required)

This is the graphQL query that will be executed in order to retrieve your data. Your query can be very specific depending on the plugins you're using. If you're not sure about your query, you can use the GraphiQL tool (http://localhost:8000/\_\_\_graphql) provided by Gatsby on development mode to help you build it.

Example:

query: `
  query MyQuery {
    allSitePage {
      nodes {
        path
      }
    }
  }
`,

You can also check our playground's configuration file to have an example of a graphQL query using the gatsby-plugin-mdx plugin.

transformer (required)

This is a function that transforms the fetched data before sending it to Meilisearch.

After executing the graphQL query, a data object is received with a structure that can differ from one project to another, depending on the query you provided. As Meilisearch requires a unique identifier at the root of each document and it should avoid nested objects, you will need to transform your data object accordingly. The transformer function is the correct place to do so.

Example:

transformer: data =>
  data.allSitePage.nodes.map((node, index) => ({
    id: index,
    ...node,
  })),

Without using the transformer function, the data will look like this:

{
  data: {
    allSitePage: {
      nodes: [
        {
          path: '/404/'
        },
        {
          path: '/404.html'
        },
        {
          path: '/'
        }
      ]
    }
  }
}

After using the transformer function as in the above example, the data will look like this, and will be ready for indexation:

[
  {
    id: 0,
    path: '/404/',
  },
  {
    id: 1,
    path: '/404.html',
  },
  {
    id: 2,
    path: '/',
  },
];

If you want to learn more about Meilisearch's documents structure, you can do so in our documentation.

Full usage example:

{
  resolve: 'gatsby-plugin-meilisearch',
  options: {
    host: 'http://localhost:7700',
    apiKey: 'masterKey',
    skipIndexing: false,
    batchSize: 1000,
    options: {
      settings: {
        searchableAttributes: ["*"],
      },
    },
    indexes: [
    {
      indexUid: 'my_index',
      transformer: () => {},
      query: ``
    },
  ],
}

🤖 Compatibility with Meilisearch and Gatsby

Supported Gatsby versions:

(This plugin may work with the older Gatsby versions, but these are not tested nor officially supported at this time.)

Supported Meilisearch versions:

This package guarantees compatibility with version v1.x of Meilisearch, but some features may not be present. Please check the issues for more info.

Node / NPM versions:

We recommend always using the latest version of Gatsby to start your new projects.

⚙️ Development Workflow and Contributing

Any new contribution is more than welcome in this project!

If you want to know more about the development workflow or want to contribute, please visit our contributing guidelines for detailed instructions!