Remove Blog ADR Search (SearchBox/MiniSearch)
SummaryCompletely removed the MiniSearch-based client-side full-text search (SearchBox) from the blog ADR site header. The search — introduced in Sprint 157 (minisearch dependency + build-time search-index.json generation) — is independent of ADR rendering (list/detail/archive/topics), so removal has no impact on other ADR display features. Before starting, grep separated search-only assets from shared assets — removed only search-only assets (minisearch dependency, search* i18n keys, SearchDoc type, AdrIndex.searchDocs dead field, toSearchDoc/toPlainText) while preserving shared assets (kind*/metaSprint i18n keys, buildUrl/groupByKind/mapBySprint/filterAdrsByTopic functions). The first PR #355 (d4660b0) cleaned up blog/ internals, but because the grep scope was limited to blog/, it missed that the root scripts/check-adr-links.mjs validates the (now-deleted) search-index.json existence (exit 2) → CI #355's Build Blog (SSG) job was actually a failure, but since that job is not a branch-protection required check, the squash merge proceeded and main was merged in a broken state. The /stop gate's local check-adr-links run caught it → a follow-up PR removed the search-index validation in check-adr-links.mjs + tidied the ci.yml paths-filter comment. tsc 0 · next lint 0/0 · build 329 pages (search-index.json not regenerated) · check-adr-links KR/EN exit 0 · doc-refs 363 0 broken · grep residue 0 · Critic (Codex) Critical/High 0.
Goal
- Completely remove the MiniSearch-based client-side full-text search (SearchBox) from the blog (
blog/) ADR site header. - Cleanly remove search-related code, build artifacts, dependencies, translation keys and the CI gate that validated the search artifact, while preserving the rest of the ADR site (list/detail/archive/topics rendering) and build/type/lint/link-integrity gate consistency.
Background
- ADR search was introduced in Sprint 157 (
minisearchdependency +scripts/generate-search-index.mjsbuildingpublic/adr/search-index.jsonat build time → runtime fuzzy search viafetch+MiniSearch). It was a dropdown UI opened via the/keyboard shortcut, searching ADR titles, agent names, and body text. - Search is independent of the ADR rendering pipeline (loader/parser →
buildAdrIndex→ list/detail/archive/topics views). SearchBox is mounted only inAdrHeaderand fetches the search index (search-index.json) directly, so removing it has no impact on other ADR display features. - Technical key: the
AdrIndex.searchDocsfield is produced bybuildAdrIndexinindex-builder.ts, but its consumers (adr/page.tsx·archive/page.tsx·post-page.tsx) all read only.all/.byKind/.bySprintand never read.searchDocs— it was effectively a dead field. Thus removal has zero runtime impact.
Decisions
D0. Search-only vs shared assets — separated up front via grep
- Getting the deletion scope wrong would break ADR rendering, so before starting, grep separated assets used only by search from shared assets used by non-search components too.
- Search-only (safe to delete):
minisearchdependency,searchPlaceholder/searchAriaLabel/searchEmptyi18n keys (referenced only in SearchBox),SearchDoctype,AdrIndex.searchDocsfield,toSearchDoc/toPlainTextfunctions. - Shared (must keep):
kindPermanent/kindTopic/kindSprint/metaSprinti18n keys — also used inadr-card·adr-category-tabs·sprint-timeline·adr-meta-sidebar.buildUrl/groupByKind/mapBySprint/filterAdrsByTopic— still used by ADR rendering.
- Search-only (safe to delete):
D1. Full-deletion vs modification classification
- Full deletion (3 files):
search-box.tsx(search UI),generate-search-index.mjs(build script),search-index.json(artifact,.gitignore'd so removed from disk only). - Modification (5 files):
package.json(prebuild hook + minisearch dependency),adr-header.tsx(SearchBox mount),i18n.ts(search* keys),types.ts(SearchDoc type + searchDocs field),index-builder.ts(search helpers + searchDocs return).
D2. Remove minisearch dependency / prebuild hook together
- Search was the only minisearch consumer, so
dependencies.minisearchis removed and the lockfile synced vianpm install. Thescripts.prebuild(index generation hook) is removed too →search-index.jsonis no longer regenerated at build time.
D3. (Follow-up) Remove the CI gate that validated the search artifact — grep-scope miss correction
- The first pass's grep scope was limited to
blog/(src·scripts·package.json), so it missed that the rootscripts/check-adr-links.mjssanity-checks the build artifact'ssearch-index.jsonexistence + entry count (exit 2 on missing). - Since search-index.json is no longer generated, that gate always fails. So the search-index validation block in
check-adr-links.mjs(header comments·runMain step 3·thecheckSearchIndexfunction·export) is removed, leaving only internal link integrity checks (exit 0/1). Thegenerate-search-index.mjsmention in theci.ymlpaths-filter comment is also tidied.
Implementation
Pass 1 — Remove the search feature (1 commit, PR #355 squash → d4660b0)
689d0d6chore(blog): remove ADR search (SearchBox/MiniSearch) (8 files, +4/-520)- Deleted:
blog/src/components/adr/search-box.tsx(-265),blog/scripts/generate-search-index.mjs(-176),blog/public/adr/search-index.json(artifact, not agit rmtarget →rm). package.json/package-lock.json: removedprebuildhook +minisearchdependency, synced lockfile vianpm install.adr-header.tsx: removedSearchBoximport +<SearchBox />render, tidied@relatedcomment (only Blog link·LocaleToggle remain).i18n.ts: removed ko+ensearchPlaceholder/searchAriaLabel/searchEmpty. Key type auto-derived asDictKey = keyof typeof DICTIONARY['ko']→ no separate union edit needed.kind*/metaSprintpreserved.types.ts: removedSearchDocinterface +AdrIndex.searchDocsfield.index-builder.ts: removedSearchDocimport·toSearchDoc·toPlainText·CODE_FENCE_RE/MD_SYMBOL_RE, removedsearchDocsfrombuildAdrIndexreturn.buildUrl/groupByKind/mapBySprint/filterAdrsByTopicpreserved.
- Deleted:
Pass 2 — Clean up the CI gate (follow-up PR, caught by the /stop gate)
fix(ci): remove search-index validation from check-adr-links.mjs (Sprint 201 search removal follow-up)scripts/check-adr-links.mjs: removed the search-index sanity-check block +checkSearchIndexfunction + export + related header comments/exit 2. Performs only internal link integrity (exit 0/1). All imports remain used by surviving functions..github/workflows/ci.yml: tidied thegenerate-search-index.mjsmention in the blog paths-filter comment (keptloader.ts(DIR_KIND_MAP)+ a Sprint 201 removal note).
Verification
- Type/build:
tsc --noEmit0.next lint0 errors / 0 warnings.npm run build— 329 static pages, ADR routes (KR/EN) OK,search-index.jsonnot regenerated after prebuild removal. - Link integrity gate: with the fixed
check-adr-links.mjs, both KR (blog/out/adr) and EN (blog/out/en/adr) exit 0 (151 HTML, ~1200 internal links all resolved, including the sprint-201 ADR). Right after pass 1 it was[FAIL] search-index.json not found(exit 2). - Other gates:
check-doc-refs.mjs363 files 0 broken.check-adr-index-count.mjs --strictsprint 139 match.check-adr-en-coverage.mjs --lint148/148. - grep residue:
SearchBox/minisearch/searchDocs/SearchDoc/search-index/checkSearchIndex/search* i18n → 0 globally (blog/ + root scripts/). - Critic (pass 1):
codex review --base main(Codex, session019e4eec-c0d8-7df3-becd-a9230ebb3156) — Critical/High/Medium/Low 0 ("the deletion appears internally consistent"). However codex's review scope was the pass-1 diff (blog/ + package.json); the root gate script was out of scope, so the search-index gate miss went undetected → caught by the /stop local gate. - CI: #355's Build Blog (SSG) job was actually a failure (the search-index gate) but merged due to it not being a required check. The follow-up PR re-triggers Build Blog (SSG) via
docs/adr/sprints/**·docs/adr-en/sprints/**changes → passes with the fixed gate.
New Patterns
- Pre-deletion grep — repo-wide classification — exhaustively trace the target feature's symbols/artifacts (components·types·fields·i18n keys·dependencies·build artifacts + the root gates/CI steps that validate them) via repo-wide grep and classify into "exclusive (delete) / shared (keep)" before starting. Limiting grep to a subdirectory like blog/ causes root-gate misses → CI regressions.