Skip to content

feat: adding search#828

Open
kaltepeter wants to merge 4 commits intomainfrom
updates
Open

feat: adding search#828
kaltepeter wants to merge 4 commits intomainfrom
updates

Conversation

@kaltepeter
Copy link
Copy Markdown
Owner

@kaltepeter kaltepeter commented Apr 18, 2026

  • feat: layout and about page
  • feat: adding search
  • feat: Update Claude Instructions to sign changes

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a site-wide note search experience to the Gatsby notes site, including a header search input with preview results and a dedicated /search results page.

Changes:

  • Introduces a search page (/search) that reads the q query param and renders matching notes.
  • Adds a useNoteSearch hook backed by js-search indexing over note metadata and excerpts.
  • Replaces the header’s static search UI with an interactive SearchInput preview popper and adds required dependencies.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/pages/search.tsx New search results page rendering matches from the search hook.
src/hooks/use-note-search.ts New hook that builds a js-search index over note documents and returns matches.
src/components/search-input.tsx New interactive header search input with preview results popper and navigation to /search.
src/components/header.tsx Integrates SearchInput into the header and simplifies drawer toggle handler.
package.json Adds js-search and TypeScript types (and updates devDependencies).
package-lock.json Locks the added dependencies.
CLAUDE.md Updates contributor/tooling guidance documentation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/pages/search.tsx
Comment thread package.json
Comment thread CLAUDE.md
Comment thread src/components/search-input.tsx Outdated
Comment thread src/pages/search.tsx Outdated
Comment thread src/hooks/use-note-search.ts Outdated
Comment thread src/pages/search.tsx Outdated
@kaltepeter
Copy link
Copy Markdown
Owner Author

Re: filter in useNoteSearch — this is a false positive. useNoteExcerptList already filters out notes with missing/empty titles before returning them, so useNoteSearch only ever receives valid documents. No change needed.

— 🤖 Claude

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/components/search-input.tsx Outdated
Comment thread src/components/search-input.tsx Outdated
Comment thread src/components/note-list-entry.tsx Outdated
Comment thread src/components/note-list-entry.tsx Outdated
Comment thread CLAUDE.md
Comment thread src/pages/search.tsx
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

package.json:50

  • Adding @eslint/js@10.0.1 introduces a Node engine requirement of ^20.19.0 || ^22.13.0 || >=24 (per the lockfile), which conflicts with this repo’s declared engine of node >=18.16.1. This can cause warnings or installation failures in environments pinned to Node 18. Consider either bumping the repo’s engines.node range to match the new dependency requirements, or selecting dependency versions that still support Node 18.
  "devDependencies": {
    "@emotion/cache": "^11.14.0",
    "@eslint/js": "^10.0.1",
    "@graphql-eslint/eslint-plugin": "^4.0.0",
    "@types/js-search": "^1.4.4",
    "@types/node": "^24.0.0",
    "@types/react": "^19.0.0",
    "@types/react-dom": "^19.0.0",
    "@typescript-eslint/eslint-plugin": "^8.0.0",
    "@typescript-eslint/parser": "^8.0.0",
    "eslint": "^10.0.0",
    "gh-pages": "^6.0.0",
    "prettier": "^3.0.0",
    "typescript": "^6.0.0"

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/components/search-input.tsx
Comment thread src/components/note-list-entry.tsx Outdated
Comment thread src/pages/search.tsx Outdated
Comment thread src/hooks/use-note-search.ts Outdated
Comment thread src/components/search-input.tsx Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +12 to +32
return useMemo(() => {
if (!isSearchEnabled) return [];

const documents = notes
.map(({ node }) => node as unknown as Note)
.filter(
(note) =>
typeof note.frontmatter?.title === "string" &&
note.frontmatter.title.trim() !== "" &&
typeof note.fields?.slug === "string" &&
note.fields.slug.trim() !== "",
);

const search = new JsSearch.Search("id");
search.addIndex(["frontmatter", "title"]);
search.addIndex(["frontmatter", "tags"]);
search.addIndex("excerpt");
search.addDocuments(documents);

return search.search(query) as Note[];
}, [isSearchEnabled, notes, query]);
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useNoteSearch rebuilds the full js-search index whenever query changes because the memo depends on query and the index is created inside the memo. This can become noticeably expensive on each keystroke as the note list grows. Consider memoizing the Search instance (and addDocuments) based only on notes, then running search.search(query) in a separate memo derived from query (or just calling it directly) so indexing is not repeated per query update.

Suggested change
return useMemo(() => {
if (!isSearchEnabled) return [];
const documents = notes
.map(({ node }) => node as unknown as Note)
.filter(
(note) =>
typeof note.frontmatter?.title === "string" &&
note.frontmatter.title.trim() !== "" &&
typeof note.fields?.slug === "string" &&
note.fields.slug.trim() !== "",
);
const search = new JsSearch.Search("id");
search.addIndex(["frontmatter", "title"]);
search.addIndex(["frontmatter", "tags"]);
search.addIndex("excerpt");
search.addDocuments(documents);
return search.search(query) as Note[];
}, [isSearchEnabled, notes, query]);
const documents = useMemo(
() =>
notes
.map(({ node }) => node as unknown as Note)
.filter(
(note) =>
typeof note.frontmatter?.title === "string" &&
note.frontmatter.title.trim() !== "" &&
typeof note.fields?.slug === "string" &&
note.fields.slug.trim() !== "",
),
[notes],
);
const search = useMemo(() => {
const nextSearch = new JsSearch.Search("id");
nextSearch.addIndex(["frontmatter", "title"]);
nextSearch.addIndex(["frontmatter", "tags"]);
nextSearch.addIndex("excerpt");
nextSearch.addDocuments(documents);
return nextSearch;
}, [documents]);
return useMemo(() => {
if (!isSearchEnabled) return [];
return search.search(query) as Note[];
}, [isSearchEnabled, query, search]);

Copilot uses AI. Check for mistakes.
if (!isoDateStr) return "";
const date = new Date(isoDateStr);
if (isNaN(date.getTime())) return "";
const diffDays = Math.floor((Date.now() - date.getTime()) / 86400000);
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

relativeDate treats future dates as "today" because diffDays becomes negative and hits the < 1 branch. If rawDate can be in the future (typos, scheduled posts, timezone parsing), this will display incorrect metadata; handle diffDays < 0 explicitly (e.g., return ""/"in Xd" or clamp to 0).

Suggested change
const diffDays = Math.floor((Date.now() - date.getTime()) / 86400000);
const diffDays = Math.floor((Date.now() - date.getTime()) / 86400000);
if (diffDays < 0) return "";

Copilot uses AI. Check for mistakes.
/>
</SearchContainer>
<ResultsPopper
open={open}
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Popper is opened based on open, but anchorEl can be null during the initial render(s) (before the ref is set), which can lead to warnings/positioning issues. Consider gating open with Boolean(anchorRef.current) (or rendering the Popper only once the anchor is available).

Suggested change
open={open}
open={open && Boolean(anchorRef.current)}

Copilot uses AI. Check for mistakes.
Comment thread package.json
"author": "Kayla Altepeter",
"engines": {
"node": ">=18.16.1",
"node": ">=24.15.0",
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bumping the supported Node engine from >=18.16.1 to >=24.15.0 is a major operational change and is significantly stricter than what Gatsby 5 itself declares (it supports >=18 <26 per the lockfile). If the project truly requires Node 24.15 specifically (vs 24.x / >=24), it would help to justify this in the PR or relax it to the minimum actually required so CI/deploy environments don’t break unnecessarily.

Suggested change
"node": ">=24.15.0",
"node": ">=18.16.1",

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants