fix: load pagefind once in base layout, eliminate duplicate scripts

Pagefind CSS/JS is now loaded once in base.njk <head> with defer.
A tiny initPagefind() helper queues widget inits until DOMContentLoaded
when PagefindUI is available. Removes duplicate <link>/<script> tags
from all sidebar widgets, search page, and 404 page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ricardo
2026-02-13 10:50:32 +01:00
parent 60b59949ef
commit 7cb0203adc
6 changed files with 29 additions and 50 deletions

12
404.njk
View File

@@ -14,15 +14,5 @@ pagefindIgnore: true
</a>
</div>
<link rel="stylesheet" href="/pagefind/pagefind-ui.css">
<div id="search-404" class="max-w-2xl mx-auto"></div>
<script src="/pagefind/pagefind-ui.js"></script>
<script>
window.addEventListener("DOMContentLoaded", () => {
new PagefindUI({
element: "#search-404",
showSubResults: true,
showImages: false,
});
});
</script>
<script>initPagefind("#search-404", { showSubResults: true });</script>

View File

@@ -33,14 +33,8 @@
{% elif widget.type == "search" %}
<div class="sidebar-widget">
<h3 class="text-sm font-semibold text-surface-600 dark:text-surface-400 uppercase tracking-wide mb-3">Search</h3>
<link rel="stylesheet" href="/pagefind/pagefind-ui.css">
<div id="blog-sidebar-search"></div>
<script src="/pagefind/pagefind-ui.js"></script>
<script>
window.addEventListener("DOMContentLoaded", function() {
new PagefindUI({ element: "#blog-sidebar-search", showSubResults: false, showImages: false });
});
</script>
<script>initPagefind("#blog-sidebar-search");</script>
</div>
{% elif widget.type == "custom-html" %}
{% set wConfig = widget.config or {} %}

View File

@@ -16,17 +16,10 @@
{% elif widget.type == "categories" %}
{% include "components/widgets/categories.njk" %}
{% elif widget.type == "search" %}
{# Pagefind search widget #}
<div class="sidebar-widget">
<h3 class="text-sm font-semibold text-surface-600 dark:text-surface-400 uppercase tracking-wide mb-3">Search</h3>
<link rel="stylesheet" href="/pagefind/pagefind-ui.css">
<div id="sidebar-search"></div>
<script src="/pagefind/pagefind-ui.js"></script>
<script>
window.addEventListener("DOMContentLoaded", function() {
new PagefindUI({ element: "#sidebar-search", showSubResults: false, showImages: false });
});
</script>
<script>initPagefind("#sidebar-search");</script>
</div>
{% elif widget.type == "webmentions" %}
{% include "components/widgets/webmentions.njk" %}

View File

@@ -27,14 +27,8 @@
{% elif widget.type == "search" %}
<div class="sidebar-widget">
<h3 class="text-sm font-semibold text-surface-600 dark:text-surface-400 uppercase tracking-wide mb-3">Search</h3>
<link rel="stylesheet" href="/pagefind/pagefind-ui.css">
<div id="listing-sidebar-search"></div>
<script src="/pagefind/pagefind-ui.js"></script>
<script>
window.addEventListener("DOMContentLoaded", function() {
new PagefindUI({ element: "#listing-sidebar-search", showSubResults: false, showImages: false });
});
</script>
<script>initPagefind("#listing-sidebar-search");</script>
</div>
{% elif widget.type == "webmentions" %}
{% include "components/widgets/webmentions.njk" %}

View File

@@ -53,6 +53,20 @@
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg">
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="stylesheet" href="/pagefind/pagefind-ui.css">
<script src="/pagefind/pagefind-ui.js" defer></script>
<script>
// Pagefind init helper — queues creation until PagefindUI is available (deferred script)
var _pfQueue = [];
function initPagefind(sel, opts) { _pfQueue.push([sel, opts]); }
document.addEventListener("DOMContentLoaded", function() {
if (typeof PagefindUI === "undefined") return;
for (var i = 0; i < _pfQueue.length; i++) {
var el = document.querySelector(_pfQueue[i][0]);
if (el) new PagefindUI(Object.assign({ element: _pfQueue[i][0], showSubResults: false, showImages: false }, _pfQueue[i][1] || {}));
}
});
</script>
<link rel="stylesheet" href="/css/style.css?v={{ '/css/style.css' | hash }}">
<link rel="stylesheet" href="/css/prism-theme.css?v={{ '/css/prism-theme.css' | hash }}">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/lite-youtube-embed@0.3.2/src/lite-yt-embed.min.css">

View File

@@ -10,30 +10,24 @@ pagefindIgnore: true
<p class="text-surface-600 dark:text-surface-400">Search across all posts, articles, notes, and pages.</p>
</div>
<link rel="stylesheet" href="/pagefind/pagefind-ui.css">
<div id="search"></div>
<script src="/pagefind/pagefind-ui.js"></script>
<script>
window.addEventListener("DOMContentLoaded", () => {
const ui = new PagefindUI({
element: "#search",
showSubResults: true,
showImages: false,
});
initPagefind("#search", { showSubResults: true });
// Support ?q= query parameter
// Support ?q= query parameter and auto-focus
window.addEventListener("DOMContentLoaded", () => {
const params = new URLSearchParams(window.location.search);
const query = params.get("q");
if (query) {
ui.triggerSearch(query);
}
// Auto-focus the search input
const input = document.querySelector("#search input[type='text']");
if (input && !query) {
input.focus();
if (input) {
input.value = query;
input.dispatchEvent(new Event("input", { bubbles: true }));
}
} else {
const input = document.querySelector("#search input[type='text']");
if (input) input.focus();
}
});
</script>