Skip to content

feat: Similar Profiles suggestions - #825

Merged
PRODHOSH merged 1 commit into
PRODHOSH:mainfrom
Aditya8369:feat/Similar-Profiles
Aug 6, 2026
Merged

feat: Similar Profiles suggestions#825
PRODHOSH merged 1 commit into
PRODHOSH:mainfrom
Aditya8369:feat/Similar-Profiles

Conversation

@Aditya8369

@Aditya8369 Aditya8369 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Related Issue

Closes #730

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Refactor
  • Chore / dependency update

Changes Made

Checklist

  • I was assigned to the issue before opening this PR
  • My branch is up to date with main
  • Code works locally and I have tested it
  • No console.log left in src/
  • If schema changed — both schema.sql and a new migration file are included
  • If this is a UI change — I read DESIGN.md and followed the design system (colors, spacing, typography, components)
  • Docs updated if needed
  • PR title follows Conventional Commits format (feat:, fix:, docs:, etc.)
  • This PR description is written in my own words

Summary by CodeRabbit

  • New Features
    • Added a “Similar Profiles” section to profile pages.
    • Displays recommended public profiles with avatars, names, usernames, similarity scores, languages, and shared interests.
    • Added horizontally scrollable profile cards with loading placeholders and profile navigation.
    • Recommendations are ranked using shared programming languages and organizations.
  • Style
    • Added hover effects to similar-profile cards for clearer interaction feedback.

@Aditya8369
Aditya8369 requested a review from PRODHOSH as a code owner August 6, 2026 11:02
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Welcome to OSSfolio, @Aditya8369! 🎉

Thank you for opening this pull request and contributing to the open-source community! 🚀

To ensure a smooth review process, please make sure you have:

  • Checked that your changes work locally and compile cleanly.
  • Followed the guidelines outlined in CONTRIBUTING.md.
  • Linked your PR to an open issue (e.g. Closes #ISSUE_NUMBER).

We will review your PR as soon as possible. Happy coding! 💻✨

@github-actions github-actions Bot added frontend Related to UI / Next.js backend API / Database / Server UI Visual / design changes labels Aug 6, 2026
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds similar-profile suggestions to profile pages. A Supabase RPC ranks public profiles by shared languages and organizations. A cached API route exposes the results. A lazy client component renders loading states, profile cards, match reasons, and empty results.

Changes

Similar profile suggestions

Layer / File(s) Summary
Similarity RPC and result contract
supabase/migrations/..., src/lib/db.ts
Adds the SimilarProfile type and find_similar_profiles RPC. The RPC filters public profiles, calculates weighted overlaps, ranks matches, and limits results to six.
Database access and API response
src/lib/db.ts, src/app/api/similar-profiles/[username]/route.ts
Adds typed RPC access and a validated GET route. Errors and invalid data return empty lists. Successful responses use CDN caching headers.
Profile-page loading and display
src/components/profile/SimilarProfiles.tsx, src/components/profile/ProfileView.tsx, src/app/globals.css
Adds lazy loading, skeletons, empty handling, horizontally scrollable profile cards, match details, navigation links, and hover styling.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ProfileView
  participant SimilarProfiles
  participant API
  participant Database
  ProfileView->>SimilarProfiles: pass username and score
  SimilarProfiles->>API: fetch similar profiles
  API->>Database: invoke find_similar_profiles
  Database-->>API: return ranked public profiles
  API-->>SimilarProfiles: return cached JSON
  SimilarProfiles-->>ProfileView: render suggestion cards
Loading

Possibly related PRs

  • PRODHOSH/ossfolio#212: Adds related profile discovery functionality and shared profile-search data structures.
  • PRODHOSH/ossfolio#471: Introduces shared database-layer and profile-view changes used by this implementation.

Suggested labels: enhancement, ELUSOC, completed, VETERAN

Suggested reviewers: prodhosh, sakethsumanbathini

Poem

I’m a rabbit with profiles to share,
Finding kindred code everywhere.
Languages meet, organizations align,
Six little cards in a scrolling line.
Hop through the network—connections grow! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the Similar Profiles feature added by the pull request.
Linked Issues check ✅ Passed The changes implement the requested RPC, public-profile filtering, similarity ranking, profile-page section, and profile suggestions described in issue #730.
Out of Scope Changes check ✅ Passed The API route, database function, UI component, profile integration, and styling directly support issue #730.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Biome (2.5.6)
src/app/globals.css

File contains syntax errors that prevent linting: Line 6: Tailwind-specific syntax is disabled.; Line 224: Tailwind-specific syntax is disabled.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/profile/SimilarProfiles.tsx`:
- Around line 44-60: Update the skeleton elements in SimilarProfiles by
replacing each inline borderRadius value of "6px" with the design token
var(--radius-sm), including both changed blocks.
- Around line 297-323: Update the useEffect tied to username changes to clear
the existing profiles and setIsLoading(true) before starting load(), ensuring
the new request cannot display stale suggestions. Preserve the existing
cancellation and completion handling for the refreshed request.

In `@supabase/migrations/20260806000000_add_find_similar_profiles.sql`:
- Around line 58-73: Update the target organization extraction that populates
v_target_orgs and the candidate query grouped by ps_cand.snapshot to use only
the latest profile_snapshot for each username before expanding orgs or
calculating matches. Ensure each candidate username is represented by at most
one latest snapshot so obsolete organizations are excluded and duplicate
usernames cannot consume the six-result limit.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 04b4ad56-a5e8-4a10-89e8-ede65dec770f

📥 Commits

Reviewing files that changed from the base of the PR and between 87724b8 and ef2697e.

📒 Files selected for processing (6)
  • src/app/api/similar-profiles/[username]/route.ts
  • src/app/globals.css
  • src/components/profile/ProfileView.tsx
  • src/components/profile/SimilarProfiles.tsx
  • src/lib/db.ts
  • supabase/migrations/20260806000000_add_find_similar_profiles.sql

Comment on lines +44 to +60
<div
style={{
height: "14px",
width: "80%",
borderRadius: "6px",
backgroundColor: "var(--color-hairline)",
animation: "pulse 1.5s ease-in-out infinite",
}}
/>
<div
style={{
height: "11px",
width: "55%",
borderRadius: "6px",
backgroundColor: "var(--color-hairline)",
animation: "pulse 1.5s ease-in-out infinite",
}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use the radius token for the skeleton elements.

Replace each changed borderRadius: "6px" value with var(--radius-sm).

Based on learnings, inline borderRadius: "6px" values must use var(--radius-sm) during the design-token migration.

Also applies to: 340-346

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/profile/SimilarProfiles.tsx` around lines 44 - 60, Update the
skeleton elements in SimilarProfiles by replacing each inline borderRadius value
of "6px" with the design token var(--radius-sm), including both changed blocks.

Source: Learnings

Comment on lines +297 to +323
useEffect(() => {
let cancelled = false;

async function load() {
try {
const res = await fetch(`/api/similar-profiles/${username}`);
if (cancelled) return;
if (!res.ok) {
setIsLoading(false);
return;
}
const json = await res.json();
if (!cancelled && Array.isArray(json.profiles)) {
setProfiles(json.profiles);
}
} catch {
// Silent fail — the section simply won't appear.
} finally {
if (!cancelled) setIsLoading(false);
}
}

load();
return () => {
cancelled = true;
};
}, [username]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reset result state when username changes.

The effect starts a new request without clearing profiles or restoring isLoading. During that request, the new profile can display suggestions for the previous username. If the request fails, those stale suggestions remain visible.

Proposed fix
   useEffect(() => {
     let cancelled = false;
+    setProfiles([]);
+    setIsLoading(true);

     async function load() {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
let cancelled = false;
async function load() {
try {
const res = await fetch(`/api/similar-profiles/${username}`);
if (cancelled) return;
if (!res.ok) {
setIsLoading(false);
return;
}
const json = await res.json();
if (!cancelled && Array.isArray(json.profiles)) {
setProfiles(json.profiles);
}
} catch {
// Silent fail — the section simply won't appear.
} finally {
if (!cancelled) setIsLoading(false);
}
}
load();
return () => {
cancelled = true;
};
}, [username]);
useEffect(() => {
let cancelled = false;
setProfiles([]);
setIsLoading(true);
async function load() {
try {
const res = await fetch(`/api/similar-profiles/${username}`);
if (cancelled) return;
if (!res.ok) {
setIsLoading(false);
return;
}
const json = await res.json();
if (!cancelled && Array.isArray(json.profiles)) {
setProfiles(json.profiles);
}
} catch {
// Silent fail — the section simply won't appear.
} finally {
if (!cancelled) setIsLoading(false);
}
}
load();
return () => {
cancelled = true;
};
}, [username]);
🧰 Tools
🪛 React Doctor (0.9.3)

[error] 297-297: This setter runs after await, so overlapping re-runs of the effect can resolve out of order and write stale state; gate it behind a cancellation/ignore flag or return a cleanup that cancels the work.

In a useEffect whose dependencies can change, guard any setter call that runs after an await behind a cancellation/ignore flag, or return a cleanup that cancels the async work.

(no-set-state-after-await-in-effect)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/profile/SimilarProfiles.tsx` around lines 297 - 323, Update
the useEffect tied to username changes to clear the existing profiles and
setIsLoading(true) before starting load(), ensuring the new request cannot
display stale suggestions. Preserve the existing cancellation and completion
handling for the refreshed request.

Comment on lines +58 to +73
select coalesce(
array(
select lower(org_elem->>'login')
from public.profile_snapshots ps,
jsonb_array_elements(
case
when jsonb_typeof(ps.snapshot->'orgs') = 'array'
then ps.snapshot->'orgs'
else '[]'::jsonb
end
) as org_elem
where ps.username = p_username
and (org_elem->>'login') is not null
),
'{}'::text[]
) into v_target_orgs;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Read only the latest snapshot for each profile.

Lines 58-73 aggregate organizations from every target snapshot. Lines 140-185 join every candidate snapshot and group by ps_cand.snapshot.

This violates the latest-profile_snapshot contract. It can score obsolete organizations and return the same username more than once, which can consume the six-result limit.

Select one latest snapshot for the target and one latest snapshot per candidate before expanding orgs.

Also applies to: 140-185

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/migrations/20260806000000_add_find_similar_profiles.sql` around
lines 58 - 73, Update the target organization extraction that populates
v_target_orgs and the candidate query grouped by ps_cand.snapshot to use only
the latest profile_snapshot for each username before expanding orgs or
calculating matches. Ensure each candidate username is represented by at most
one latest snapshot so obsolete organizations are excluded and duplicate
usernames cannot consume the six-result limit.

@PRODHOSH PRODHOSH added ELUSOC ELUSOC project submission completed VETERAN Advanced 50 pts labels Aug 6, 2026
@PRODHOSH
PRODHOSH merged commit 8219bbc into PRODHOSH:main Aug 6, 2026
10 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend API / Database / Server completed ELUSOC ELUSOC project submission frontend Related to UI / Next.js UI Visual / design changes VETERAN Advanced 50 pts

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"Similar Profiles" Suggestions

2 participants