-
-
Notifications
You must be signed in to change notification settings - Fork 88
feat: global search component added in the homepage #84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
|
@aysahoo is attempting to deploy a commit to the bruvimtired-pro Team on Vercel. A member of the Team first needs to authorize it. |
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughTwo new React components were added: one implements a homepage with featured open source launches and animated voting, and the other provides an accessible, interactive modal for searching projects with debounced queries and keyboard shortcuts. Additionally, a new CSS keyframe animation for floating effects was introduced. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Homepage
participant SearchModal
participant Backend
User->>Homepage: Visit homepage
Homepage->>User: Render hero and featured launches
User->>Homepage: Click "Vote" on a launch
Homepage->>Homepage: Trigger floating triangle animation
User->>SearchModal: Press Cmd/Ctrl+K
SearchModal->>User: Open search modal
User->>SearchModal: Type search query
SearchModal->>Backend: Fetch search results (debounced)
Backend-->>SearchModal: Return project results
SearchModal->>User: Display results, allow navigation
User->>SearchModal: Select project or close modal
SearchModal->>User: Update UI or close modal
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
✨ Finishing Touches🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (1)
apps/web/components/search-comp.tsx (1)
69-72: Improve empty state message for short search queries.When the query length is less than 3 characters, the component renders an empty string, leaving users without feedback. Consider providing a helpful message instead.
- {query.length < 3 - ? '' - : `No projects match "${query}". Try different keywords or check your spelling.`} + {query.length < 3 + ? 'Type at least 3 characters to search' + : `No projects match "${query}". Try different keywords or check your spelling.`}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
.vscode/settings.json(1 hunks)apps/web/app/(public)/homepage/page.tsx(1 hunks)apps/web/components/search-comp.tsx(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
apps/web/components/search-comp.tsx (2)
packages/db/src/schema/projects.ts (1)
project(16-64)packages/ui/src/components/link.tsx (1)
Link(17-44)
🔇 Additional comments (3)
.vscode/settings.json (1)
4-7: LGTM! Clean formatting changes.The removal of the trailing comma and single-line array formatting improve consistency without affecting functionality.
apps/web/components/search-comp.tsx (2)
119-131: Good caching strategy for repository metadata.The long cache times (12-24 hours) are appropriate for repository metadata that doesn't change frequently, reducing unnecessary API calls.
347-351: Excellent accessibility implementation!The search component includes comprehensive ARIA attributes for screen readers, proper role assignments, and keyboard navigation support.
Also applies to: 372-374
| approvalStatus: 'approved', | ||
| page: 1, | ||
| pageSize: 6, | ||
| sortBy: 'recent', | ||
| }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider server-side filtering for pinned projects.
The current implementation fetches 6 projects and then filters for isPinned client-side, which could result in fewer results than expected if not all fetched projects are pinned.
Consider adding an isPinned filter parameter to the API query to ensure you get the desired number of pinned projects:
...trpc.projects.getProjects.queryOptions({
approvalStatus: 'approved',
+ isPinned: true,
page: 1,
pageSize: 6,
sortBy: 'recent',
}),Then remove the client-side filtering on line 262:
- const pinnedProjects = pinnedProjectsData?.data?.filter((project) => project.isPinned) || [];
+ const pinnedProjects = pinnedProjectsData?.data || [];Also applies to: 262-262
🤖 Prompt for AI Agents
In apps/web/components/search-comp.tsx around lines 226 to 230 and line 262, the
code fetches 6 projects and filters pinned projects client-side, which may yield
fewer results than expected. Modify the API query to include an isPinned filter
parameter so the server returns only pinned projects, ensuring the correct
number of results. Then remove the client-side filtering on line 262 to avoid
redundant filtering.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/web/app/(public)/homepage/page.tsx (2)
9-46: Consider improvements to mock data structure.The mock data serves its purpose, but consider these enhancements:
- Vote counts are stored as strings (
'2.7K','1.9K') which could complicate numeric sorting if needed- For better organization, consider moving this data to a separate constants file
If numeric operations on votes are needed, consider storing both display and numeric values:
const featuredLaunches = [ { id: 1, name: 'Zeitworld', shortDescription: 'Ship websites faster.', longDescription: 'Ship better websites. Faster. Build and deploy with modern tools.', - votes: '2.7K', + votes: '2.7K', + voteCount: 2700, }, // ... rest of items ] as const;
109-201: Consider accessibility improvements for triangle symbols.The featured launches section is well-implemented with good responsive design, but consider accessibility enhancements:
Replace unicode triangle symbols with proper semantic elements or add aria-labels:
- <span className="text-xs sm:text-sm">▲</span> + <span className="text-xs sm:text-sm" aria-label="upvote">▲</span>And for floating triangles:
- <span className="text-xs text-cyan-400 sm:text-sm">▲</span> + <span className="text-xs text-cyan-400 sm:text-sm" aria-hidden="true">▲</span>Also consider adding proper button aria-labels:
<Button variant="outline" size="sm" onClick={() => handleVoteClick(launch.id)} + aria-label={`Vote for ${launch.name}`} className="flex h-6 items-center gap-0.5..." >
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
apps/web/public/sunshine1.pngis excluded by!**/*.png
📒 Files selected for processing (2)
apps/web/app/(public)/homepage/page.tsx(1 hunks)apps/web/app/globals.css(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- apps/web/app/globals.css
🧰 Additional context used
🧠 Learnings (1)
apps/web/app/(public)/homepage/page.tsx (1)
Learnt from: Vicentesan
PR: #18
File: apps/web/app/(public)/page.tsx:7-15
Timestamp: 2025-06-13T17:21:40.703Z
Learning: Landing-page sections intentionally omit relative on the parent of the absolutely-positioned background <Image> so the image anchors to the viewport, becoming the header’s global backdrop.
🧬 Code Graph Analysis (1)
apps/web/app/(public)/homepage/page.tsx (2)
packages/ui/src/components/button.tsx (1)
Button(56-56)packages/ui/src/components/link.tsx (1)
Link(17-44)
🔇 Additional comments (3)
apps/web/app/(public)/homepage/page.tsx (3)
1-7: LGTM: Imports are well-organized and appropriate.The imports are correctly structured with the 'use client' directive at the top, and all dependencies are relevant to the component's functionality.
69-107: LGTM: Well-structured hero section with good responsive design.The hero section implementation is solid:
- Proper semantic HTML structure with
h1heading- Responsive design using Tailwind breakpoints
- Creative use of CSS blend modes for the background effect
- Event tracking properly implemented on the CTA button
- Good accessibility with descriptive text and proper link structure
166-181: floatUp Keyframes Animation ConfirmedThe
floatUpanimation is defined in apps/web/app/globals.css:
- Located at
@keyframes floatUpin apps/web/app/globals.css- Keyframes cover 0%, 50%, and 100% transforms and opacity
With the animation present, the floating triangle implementation is solid—proper staggering, positioning, and React key usage are all in place. Approved.
…ollabute#167) Co-authored-by: Ahmet Kilinc <akx9@icloud.com>
…llabute#162) Co-authored-by: Ahmet Kilinc <akx9@icloud.com>
* added the pending feature to the profile page * refactored the code a bit:removed redundant approvalStatus assignment (defaults to 'pending') * refactor:fixed a problem in code * small-fixes --------- Co-authored-by: Ayush Ranjan Sahoo <77970726+aysahoo@users.noreply.github.com>
* project-ogimage * add cache headers --------- Co-authored-by: Ahmet Kilinc <akx9@icloud.com>
* Fix: improved the sortby_stars_forks_name improved the sortby_stars_forks_name * done code refractor
…ute#170) * fix:issue collabute#160 profile page contribution not working * bug:fix Removed redundant client-side filtering
…into search_comp
| onError={(e) => { | ||
| e.currentTarget.src = `https://ui-avatars.com/api/?name=${encodeURIComponent(repoData.owner.login)}&size=160`; | ||
| }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The onError handler in the JSX img element will not work in server-side ImageResponse generation, potentially causing avatar fallback failures.
View Details
📝 Patch Details
diff --git a/apps/web/app/api/og-image/[provider]/[owner]/[repo]/route.tsx b/apps/web/app/api/og-image/[provider]/[owner]/[repo]/route.tsx
index 15582c8..a001797 100644
--- a/apps/web/app/api/og-image/[provider]/[owner]/[repo]/route.tsx
+++ b/apps/web/app/api/og-image/[provider]/[owner]/[repo]/route.tsx
@@ -133,6 +133,17 @@ export async function GET(
const displayName = projectName || repoData.name;
const displayDescription = description || repoData.description || '';
+ // Validate avatar URL server-side since onError handlers don't work in ImageResponse
+ let validatedAvatarUrl = repoData.owner.avatar_url;
+ try {
+ const avatarResponse = await fetch(validatedAvatarUrl, { method: 'HEAD' });
+ if (!avatarResponse.ok) {
+ validatedAvatarUrl = `https://ui-avatars.com/api/?name=${encodeURIComponent(repoData.owner.login)}&size=160`;
+ }
+ } catch {
+ validatedAvatarUrl = `https://ui-avatars.com/api/?name=${encodeURIComponent(repoData.owner.login)}&size=160`;
+ }
+
const formatNumber = (num: number): string => {
if (num >= 1000000) {
return (num / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
@@ -166,13 +177,10 @@ export async function GET(
}}
>
<img
- src={repoData.owner.avatar_url}
+ src={validatedAvatarUrl}
alt={`${repoData.owner.login} avatar`}
width="160"
height="160"
- onError={(e) => {
- e.currentTarget.src = `https://ui-avatars.com/api/?name=${encodeURIComponent(repoData.owner.login)}&size=160`;
- }}
style={{
position: 'absolute',
top: '80px',
Analysis
The OG image generation route uses Vercel's ImageResponse which renders JSX server-side to create images. However, the onError event handler on the img element (lines 173-175) attempts to set a fallback avatar URL when the primary avatar fails to load. This approach will not work because:
- Server-side JSX rendering in ImageResponse doesn't support JavaScript event handlers like
onError - The fallback logic will never execute, so if the primary avatar URL is broken, the OG image will show a broken image instead of the intended fallback
- This could result in malformed social media previews for repositories with invalid avatar URLs
The current code attempts to use client-side DOM manipulation in a server-side rendering context, which is a fundamental architectural mismatch.
Recommendation
Implement server-side avatar validation before rendering the ImageResponse. Pre-validate the avatar URL with a HEAD request or fetch, and if it fails, use the fallback URL directly in the src attribute instead of relying on the onError handler. For example:
// Before rendering ImageResponse
let avatarUrl = repoData.owner.avatar_url;
try {
const response = await fetch(avatarUrl, { method: 'HEAD' });
if (!response.ok) {
avatarUrl = `https://ui-avatars.com/api/?name=${encodeURIComponent(repoData.owner.login)}&size=160`;
}
} catch {
avatarUrl = `https://ui-avatars.com/api/?name=${encodeURIComponent(repoData.owner.login)}&size=160`;
}
// Then use avatarUrl in the img element without onError handler
<img src={avatarUrl} ... />
go to /homepage then cmd+k
will update the homepage code with time
Summary by CodeRabbit
New Features
Style