Sharing is caring!

How to Add Search to a Static WordPress Site for Free Using Lunr.js

Running a static WordPress site comes with serious perks—faster load times, better security, and fewer hosting headaches. But it’s not without its quirks. One major downside? No built-in search functionality.

That’s because WordPress’s native search is powered by PHP and queries the database. Static sites don’t use either.

But don’t worry—you can add a fully functional, client-side search feature using Lunr.js, a free JavaScript library built just for this sort of challenge.


🔍 What is Lunr.js and Why It’s Ideal for Static WordPress Sites

Lunr.js is a lightweight JavaScript-based search engine that runs entirely in the browser. It doesn’t need server-side code, databases, or even API calls—perfect for static websites. You build a search index as a JSON file, and Lunr.js uses it to match keywords and return results—all client-side.

What is Lunr.js and Why It's Ideal for Static WordPress Sites

It’s fast, free, and requires no third-party service. That means no extra hosting costs or maintenance.

Before jumping in, it’s good to know what Lunr.js does well—and where it might not be the perfect fit.


⚖️ Pros and Cons of Using Lunr.js

✅ What You’ll Love:

  • Built-in relevance scoring.
  • Handles typos with fuzzy matching.
  • Supports stemming (e.g., “run” matches “running”).

🚫 What You’ll Trade Off:

  • Doesn’t understand natural language queries.
  • Can’t process advanced search logic (though wildcard and exact-match operators are supported).

💡 Performance Tip:

Lunr is ideal for sites with fewer than 500 pages. Above that, index size and memory use may become issues. For large-scale static sites, consider alternatives like Fuse.js.


🔧 Step 1: Prep Your Dev Environment

Before anything else, gather your tools:

  • A local WordPress install (e.g., via Local by Flywheel).
  • Simply Static plugin.
  • A text/code editor like VS Code or Sublime Text.
  • Terminal (macOS/Linux) or Command Prompt (Windows).
  • Lunr.js (linked via CDN or downloaded).

⚠️ This tutorial uses a block-based theme (like Neve FSE), but works with classic themes too—with only minor tweaks.


🧪 Step 2: Add Lunr.js to Your Site’s Header

  1. Open your local WordPress site’s admin.
  2. Go to Appearance → Editor (for block themes) or Appearance → Theme File Editor (for classic themes).
 Add Lunr.js to Your Site’s Header
  1. Locate the Header template part or file.
  1. Add the following inside the <head> section via a Custom HTML block or directly in the theme file:
<script src="https://unpkg.com/lunr/lunr.js"></script>

Click Save when done.


📄 Step 3: Build a Search Page in WordPress

  1. Create a new page and name it something like Search.
  2. Add a Group block and insert:
    • A Heading block (“Search This Site”)
    • A Paragraph block (e.g., “Start typing below to find content.”)
  1. A Custom HTML block with the following:
<div class="lunr-search-container">
  <input id="lunr-search-input" placeholder="Type to search..." />
  <button id="lunr-search-button">Search</button>
  <div id="lunr-search-results"></div>
</div>
  1. Add a note below the input field with this HTML block:
<div class="search-tips">
  <small><strong>Tips:</strong> Use * for wildcards, and " " for exact phrases.</small>
</div>
  1. Add one more Custom HTML block for JavaScript:
<script>
  document.addEventListener('DOMContentLoaded', function() {
    // This is where our Lunr.js search implementation will go
    console.log('Search page loaded and ready for Lunr implementation');
    
    // Elements
    const searchInput = document.getElementById('lunr-search-input');
    const searchButton = document.getElementById('lunr-search-button');
    const resultsContainer = document.getElementById('lunr-search-results');
    
    // Just to confirm everything is connected properly
    searchButton.addEventListener('click', function() {
      resultsContainer.innerHTML = '<p>Search functionality coming soon! You searched for: <strong>' + 
        searchInput.value + '</strong></p>';
    });
  });
</script>
  1. For CSS:
<style>
  .lunr-search-container {
    max-width: 600px;
    margin: 40px auto;
    padding: 20px;
    background-color: #f9f9f9;
    border-radius: 8px;
    box-shadow: 0 2px 5px rgba(0,0,0,0.05);
  }
  
  .lunr-search-form {
    display: flex;
    gap: 10px; /* This creates space between input and button */
  }
  
  .lunr-search-input {
    flex: 1;
    padding: 12px 15px;
    font-size: 16px;
    border: 2px solid #ddd;
    border-radius: 4px;
    outline: none;
    transition: border-color 0.2s;
  }
  
  .lunr-search-input:focus {
    border-color: #0073aa;
  }
  
  .lunr-search-button {
    padding: 12px 24px;
    font-size: 16px;
    background-color: #0073aa;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transition: background-color 0.2s;
    white-space: nowrap;
  }
  
  .lunr-search-button:hover {
    background-color: #005177;
  }
  
  /* Search tips styling */
  .search-tips {
    margin-top: 20px;
    margin-bottom: 15px;
    opacity: 0.8;
    font-size: 1.0em;
  }
  
  .lunr-search-results {
    margin-top: 30px;
    min-height: 50px;
  }
  
  .lunr-result-item {
    margin-bottom: 20px;
    padding-bottom: 20px;
    border-bottom: 1px solid #eee;
  }
  
  .lunr-result-title {
    font-size: 18px;
    font-weight: bold;
    margin-bottom: 8px;
  }
  
  .lunr-result-title a {
    color: #0073aa;
    text-decoration: none;
  }
  
  .lunr-result-snippet {
    font-size: 14px;
    line-height: 1.6;
    color: #555;
  }
  
  .lunr-no-results {
    font-style: italic;
    color: #777;
  }
  
  /* Highlight styling for search results */
  .lunr-highlight {
    background-color: #ffeb3b;
    padding: 0 2px;
    border-radius: 2px;
  }
</style>

🧱 Step 4: Create the Search Index

You’ll now generate a .json file that Lunr can use to search your content.

Build a Custom Plugin to Export Your Posts:

  1. In your local site’s wp-content/plugins/, create a new folder:
    lunr-index-generator
  2. Inside it, create a file:
    lunr-index-generator.php
  3. Paste this starter plugin code:
<?php
/*
Plugin Name: Lunr Index Generator
Description: Exports post data to JSON for Lunr.js
*/

add_action('admin_menu', function() {
  add_management_page('Lunr Search Index', 'Lunr Index', 'manage_options', 'lunr-index', function() {
    echo '<div class="wrap"><h1>Lunr Index</h1>';
    if ($_POST['generate']) {
      $posts = get_posts(['numberposts' => -1, 'post_status' => 'publish']);
      $data = [];
      foreach ($posts as $post) {
        $data[] = [
          'id' => $post->ID,
          'title' => $post->post_title,
          'content' => strip_tags($post->post_content),
          'url' => get_permalink($post->ID),
        ];
      }
      file_put_contents(get_stylesheet_directory() . '/lunr-search-index.json', json_encode($data));
      echo '<p><strong>Index created!</strong></p>';
    }
    echo '<form method="post"><input type="submit" name="generate" value="Generate Index" class="button button-primary"></form>';
    echo '</div>';
  });
});
  1. Go to Plugins → Installed Plugins and activate your new plugin.
  1. Then head to Tools → Lunr Index and click Generate Index.

Your new JSON file will appear in your theme folder.


⚙️ Step 5: Add the Index to Simply Static

To include this JSON file when exporting your static site:

  1. In wp-admin, go to Simply Static → Settings → Additional Files.
  2. Add the path to your JSON index, like:
/wp-content/themes/your-theme/lunr-search-index.json

📲 Step 6: Add the Real Search JavaScript

Head back to your Search page in WordPress.

Find the bottom HTML block (where you left space for JS) and paste:

<script>
document.getElementById('lunr-search-button').addEventListener('click', function() {
  fetch('/wp-content/themes/YOUR-THEME-NAME/lunr-search-index.json')
    .then(res => res.json())
    .then(data => {
      const idx = lunr(function () {
        this.ref('id');
        this.field('title');
        this.field('content');
        data.forEach(doc => this.add(doc));
      });

      const query = document.getElementById('lunr-search-input').value;
      const results = idx.search(query);
      const output = results.map(r => {
        const item = data.find(d => d.id == r.ref);
        return `<p><a href="${item.url}">${item.title}</a></p>`;
      }).join('') || '<p>No results found.</p>';

      document.getElementById('lunr-search-results').innerHTML = output;
    });
});
</script>

🔁 Replace YOUR-THEME-NAME with your actual theme directory name.

Click Update to save your page.


🚀 Step 7: Regenerate Your Static Site

Finally, regenerate your site’s static version:

  1. Go to Simply Static → Generate.
  2. Wait for the export to complete.
  3. Upload to your host or run your update script.

Visit the live search page and test it. Try different keywords, partial matches (design*), and quoted phrases ("static WordPress").


✅ Final Thoughts

Static WordPress sites are blazing fast, but sometimes too simple. With Lunr.js, you can add a powerful search feature—without touching PHP or paying a dime.

If your site ever grows too big for Lunr to handle, Fuse.js is a great next-level option.

Got questions about adding search to your static site? Drop them in the comments below—I’m here to help.


Categories: Blog

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *