If you have a static WordPress site or you’re strongly considering launching one, then you’re probably already aware of its default limitations. One of the big ones is the inability to add a search function to your site. This is due to the fact that the “regular way” search works on a standard WordPress site is via PHP and static sites don’t use PHP. The roadblock is obvious here.
But with a little bit of creative thinking, you can use a free, open-source JavaScript library called Lunr (along with a few other tools) to get around it and add search to your static site anyway.

So if you’re ready to channel some inner JCVD Bloodsport energy into your WordPress static site then let’s get started.
What is Lunr.js and why it’s a perfect search solution for static sites 🌙
⏭️ If you’re already sold and just want the implementation steps, click here to skip straight to the tutorial.
Lunr.js is a compact JavaScript library that’s designed specifically for browser-based search. Unlike traditional WordPress search which hammers your database with queries, Lunr.js handles everything on the client side. No PHP processing. No API calls to external services. Just pure, speedy JavaScript goodness.
The best part is that adding Lunr.js to your static site won’t increase your hosting costs one cent. Your site will still run on Cloudflare Pages (or a similar service) with all the benefits I covered in the main guide on how to launch a static site.
With that said, I want to briefly set some proper expectations. Lunr.js has a lot going for it, but it’s not a flawless solution. Here’s what to expect…
The ups and downs of using Lunr.js ⬆️⬇️
There are two main things to take into consideration when deciding if this is going to be a good search solution for your static site:
- Size of your site.
- Search quality trade-offs.
Performance considerations for larger sites
Lunr.js works brilliantly for small to medium-sized sites, but there are some practical limits to consider:
- Index size and loading time: For every 100 posts, expect roughly 100-200KB of index file size. This might not sound like much, but a site with 1,000+ posts could end up with a 1MB+ index that would need to load in visitors’ browsers before searching begins. For smaller sites, this loading is nearly instantaneous, but larger sites might experience a noticeable delay.
- Memory usage: The entire index loads into the browser’s memory. For very large sites, this could potentially slow down the visitor’s browser (i.e., not just the tab with your search page but all their tabs).
The bottom line is that if your site has fewer than 500 pages, you’ll likely be fine.
Search quality: What you gain and what you give up
Compared to server-side search solutions, Lunr.js makes some tradeoffs:
The good stuff:
- Relevance-based ranking out of the box.
- Fuzzy matching to deal with accidental typos.
- Term stemming (finding “running” when searching for “run”).
The compromises:
- No natural language processing for understanding query intent.
- Limited ability to handle complex queries with many search operators. This isn’t an enormous drawback since most people don’t use search operators anyway, but it’s just something to be aware of in case it’s important to you. The solution I’m going to give you includes two (wildcard and exact match) search operators which will suffice for the vast majority of use cases.
For most personal blogs, portfolio sites, and small business websites, these tradeoffs are completely reasonable. Your visitors will still get helpful, relevant results.
Phase one: Set up your development environment 👨🏻💻
Now that you understand what Lunr.js is all about, it’s time to roll up your sleeves and get everything ready for implementation.
Required tools 🧰
To pull this off, you’ll need a few essentials:
- Your local WordPress site (with the Simply Static plugin).
- Lunr.js library.
- A code editor (e.g., Sublime Text or even the simple text editors that come installed on both Mac and Windows).
- Terminal on Mac / Command Line on Windows.
If you followed my previous guide on setting up a static WordPress site, then all of these – with the exception Lunr.js perhaps – will be familiar to you.
⚠️ Note: My demo static site was built using Neve FSE, which is a block theme, but you can use this tutorial for classic themes as well. There’s only one tiny difference in the way it gets implemented and that difference happens right at the beginning of the tutorial – I’ll point it out.
Add Lunr.js to your local WordPress environment 🖥️
Assuming you are using Local by Flywheel, the first step is to get into your WordPress site. Make sure the One-click admin is toggled on and then tap on the WP Admin button:

Next, from your WordPress dashboard, go to Appearance → Editor.

This will bring you into the Full Site Editor. Select Patterns from the side menu:

If you’re not specifically using the Neve FSE theme but another block theme then the next screen is going to look slightly different.
Nonetheless, you should be able to see an option for Header under All template parts.
This is because every theme is going to have at least one header template where your navigation menu and other common features are stored (e.g., site icon, site title). Many themes actually have multiple header templates (that includes Neve FSE), but the default one is typically called “Header” with no other words.
You might also see “Main Header” or “Header Main.” The idea is to look for the one that sounds the most like it’s the default option. Once you have it, tap the three vertical dots and click on Edit:

Next, you will need to add a Custom HTML block to the header template, which means you’ll first need to get to the highest-level parent block by clicking anywhere inside the header. After that:
- Click the farthest left button repeatedly until you reach the top parent block.
- Once there, click the little + icon on the bottom right to add a new block.
- Type in html.
- Click on Custom HTML to add the block.

Copy the code snippet below and paste it into the HTML block:
<script src="https://unpkg.com/lunr/lunr.js"></script>
Code language: HTML, XML (xml)

Click Save to apply the changes.
Create a search test page 🔎
After successfully adding Lunr.js to your header template, the next step is to create a dedicated search page where your site visitors will go so they can search your site:
From your WordPress dashboard, go to Pages → Add New Page.
Once you’re inside the block editor, you can get to work.
First, give the page a name. There’s no need to be creative here. “Search” or “Search + Your Website’s Name” will probably work for 99% of websites.
Next, add a Group block to contain everything:
Click the + icon, type group into the search field and select the Group block. Then click on the first option, which just looks like a single rectangle:

Inside the Group block, add the following:
- A Heading block with text like “Search Our Site.”
- A Paragraph block with brief instructions (e.g., “Type what you’re looking for. Be descriptive, but concise”).
Make sure that as you are adding the two blocks that you tap the far left button so when you click the + icon, it’ll be inside the Group parent block:

Now for the crucial part – you need to add an HTML block for the search interface. Make sure you are inside the Group parent block and then:
- Click the + icon to add a new block.
- Search for html and select the Custom HTML block.
- Paste the following code into it:
<div class="lunr-search-container">
<div class="lunr-search-form">
<input type="text" id="lunr-search-input" placeholder="Search for..." class="lunr-search-input">
<button id="lunr-search-button" class="lunr-search-button">Search</button>
</div>
<div id="lunr-search-results" class="lunr-search-results"></div>
</div>
Code language: JavaScript (javascript)
Below this, add three more HTML blocks.
The code for the first one will add a note on how to use two search operators – the wildcard and exact match – for different needs:
<div class="search-tips">
<small>
<strong>Search tips:</strong>
Use * for partial matches (i.e., design* finds design, designer) and " " for exact phrases (i.e., "static site").
</small>
</div>
Code language: HTML, XML (xml)
You could technically also add the above as just a regular paragraph block, but using the <div class="search-tips">
allows for some minor styling that gets pulled from the next block below. If you do choose to use a paragraph block instead, you should still add the CSS code 👇🏻 because it sets the look for your entire search block. The search tips are only a small part of that.
The third one is actually just a placeholder. It will eventually contain your JavaScript code but you’re adding the placeholder for now so you can test it to make sure everything is working properly:
Testing is the next step, but before you do that, quickly do one more spot check to ensure that all of the blocks were added inside the Group block. You should see a thin line that surrounds everything with all six of your blocks (i.e., heading, paragraph, four HTML) inside of it:

Testing the search interface
Next, click on Save Draft on the top right and then the preview button to see what your search page looks like on the frontend of your site.
Try typing something in the search box and clicking the Search button. You should see a message that says Search functionality coming soon! followed by whatever you typed.

If everything displays correctly, congratulations! You’ve successfully set up the search interface. The search won’t actually work yet because you haven’t created your search index, but the foundation is in place.
Go back to the block editor tab and click on Publish. You’re now ready for phase two.
Phase two: Create a search index generator 🏗️
For Lunr.js, your search index needs to be a structured JSON file that contains all the searchable content from your WordPress site. This file will get loaded by your JavaScript code when someone visits the search page. Although the JSON file could be created manually, it’s more efficient to automate it. For that, you’ll need a mini custom-made plugin.
Build a custom content extraction plugin 🔌
First, open up Local by Flywheel and make sure that the site you are working on is selected (if you have more than one site). Then do the following:
- Tap on the Site folder located directly below your site name at the top. This will open up Finder on Mac (shown below) or File Manager on Windows and you’ll see some folders there.
- Go into
app
, followed bypublic
, followed bywp-content
, and finallyplugins
. - Inside of
plugins
, create a new folder calledlunr-index-generator
:

Open up Sublime Text or whatever code/text editor you used earlier and paste the code below into it. Then save the file as lunr-index-generator.php
inside of this new lunr-index-generator
folder:
The next step is to activate it.
Activate the plugin and generate your JSON file
Go back to your WordPress site and activate the plugin like you would any other plugin: Plugins → Installed Plugins → Activate.

After activation, go to Tools → Lunr Search Index.
Check which content types you want to include (i.e., posts, pages) and click on Generate Index. The plugin will automatically save the JSON file for you.
⚠️ Copy the location to the right of where it says File saved to.
Also, even though the plugin saves it, download a copy anyway so you can quickly inspect it:

Once you open it up, you should see text that corresponds to your pages and/or posts. For example, mine looked like this:

If everything is good, you can go ahead and add it to your static setup.
✋ Assuming you read and followed my tutorial on setting up a WordPress static site, then you’ll already have the Simply Static plugin installed and configured. If that’s not the case, then I suggest heading to the tutorial first and then coming back here. Alternatively, if you’re using a different solution and would like to stick with it, then you’ll need to find the equivalent of what I’m about to show you below.
From your wp-admin, go to Simply Static → General and paste the location of the JSON file you set aside into the Additional Files and Directories window. It should look something like this:
/Users/username/Local Sites/site-name/app/public/wp-content/themes/theme-name/lunr-search-index.json
Code language: PHP (php)
The difference being that username
, site-name
, and theme-name
should be your actual information.

Phase three: Implement the search interface 🔋
At this point you’ve got your Lunr.js library loaded and a fresh JSON index full of content. Now comes the fun part – bringing it all together to create a working search feature for your site visitors.
Connect the dots 🔗
Remember that placeholder JavaScript you added to your search page earlier? It’s time to swap it out for the real deal. Head back to your search page and edit it:
- Go to Pages → All Pages in your WordPress dashboard.
- Find your Search page and click Edit.
- Locate your Group block containing the HTML blocks.
- Find the JavaScript HTML block (the most bottom one on the page) and replace the placeholder code with the full implementation below – but ⚠️ for this line
fetch('wp-content/themes/YOUR-THEME-NAME/lunr-search-index.json')
substitute/YOUR-THEME-NAME/
with your actual theme name. For example, in my file, that line looked like this:fetch('/wp-content/themes/neve-fse/lunr-search-index.json')
. The completed line should also partially match what you added to the Additional Files and Directories window in the Simply Static plugin. The only difference is that in the plugin you wrote the full path, whereas here it starts from/wp-content/
.
Test your search functionality
After you replace the code, save the page and test it on the frontend. Type something into the search bar that relates to content on your site and see if you get a result:

Also click on the result to ensure that it takes you to the page or post that’s showing.
Then try the search operators. Type the same query but add a * to then end of it and see what comes up:

Repeat again but put your query inside quotation marks. If everything looks like it’s working, then you can make your way to the last leg of the implementation.
Phase four: Update your live site 📤
Publishing the search page to your live site is an exciting moment and shouldn’t take you more than a minute or two if you already have everything set up from having followed my WordPress static site tutorial. From your wp-admin inside of Local:
- Go back to Simply Static and check the Diagnostics option to make sure there are no issues.
- If everything is fine, then tap on Generate:

Afterwards do the following:
Open up Terminal and make your way to the directory (folder) that has your Python snippet. For example:
cd ~/Desktop/website-tools
Code language: JavaScript (javascript)
From inside the folder, run the execution script:
./update-website.sh
Use File Explorer to go to the folder that has your Python snippet. If you’re unsure, you can search for it – update-website.bat
. This is assuming that you saved the file under that name as suggested in my static site tutorial. If not, then you can try searching for .bat
, which will bring up all .bat
files on your hard drive. After you find the file, double click it to execute it.
✋🤔 If you need more context, go to the static WordPress site tutorial and then come back here after you read it.
Wait a few minutes after you run the Python script. Then check your live website, but more importantly check the search page. Test it one final time so you know everything is still working and that’s it. You’re done. 🎉
Final thoughts 💭
Static WordPress sites come with a host of advantages – cost, speed, security – but they’re not without their limitations. Luckily, there are all sorts of ways to work around them if you’re willing to think creatively and put in a little bit of work.
Whether it’s adding a full-fledged search solution like we covered here or adding contact forms like I covered previously, you can have your cake and eat it too.
For search specifically, if your site ever grows beyond the 500-page mark where Lunr.js starts to show its limitations, Fuse.js makes an excellent alternative. It works differently (using fuzzy matching at search time rather than building an index upfront like you learned here), but it’s much more efficient for static sites with massive amounts of content.
Do you have any questions on how to add search to a static site? Let me know in the comments below. I’ll be happy to help.
…
Don’t forget to join our crash course on speeding up your WordPress site. Learn more below: