Skip to content

Commit 3c7fb7a

Browse files
authored
[feat] better search - {keyword, hybrid, semantic} (#98)
* [feat] checkpoint for semantic search * [feat] keyword, hybrid, and semantic search * [docs] adding some extra info
1 parent 3fdc41b commit 3c7fb7a

File tree

49 files changed

+5910
-147
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+5910
-147
lines changed

.claude/settings.local.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
"Bash(npx postcss:*)",
1616
"Skill(document-skills:frontend-design)",
1717
"Bash(wc:*)",
18-
"WebSearch"
18+
"WebSearch",
19+
"Bash(cat:*)",
20+
"Bash(gh pr view:*)"
1921
],
2022
"deny": []
2123
}

.github/workflows/deploy.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Deploy Jekyll with Pagefind
1+
name: Deploy Jekyll with Pagefind and Vector Search
22

33
on:
44
push:
@@ -31,6 +31,10 @@ jobs:
3131
uses: actions/setup-node@v4
3232
with:
3333
node-version: '20'
34+
cache: 'npm'
35+
36+
- name: Install Node dependencies
37+
run: npm ci
3438

3539
- name: Setup Pages
3640
id: pages
@@ -44,6 +48,9 @@ jobs:
4448
- name: Build Pagefind search index
4549
run: npx pagefind --site _site
4650

51+
- name: Generate vector search embeddings
52+
run: node _scripts/generate-embeddings.js
53+
4754
- name: Upload artifact
4855
uses: actions/upload-pages-artifact@v3
4956

Makefile

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: build-css build-img build-js build serve serve-static clean jekyll pagefind
1+
.PHONY: build-css build-img build-js build serve serve-static clean jekyll pagefind embeddings search
22

33
# i need to update this
44
build-css:
@@ -20,12 +20,20 @@ jekyll:
2020
pagefind:
2121
npx pagefind --site _site
2222

23+
# semantic search embeddings (req: _site is built)
24+
embeddings:
25+
node _scripts/generate-embeddings.js
26+
27+
# generate all search indexes (pagefind + semantic)
28+
search: pagefind embeddings
29+
@echo "Search indexes generated!"
30+
2331
# quick build
24-
build-quick: jekyll pagefind
32+
build-quick: jekyll search
2533
@echo "Build complete! _site/ ready for deployment"
2634

2735
# full build
28-
build-full: build-css build-img build-js jekyll pagefind
36+
build-full: build-css build-img build-js jekyll search
2937
@echo "Build complete! _site/ ready for deployment"
3038

3139
# local dev server (rebuilds, no search)

_includes/search-modal.html

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,45 @@
1111
<div class="search-modal__container">
1212
<div class="search-modal__header">
1313
<h2 id="search-modal-title" class="search-modal__title">Search</h2>
14+
15+
<!-- Search Mode Toggle -->
16+
<div class="search-mode-toggle" role="radiogroup" aria-label="Search mode">
17+
<button
18+
class="search-mode-toggle__btn"
19+
role="radio"
20+
aria-checked="false"
21+
data-mode="keyword"
22+
>
23+
<svg class="search-mode-toggle__icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
24+
<path d="M4 6h16M4 12h16M4 18h7"></path>
25+
</svg>
26+
Keyword
27+
</button>
28+
<button
29+
class="search-mode-toggle__btn search-mode-toggle__btn--active"
30+
role="radio"
31+
aria-checked="true"
32+
data-mode="hybrid"
33+
>
34+
<svg class="search-mode-toggle__icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
35+
<path d="M12 3v18M3 12h18M7.5 7.5l9 9M16.5 7.5l-9 9"></path>
36+
</svg>
37+
Hybrid
38+
</button>
39+
<button
40+
class="search-mode-toggle__btn"
41+
role="radio"
42+
aria-checked="false"
43+
data-mode="semantic"
44+
>
45+
<svg class="search-mode-toggle__icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
46+
<circle cx="12" cy="12" r="3"></circle>
47+
<path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"></path>
48+
</svg>
49+
Semantic
50+
</button>
51+
</div>
52+
1453
<div class="search-modal__shortcut">
1554
<kbd class="search-modal__kbd">esc</kbd>
1655
<span>to close</span>
@@ -36,8 +75,68 @@ <h2 id="search-modal-title" class="search-modal__title">Search</h2>
3675
</div>
3776

3877
<div class="search-modal__content">
39-
<!-- Pagefind UI mounts here -->
40-
<div id="pagefind-container"></div>
78+
<!-- Pagefind UI (keyword mode) -->
79+
<div id="pagefind-container" class="search-content" style="display: none;"></div>
80+
81+
<!-- Vector Search UI (semantic mode) -->
82+
<div id="vector-search-container" class="search-content" style="display: none;">
83+
<!-- Loading state -->
84+
<div class="vector-search__loading" style="display: none;">
85+
<div class="vector-search__loading-spinner"></div>
86+
<p class="vector-search__loading-message">Initializing semantic search...</p>
87+
<div class="vector-search__loading-bar">
88+
<div class="vector-search__loading-progress"></div>
89+
</div>
90+
</div>
91+
92+
<!-- Search input -->
93+
<div class="vector-search__input-wrapper">
94+
<input
95+
type="text"
96+
class="vector-search__input"
97+
placeholder="Search by meaning..."
98+
aria-label="Semantic search query"
99+
>
100+
</div>
101+
102+
<!-- Results -->
103+
<div class="vector-search__results"></div>
104+
105+
<!-- Empty state -->
106+
<div class="vector-search__empty" style="display: none;">
107+
<p>No matching results found. Try rephrasing your query.</p>
108+
</div>
109+
</div>
110+
111+
<!-- Hybrid Search UI (keyword + semantic combined) -->
112+
<div id="hybrid-search-container" class="search-content search-content--active">
113+
<!-- Loading state -->
114+
<div class="hybrid-search__loading" style="display: none;">
115+
<div class="vector-search__loading-spinner"></div>
116+
<p class="vector-search__loading-message">Initializing hybrid search...</p>
117+
<div class="vector-search__loading-bar">
118+
<div class="vector-search__loading-progress"></div>
119+
</div>
120+
</div>
121+
122+
<!-- Search input -->
123+
<div class="vector-search__input-wrapper">
124+
<input
125+
type="text"
126+
class="hybrid-search__input"
127+
placeholder="Search by keyword + meaning..."
128+
aria-label="Hybrid search query"
129+
>
130+
</div>
131+
132+
<!-- Results -->
133+
<div class="hybrid-search__results"></div>
134+
135+
<!-- Empty state -->
136+
<div class="hybrid-search__empty" style="display: none;">
137+
<p>No matching results found. Try different search terms.</p>
138+
</div>
139+
</div>
41140
</div>
42141
</div>
43142
</div>

0 commit comments

Comments
 (0)