Home Blog How to Add Search to a Jekyll Site (Lunr.js vs Algolia)
Tutorial

How to Add Search to a Jekyll Site (Lunr.js vs Algolia)

Add full-text search to your Jekyll site using Lunr.js (free, no backend) or Algolia (fast, scalable). Setup guides for both options with pros and cons.

How to Add Search to a Jekyll Site (Lunr.js vs Algolia)

Jekyll doesn’t include search out of the box — but adding it is simpler than you might think. This guide covers the two best options: Lunr.js for a free, no-backend solution and Algolia for a fast, scalable search service.


Option 1: Lunr.js (Free, No Backend Required)

Lunr.js is a client-side search library. Jekyll generates a JSON search index at build time, and Lunr searches it entirely in the browser.

Pros: Free, privacy-friendly, no external service required, works on GitHub Pages
Cons: Index grows with site size, can be slow on very large sites (500+ posts)

Step 1: Generate a Search Index

Create search-index.json at your site root. This file is regenerated on every build:


---
layout: null
---
[
  {% for post in site.posts %}
  {
    "title": {{ post.title | jsonify }},
    "url": {{ post.url | absolute_url | jsonify }},
    "date": {{ post.date | date: "%B %d, %Y" | jsonify }},
    "excerpt": {{ post.excerpt | strip_html | truncatewords: 50 | jsonify }},
    "content": {{ post.content | strip_html | truncatewords: 300 | jsonify }},
    "tags": {{ post.tags | jsonify }},
    "categories": {{ post.categories | jsonify }}
  }{% unless forloop.last %},{% endunless %}
  {% endfor %}
  {% if site.posts.size > 0 and site.pages.size > 0 %},{% endif %}
  {% for page in site.pages %}
  {% if page.title and page.layout != null %}
  {
    "title": {{ page.title | jsonify }},
    "url": {{ page.url | absolute_url | jsonify }},
    "excerpt": {{ page.content | strip_html | truncatewords: 50 | jsonify }},
    "content": {{ page.content | strip_html | truncatewords: 300 | jsonify }}
  }{% unless forloop.last %},{% endunless %}
  {% endif %}
  {% endfor %}
]

Save this as search-index.json in your site root.

Step 2: Create the Search Page

Create search.md:

---
layout: page
title: Search
permalink: /search/
---

<input type="search" id="search-input" placeholder="Search posts and pages..." autofocus>
<div id="search-results"></div>

<script src="https://unpkg.com/lunr/lunr.js"></script>
<script>
let searchIndex;
let documents = {};

fetch('/search-index.json')
  .then(res => res.json())
  .then(data => {
    data.forEach(doc => { documents[doc.url] = doc; });

    searchIndex = lunr(function () {
      this.ref('url');
      this.field('title', { boost: 10 });
      this.field('tags', { boost: 5 });
      this.field('content');

      data.forEach(doc => { this.add(doc); });
    });
  });

document.getElementById('search-input').addEventListener('input', function () {
  const query = this.value.trim();
  const resultsDiv = document.getElementById('search-results');

  if (!query || !searchIndex) {
    resultsDiv.innerHTML = '';
    return;
  }

  const results = searchIndex.search(query + '*');

  if (results.length === 0) {
    resultsDiv.innerHTML = '<p>No results found.</p>';
    return;
  }

  resultsDiv.innerHTML = results.map(result => {
    const doc = documents[result.ref];
    return `<div class="search-result">
      <a href="${doc.url}"><h3>${doc.title}</h3></a>
      <p>${doc.excerpt}</p>
    </div>`;
  }).join('');
});
</script>

Step 3: Add Search to Your Navigation

Add a search link or a header search box that submits to /search/?q=query:

<form action="/search/" method="get">
  <input type="search" name="q" placeholder="Search...">
  <button type="submit">Search</button>
</form>

Then in your search page, pre-fill from the URL parameter:

const params = new URLSearchParams(window.location.search);
const q = params.get('q');
if (q) {
  document.getElementById('search-input').value = q;
  // Trigger search...
}

Option 2: Algolia (Fast, Scalable)

Algolia is a hosted search service. It’s significantly faster than Lunr for large sites and provides instant results as you type.

Free plan: 10,000 search requests/month and 10,000 records
Pros: Fast, typo-tolerant, instant search, great developer experience
Cons: Requires an Algolia account, data is stored externally

Step 1: Create an Algolia Account

  1. Sign up at algolia.com
  2. Create a new application
  3. Create an index (e.g. jekyllhub_production)
  4. Note your Application ID, Search-Only API Key, and Admin API Key

Step 2: Install jekyll-algolia

# Gemfile
gem "jekyll-algolia"
# _config.yml
algolia:
  application_id: YOUR_APP_ID
  index_name: YOUR_INDEX_NAME
  search_only_api_key: YOUR_SEARCH_ONLY_KEY

Important: Your search-only key is safe to put in _config.yml. Never put your Admin API key in version control.

Set the Admin key as an environment variable:

export ALGOLIA_API_KEY='your-admin-key'

Step 3: Index Your Content

bundle exec jekyll algolia

This pushes all your posts and pages to Algolia. Run this whenever you add new content (or add it to your CI/CD pipeline).

Step 4: Add InstantSearch to Your Site

Algolia provides InstantSearch.js for the frontend:

<!-- search.html -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/instantsearch.css@7/themes/satellite-min.css">

<div id="searchbox"></div>
<div id="hits"></div>
<div id="pagination"></div>

<script src="https://cdn.jsdelivr.net/npm/algoliasearch@4/dist/algoliasearch-lite.umd.js"></script>
<script src="https://cdn.jsdelivr.net/npm/instantsearch.js@4"></script>
<script>
const searchClient = algoliasearch('YOUR_APP_ID', 'YOUR_SEARCH_ONLY_KEY');

const search = instantsearch({
  indexName: 'YOUR_INDEX_NAME',
  searchClient,
});

search.addWidgets([
  instantsearch.widgets.searchBox({
    container: '#searchbox',
    placeholder: 'Search posts...',
  }),
  instantsearch.widgets.hits({
    container: '#hits',
    templates: {
      item(hit) {
        return `
          <a href="${hit.url}">
            <h3>${instantsearch.highlight({ hit, attribute: 'title' })}</h3>
            <p>${instantsearch.snippet({ hit, attribute: 'content' })}</p>
          </a>
        `;
      },
      empty: '<p>No results found.</p>',
    },
  }),
  instantsearch.widgets.pagination({
    container: '#pagination',
  }),
]);

search.start();
</script>

Which Should You Choose?

  Lunr.js Algolia
Cost Free Free up to 10k requests/month
Setup Simple Moderate
Speed Good (small sites) Excellent (any size)
Typo tolerance Limited Built-in
Works offline Yes No
GitHub Pages Yes Yes
Privacy Full (no external service) Data sent to Algolia

Choose Lunr.js if: your site has under 200 posts, you want zero dependencies, or privacy is a priority.

Choose Algolia if: you have a large site, want instant-as-you-type results, or need typo-tolerant search.


Many Jekyll themes on JekyllHub include search functionality built in — check the theme’s feature list before building from scratch.

Share LinkedIn