Skip to content

Replace pagefind native binary with Pagefind.Net managed library#3721

Merged
Mpdreamz merged 5 commits into
important-beetfrom
pagefind-net-migration
Jul 24, 2026
Merged

Replace pagefind native binary with Pagefind.Net managed library#3721
Mpdreamz merged 5 commits into
important-beetfrom
pagefind-net-migration

Conversation

@Mpdreamz

@Mpdreamz Mpdreamz commented Jul 24, 2026

Copy link
Copy Markdown
Member

Why

PR #3709 downloads a platform-specific native pagefind binary, embeds it as a gzip'd resource, and shells out to it as a subprocess. This adds build complexity (Node.js packaging script, platform detection, checksum verification) and doesn't integrate with the exporter pipeline or serve mode.

What

Replaces the native binary approach with Pagefind.Net and Pagefind.Net.Frontend — pure managed .NET, AOT-compatible, no subprocess.

The pagefind indexer is now a proper IMarkdownExporter (PagefindMarkdownExporter) that:

  • Eagerly indexes each page during ExportAsync using PagefindIndex.AddRecord (O(1) memory — content is tokenized and discarded immediately)
  • Flushes the index + frontend runtime to disk in FinishExportAsync
  • Reports per-page failures via PagefindIndexingException with URL/title attached

The exporter is gated on BuildType.Isolated — it's a no-op for assembler and codex builds, which use the Elasticsearch-backed search API.

It is registered as Exporter.Pagefind, included in ExportOptions.Default and ExportOptions.Validation, so it works automatically in isolated builds, CLI --exporters html,pagefind, and docs-builder serve mode.

In serve mode, the pagefind index is built as part of the same background compilation that surfaces diagnostics to the HUD. The index data resides entirely in the in-memory filesystem (MockFileSystem) — no disk I/O needed. The web host serves pagefind files from the background build's in-memory FS via a dedicated route handler, so search becomes available as soon as the first background build completes and updates with each subsequent rebuild.

Removed the static-search feature flag — search is always available for isolated builds. The frontend gates the search UI on buildType === 'isolated'.

Tested against docs-content (2,583 pages indexed, zero failures).

@Mpdreamz
Mpdreamz requested review from a team as code owners July 24, 2026 12:15
@Mpdreamz
Mpdreamz requested a review from technige July 24, 2026 12:15
Mpdreamz and others added 4 commits July 24, 2026 14:18
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
docs-builder 1.29.0 added extension roots from FindGitRoot for Codex
commands. When config.yml lives under environments/internal/, the resolved
root is nested inside WorkingDirectoryRoot and ScopedFileSystem rejects
the overlapping roots. Normalize extension roots before constructing the
scoped filesystem so redundant nested paths are dropped.

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@Mpdreamz
Mpdreamz force-pushed the pagefind-net-migration branch from c234a97 to c1d03e6 Compare July 24, 2026 12:20
Replace PR #3709's native pagefind binary subprocess approach with the
Pagefind.Net and Pagefind.Net.Frontend NuGet packages — pure managed
.NET, no native binary, AOT-compatible.

The pagefind indexer is now a proper IMarkdownExporter that eagerly
indexes each page during ExportAsync (O(1) memory) and flushes the
index to disk in FinishExportAsync. It is included in both
ExportOptions.Default and ExportOptions.Validation, so it works in
isolated builds and docs-builder serve mode automatically.

Key changes:
- New PagefindMarkdownExporter in Elastic.Markdown/Exporters/Pagefind
- New Exporter.Pagefind enum value, registered in both ExporterParsers
- Removed native binary pipeline (package-pagefind.mjs, embedded
  resource, pagefind npm dep, PagefindSearchIndexer subprocess)
- Removed static-search feature flag — search is always available
  for isolated builds and serve mode
- Serve mode reads pagefind files from the background build's
  in-memory filesystem via a route handler
- Added .pagefind-net-frontend-version to AllowedHiddenFileNames

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@Mpdreamz
Mpdreamz force-pushed the pagefind-net-migration branch from c1d03e6 to 5ef4653 Compare July 24, 2026 12:23
@Mpdreamz
Mpdreamz merged commit 4554e3a into important-beet Jul 24, 2026
21 checks passed
@Mpdreamz
Mpdreamz deleted the pagefind-net-migration branch July 24, 2026 20:59
Mpdreamz added a commit that referenced this pull request Jul 25, 2026
* Emit Mermaid diagrams as external SVG files loaded via img (#3713)

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* Fix CopyBrandingResources failure during serve in-memory build (#3718)

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix overlapping scope roots for nested Codex config paths (#3719)

docs-builder 1.29.0 added extension roots from FindGitRoot for Codex
commands. When config.yml lives under environments/internal/, the resolved
root is nested inside WorkingDirectoryRoot and ScopedFileSystem rejects
the overlapping roots. Normalize extension roots before constructing the
scoped filesystem so redundant nested paths are dropped.

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

* Simplify scope root normalization for nested extension roots (#3720)

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

* Replace pagefind native binary with Pagefind.Net managed library

Replace PR #3709's native pagefind binary subprocess approach with the
Pagefind.Net and Pagefind.Net.Frontend NuGet packages — pure managed
.NET, no native binary, AOT-compatible.

The pagefind indexer is now a proper IMarkdownExporter that eagerly
indexes each page during ExportAsync (O(1) memory) and flushes the
index to disk in FinishExportAsync. It is included in both
ExportOptions.Default and ExportOptions.Validation, so it works in
isolated builds and docs-builder serve mode automatically.

Key changes:
- New PagefindMarkdownExporter in Elastic.Markdown/Exporters/Pagefind
- New Exporter.Pagefind enum value, registered in both ExporterParsers
- Removed native binary pipeline (package-pagefind.mjs, embedded
  resource, pagefind npm dep, PagefindSearchIndexer subprocess)
- Removed static-search feature flag — search is always available
  for isolated builds and serve mode
- Serve mode reads pagefind files from the background build's
  in-memory filesystem via a route handler
- Added .pagefind-net-frontend-version to AllowedHiddenFileNames

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Jan Calanog <jan.calanog@elastic.co>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants