Skip to content

Refactor Search.vue to use pagefind.js instead of window.PagefindUI #2870

@MoshiMoshiMochi

Description

@MoshiMoshiMochi

Please confirm that you have searched existing issues in the repo

Yes, I have searched the existing issues

Any related issues?

#205

What is the area that this feature belongs to?

No response

Is your feature request related to a problem? Please describe.

The current Search.vue implementation wraps window.PagefindUI — a pre-built UI component that injects its own DOM — inside a custom modal shell. This creates fragile coupling and significant maintenance overhead:

  1. CSS Override Sprawl: ~70 lines of :deep(.pagefind-ui__*) CSS overrides are required to fight PagefindUI's default styles and force alignment with MarkBind's design system.

  2. Unobservable Rendering Lifecycle: A MutationObserver is used to detect when PagefindUI renders results because Search.vue has no direct control over PagefindUI's rendering lifecycle.

  3. Dual Keyboard Navigation: Custom keyboard navigation runs alongside PagefindUI's own keyboard handling, creating potential conflicts.

  4. No Teardown API: container.innerHTML = '' on modal close is used as a teardown workaround because PagefindUI has no destroy API.

  5. Silent Failures: If window.PagefindUI is undefined (e.g., script load error), the error goes unnoticed.

  6. Unnecessary Bundle Size: pagefind-ui.js (84.6KB) + pagefind-ui.css (14.5KB) are loaded on every page, when only pagefind.js (33.8KB) is needed for the actual search functionality.

Describe the solution you'd like

Replace the window.PagefindUI integration with the lower-level pagefind.js API, which provides:

  • Direct query access returning plain data objects
  • Full control over DOM rendering via Vue reactive state
  • No CSS overrides needed (first-party styles scoped to our markup)
  • No MutationObserver, no global window dependency, no teardown hacks

Suggestions:

  1. Replace window.PagefindUI with pagefind.js — Remove <script src="pagefind-ui.js"> global; dynamically import pagefind.js inside the component
  2. In-house result rendering — Render results natively in Vue template (title, excerpt, sub-results, active highlight)
  3. In-house CSS — Replace :deep() overrides with first-party styles scoped to MarkBind's own markup

Describe alternatives you've considered

No response

Additional context

No response

Metadata

Metadata

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions