Contents

Integrating PageFind with Hugo when hosting on Azure Static Web Apps

Last night on the The Changelog news postcast they mentioned PageFind a nifty library for adding search to static websites. The search provided out of the box from the theme I use for my blog was a bit average so I thought I’d have ago at integrating PageFind - there were a couple of gotchas that I needed to figure out.

Adding the search page into the Hugo site

This was the first gotcha I had to figure out, not being particularly well versed in the structure of Hugo, I spent a bit of time trying to figure out whether I needed to add a new layout to the theme I was using, this led me down a bit of a rabbit hole. In the end it turned out to be as simple as adding a new markdown file called search.md into the content directory

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
---
noComment: true
hideTitle: true
title: Site Search
---
<link href="/pagefind/pagefind-ui.css" rel="stylesheet">
<script src="/pagefind/pagefind-ui.js"></script>

<h1 style="text-align: center">Site Search</h1>
<div id="search"></div>
<p style="text-align: center; font-size: 0.7em">Powered by <a target="_blank" href="https://pagefind.app/">PageFind</a></p>


<script>
    window.addEventListener('DOMContentLoaded', (event) => {
        new PagefindUI({ element: "#search", showSubResults: true });
    });
</script>

This will then be available at https://unravelled.dev/search. I also updated the menu navigation for my site, that was as simple as updating the config.toml file.

Indexing during build and deploy

The PageFind docs are really well written and provide clear guidance about how to use PageFind when running locally, and when building in situations when you have bare metal deployments - however my site is hosted on Azure Static Web Apps which meant I had to figure out how to get the Azure DevOps pipeline task to work nicely with Hugo and PageFind.

Indexing your site when running locally is as simple as

1
npx -y pagefind --site public --serve

What I needed to do was get this command to run alongside the Hugo build step in my pipeline.

My first attempt was updating the AzureStaticWebApp@0 task as follows:

1
2
3
4
5
6
7
- task: AzureStaticWebApp@0
    condition: ne(variables['Build.SourceBranch'], 'refs/heads/main')
    inputs:
    app_location: '/'
    app_build_command: 'hugo -D && npx pagefind --site "public"'
    output_location: '/public'
    azure_static_web_apps_api_token: '$(STAGING_TOKEN)'

In theory this should have worked, however due to how the AzureStaticWebApp@0 task works it did not. After much trial and error I worked out that I needed to split this into two steps, the first was to build the hugo site and run the PageFind indexing, then execute the AzureStaticWebApp@0 task. My pipeline ended up as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
- task: CmdLine@2
    condition: ne(variables['Build.SourceBranch'], 'refs/heads/main')
    inputs:
    script: |
        hugo -D --destination $(Build.ArtifactStagingDirectory)
        npx pagefind --site $(Build.ArtifactStagingDirectory)

- task: AzureStaticWebApp@0
    condition: ne(variables['Build.SourceBranch'], 'refs/heads/main')
    inputs:
    workingDirectory: '$(Build.ArtifactStagingDirectory)'
    app_location: '/'
    output_location: '/'
    skip_app_build: true
    skip_api_build: true
    is_static_export: true
    verbose: true
    azure_static_web_apps_api_token: '$(STAGING_TOKEN)'

You can see the full pipeline defintion on GitHub.

With that PageFind is working nicely and available at https://unravelled.dev/search/.

🍪 I use Disqus for comments

Because Disqus requires cookies this site doesn't automatically load comments.

I don't mind about cookies - Show me the comments from now on (and set a cookie to remember my preference)