Skip to content

feat: add 'recently viewed' repos section to discovery page#872

Merged
Sachinchaurasiya360 merged 2 commits into
Sachinchaurasiya360:mainfrom
ThePrabhu:feat/701-recently-viewed-repos
May 31, 2026
Merged

feat: add 'recently viewed' repos section to discovery page#872
Sachinchaurasiya360 merged 2 commits into
Sachinchaurasiya360:mainfrom
ThePrabhu:feat/701-recently-viewed-repos

Conversation

@ThePrabhu

@ThePrabhu ThePrabhu commented May 31, 2026

Copy link
Copy Markdown
Contributor

Description

This PR introduces a Recently Viewed Repositories feature that helps users quickly access repositories they have recently explored.

The feature automatically tracks repositories opened from the discovery page, stores them in localStorage, and displays them in a dedicated horizontal scroll section. The list persists across page reloads, prevents duplicate entries, and maintains a maximum history of five repositories.

This enhancement improves repository discovery and provides a more personalized browsing experience.

Related Issue

Fixes #701

Type of Change

  • Bug Fix
  • Feature
  • Enhancement
  • Documentation

Testing

Manual Testing Performed

  1. Opened the Repo Discovery page.
  2. Clicked multiple repository cards.
  3. Verified that repositories appeared in the Recently Viewed section.
  4. Confirmed repositories were displayed in the correct order (most recent first).
  5. Verified duplicate repositories were not added multiple times.
  6. Refreshed the page and confirmed data persisted through localStorage.
  7. Opened repositories directly from the Recently Viewed section and verified modal functionality.
  8. Tested maximum history limit and confirmed only the latest five repositories were retained.
  9. Verified the section remains hidden when no repositories have been viewed.

Screenshots

UI screenshots demonstrating the Recently Viewed section and persistence behavior can be attached here.

Checklist

  • Code follows project guidelines
  • No new compile/type errors
  • Tested manually (include steps above)
  • No .env, credentials, or node_modules committed
  • Docs updated (if needed)
  • Screenshots added for UI changes (if applicable)

Summary by CodeRabbit

  • New Features
    • Recently viewed repositories shown in a scrollable section (persists across sessions); selecting one deep-links to and opens its detail view.
  • Bug Fixes
    • Opening/closing a repo correctly updates the URL and share state; deep-link errors now cleanly remove the invalid repo param.
    • Filter/search/sort sync improved: changing filters won't unexpectedly reset paging; trending and language selections update the URL; clearing filters resets search input.

- Implements a 'Recently Viewed' horizontal scroll section that persists across page loads using localStorage
Fixes Sachinchaurasiya360#701
Copilot AI review requested due to automatic review settings May 31, 2026 11:21
@github-actions github-actions Bot added the enhancement New feature or request label May 31, 2026
@github-actions github-actions Bot added good first issue Good for newcomers level:intermediate Requires moderate project understanding labels May 31, 2026
@github-actions

Copy link
Copy Markdown

Hi @ThePrabhu, thanks for contributing to InternHack! 🎉

I have automatically:

  • 👤 Assigned this PR to you.
  • 🏷️ Applied the gssoc:approved label.

Our workflows will now analyze your changes to classify:

  • 📈 PR Difficulty: level:*
  • 🧩 PR Type: type:*
  • 🌟 PR Quality: quality:*

Tip

Ensure your PR description references the issue it resolves (e.g. Closes #123). This allows the bot to inherit any additional labels from that issue!

Happy coding! 🚀

@github-actions github-actions Bot added gssoc:approved Approved for GSSoC scoring quality:exceptional Exceptional implementation quality type:feature New feature implementation labels May 31, 2026
@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

Failed to post review comments

📝 Walkthrough

Walkthrough

Adds a recently viewed repos feature: a localStorage-backed hook, a horizontally scrollable UI strip, and RepoDiscoveryPage wiring that records selections, deep-links the open repo via the repo URL param, and adjusts filter/search URL sync.

Changes

Recently Viewed Repositories

Layer / File(s) Summary
Recently Viewed State & Storage Hook
client/src/module/student/opensource/useRecentlyViewedRepos.ts
Custom hook initializes recent repos from localStorage on mount with try/catch error handling, exposes addRepo callback that prepends entries, deduplicates by id, truncates to max 5, and persists updates back to localStorage.
Recently Viewed Display Component
client/src/module/student/opensource/_shared/RecentlyViewedSection.tsx
New component conditionally renders a horizontally scrollable row of selectable repo buttons when list is non-empty, displaying owner/name and description with theme-aware styling.
Page Integration, URL & Filter Wiring
client/src/module/student/opensource/RepoDiscoveryPage.tsx
Page imports hook and component, calls the hook for recentlyViewed and addRepo, introduces unified handleOpenRepo to record via addRepo and set the repo URL param when opening modal, clears only the repo param on deep-link errors, inserts RecentlyViewedSection above the filter bar, and adjusts URL-backed filter/search/sort/trending/language update behavior and debounced search/page handling.

Sequence Diagram

sequenceDiagram
  participant User
  participant RepoCard
  participant RepoDiscoveryPage
  participant Hook as useRecentlyViewedRepos:addRepo
  participant Storage as localStorage
  participant Modal as Detail Modal
  User->>RepoCard: click repo
  RepoCard->>RepoDiscoveryPage: onSelect(repo)
  RepoDiscoveryPage->>RepoDiscoveryPage: handleOpenRepo(repo)
  RepoDiscoveryPage->>Hook: addRepo(repo)
  Hook->>Storage: persist updated list
  Storage-->>Hook: write complete
  RepoDiscoveryPage->>RepoDiscoveryPage: set repo URL param
  RepoDiscoveryPage->>Modal: setSelectedRepo(repo)
  Modal-->>User: show detail
  RepoDiscoveryPage-->>User: RecentlyViewedSection updated
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly Related PRs

Suggested Reviewers

  • Sachinchaurasiya360

Poem

🐰 I hopped through code and left a trail,

Five tidy chips along the trail,
Click one, the modal blooms anew,
Saved in storage, fresh for you,
A little rabbit's memory, hopping true.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main feature added: a 'recently viewed' repos section integrated into the discovery page.
Description check ✅ Passed The PR description is comprehensive, covering all template sections with detailed testing steps and clear explanations of the feature functionality.
Linked Issues check ✅ Passed The implementation fully satisfies issue #701 requirements: localStorage persistence (oss_recently_viewed), 5-entry limit, most-recent-first ordering, deduplication, full repo object storage, and visual chip display.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the recently viewed feature; adjustments to filter/sort URL synchronization and deep-linking are supporting implementations required for the feature.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with 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.

❤️ Share

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

Copilot AI 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.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds “recently viewed repositories” to the student open source repo discovery experience, persisting selections in localStorage and rendering a new UI section.

Changes:

  • Introduces a useRecentlyViewedRepos hook that loads/saves recently viewed repos to localStorage.
  • Adds a RecentlyViewedSection component to display the stored repos.
  • Wires repo selection in RepoDiscoveryPage to record views (partially).

Reviewed changes

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

File Description
client/src/module/student/opensource/useRecentlyViewedRepos.ts New hook for reading/writing recently viewed repos in localStorage.
client/src/module/student/opensource/_shared/RecentlyViewedSection.tsx New UI component to render the “Recently Viewed” horizontal list.
client/src/module/student/opensource/RepoDiscoveryPage.tsx Integrates the hook + section into the discovery page and updates selection handling.

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

Comment on lines +240 to +241
{/* Recently Viewed */}
<RecentlyViewedSection repos={recentlyViewed} onSelect={setSelectedRepo} />
Comment on lines +21 to +31
const addRepo = useCallback((repo: OpenSourceRepo) => {
setRecentlyViewed((prev) => {
const newRecentlyViewed = [repo, ...prev.filter((r) => r.id !== repo.id)].slice(0, MAX_RECENTLY_VIEWED);
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(newRecentlyViewed));
} catch (error) {
console.error("Failed to save recently viewed repos to localStorage", error);
}
return newRecentlyViewed;
});
}, []);
@@ -0,0 +1,44 @@
import { ChevronRight } from "lucide-react";
@ThePrabhu

Copy link
Copy Markdown
Contributor Author

@Sachinchaurasiya360 , Review the code

@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

🧹 Nitpick comments (2)
client/src/module/student/opensource/_shared/RecentlyViewedSection.tsx (2)

40-40: ⚡ Quick win

Use bg-linear-to-l instead of bg-gradient-to-l.

Coding guidelines require the v4 bg-linear-* form over the bg-gradient-* shorthand.

♻️ Proposed fix
-        <div className="absolute right-0 top-0 bottom-2 w-8 bg-gradient-to-l from-stone-50 dark:from-stone-950 to-transparent pointer-events-none" />
+        <div className="absolute right-0 top-0 bottom-2 w-8 bg-linear-to-l from-stone-50 dark:from-stone-950 to-transparent pointer-events-none" />
As per coding guidelines: "Use `bg-linear-to-*` instead of `bg-gradient-*` shorthand in TailwindCSS".
🤖 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 `@client/src/module/student/opensource/_shared/RecentlyViewedSection.tsx` at
line 40, In RecentlyViewedSection replace the Tailwind gradient utility on the
overflow-fade div by using the v4 form: change the className token
"bg-gradient-to-l" to "bg-linear-to-l" so the element (the div with classes
"absolute right-0 top-0 bottom-2 w-8 ... pointer-events-none") uses the v4
bg-linear-* utility; ensure no other classes are altered and run the build to
verify Tailwind picks up the updated utility.

1-1: ⚡ Quick win

Remove unused ChevronRight import.

It's imported but never used in the JSX, which will fail the build under noUnusedLocals/lint.

♻️ Proposed fix
-import { ChevronRight } from "lucide-react";
 import type { OpenSourceRepo } from "../../../lib/types";
🤖 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 `@client/src/module/student/opensource/_shared/RecentlyViewedSection.tsx` at
line 1, Remove the unused import ChevronRight from RecentlyViewedSection.tsx:
locate the import statement importing ChevronRight and delete it (or replace it
with any actually used icon import) so the module no longer contains an unused
local; ensure no other references to ChevronRight remain in the file (e.g., JSX
or helpers) before committing.
🤖 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 `@client/src/module/student/opensource/_shared/RecentlyViewedSection.tsx`:
- Line 29: In RecentlyViewedSection.tsx update the Tailwind class on the element
that currently uses "flex-shrink-0" (the className string on the container in
the RecentlyViewedSection component) to the canonical v4 utility "shrink-0" so
it works with Tailwind v4; simply replace "flex-shrink-0" with "shrink-0" in
that className.

In `@client/src/module/student/opensource/RepoDiscoveryPage.tsx`:
- Line 241: The RecentlyViewedSection is wired to call setSelectedRepo directly,
which opens the modal but bypasses addRepo and therefore doesn't update recency;
change the prop to use the existing handler handleSelectRepo (the same function
used by the repo cards) so selection funnels through addRepo and reorders the
recentlyViewed list—locate the RecentlyViewedSection usage and replace
onSelect={setSelectedRepo} with onSelect={handleSelectRepo}, ensuring
handleSelectRepo remains responsible for calling addRepo and setting selected
repo.

In `@client/src/module/student/opensource/useRecentlyViewedRepos.ts`:
- Around line 12-15: The code reads STORAGE_KEY from localStorage and calls
setRecentlyViewed(JSON.parse(stored)) without verifying the parsed value is an
array, which can cause RecentlyViewedSection to crash if storage contains
null/object/number; update the initialization in useRecentlyViewedRepos so after
parsing you assert Array.isArray(parsed) (and optionally that items match
expected repo-shape) before calling setRecentlyViewed, otherwise ignore the
value or set an empty array and remove or overwrite the bad STORAGE_KEY; refer
to the STORAGE_KEY constant, the setRecentlyViewed setter, and the
RecentlyViewedSection consumer when making this change.

---

Nitpick comments:
In `@client/src/module/student/opensource/_shared/RecentlyViewedSection.tsx`:
- Line 40: In RecentlyViewedSection replace the Tailwind gradient utility on the
overflow-fade div by using the v4 form: change the className token
"bg-gradient-to-l" to "bg-linear-to-l" so the element (the div with classes
"absolute right-0 top-0 bottom-2 w-8 ... pointer-events-none") uses the v4
bg-linear-* utility; ensure no other classes are altered and run the build to
verify Tailwind picks up the updated utility.
- Line 1: Remove the unused import ChevronRight from RecentlyViewedSection.tsx:
locate the import statement importing ChevronRight and delete it (or replace it
with any actually used icon import) so the module no longer contains an unused
local; ensure no other references to ChevronRight remain in the file (e.g., JSX
or helpers) before committing.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro

Run ID: e034a216-c8b5-45d3-9659-a2b214966a4c

📥 Commits

Reviewing files that changed from the base of the PR and between 9e7662b and efa0a1c.

📒 Files selected for processing (3)
  • client/src/module/student/opensource/RepoDiscoveryPage.tsx
  • client/src/module/student/opensource/_shared/RecentlyViewedSection.tsx
  • client/src/module/student/opensource/useRecentlyViewedRepos.ts

key={repo.id}
type="button"
onClick={() => onSelect(repo)}
className="flex-shrink-0 w-48 text-left p-3 rounded-md bg-white dark:bg-stone-900 border border-stone-200 dark:border-white/10 hover:border-stone-400 dark:hover:border-white/25 transition-colors"

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In Tailwind CSS v4, is flex-shrink-0 deprecated in favor of shrink-0?

💡 Result:

Yes, in Tailwind CSS v4, the class flex-shrink-0 has been removed and is deprecated in favor of shrink-0 [1]. As part of the cleanup for the v4 major release, Tailwind CSS removed several utility aliases that had been deprecated for some time [1]. Specifically, the flex-shrink-* family of utilities was replaced by the shorter, canonical shrink-* naming convention [2][1]. To update your project, it is recommended to use the official Tailwind CSS upgrade tool, which automatically handles the renaming of these legacy classes [2][1][3]: npx @tailwindcss/upgrade This tool will scan your codebase and replace instances of flex-shrink-0 with shrink-0, along with other similar renames (such as flex-grow-* to grow-*) [4][2][1].

Citations:


Replace flex-shrink-0 with canonical shrink-0 (Tailwind v4)
Tailwind v4 removed the flex-shrink-* aliases; use shrink-0 instead.

♻️ Proposed fix
-              className="flex-shrink-0 w-48 text-left p-3 rounded-md bg-white dark:bg-stone-900 border border-stone-200 dark:border-white/10 hover:border-stone-400 dark:hover:border-white/25 transition-colors"
+              className="shrink-0 w-48 text-left p-3 rounded-md bg-white dark:bg-stone-900 border border-stone-200 dark:border-white/10 hover:border-stone-400 dark:hover:border-white/25 transition-colors"
📝 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
className="flex-shrink-0 w-48 text-left p-3 rounded-md bg-white dark:bg-stone-900 border border-stone-200 dark:border-white/10 hover:border-stone-400 dark:hover:border-white/25 transition-colors"
className="shrink-0 w-48 text-left p-3 rounded-md bg-white dark:bg-stone-900 border border-stone-200 dark:border-white/10 hover:border-stone-400 dark:hover:border-white/25 transition-colors"
🤖 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 `@client/src/module/student/opensource/_shared/RecentlyViewedSection.tsx` at
line 29, In RecentlyViewedSection.tsx update the Tailwind class on the element
that currently uses "flex-shrink-0" (the className string on the container in
the RecentlyViewedSection component) to the canonical v4 utility "shrink-0" so
it works with Tailwind v4; simply replace "flex-shrink-0" with "shrink-0" in
that className.

Comment thread client/src/module/student/opensource/RepoDiscoveryPage.tsx Outdated
Comment on lines +12 to +15
const stored = localStorage.getItem(STORAGE_KEY);
if (stored) {
setRecentlyViewed(JSON.parse(stored));
}

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Validate that parsed storage value is an array.

JSON.parse succeeds for valid-but-wrong-shape JSON (e.g. "null", "{}", "5"), so a corrupted oss_recently_viewed entry would set recentlyViewed to a non-array. RecentlyViewedSection then runs repos.length === 0 / repos.map(...) on a non-array and throws at render. The try/catch only guards parse syntax errors.

🛡️ Proposed guard
       const stored = localStorage.getItem(STORAGE_KEY);
       if (stored) {
-        setRecentlyViewed(JSON.parse(stored));
+        const parsed = JSON.parse(stored);
+        if (Array.isArray(parsed)) {
+          setRecentlyViewed(parsed);
+        }
       }
📝 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
const stored = localStorage.getItem(STORAGE_KEY);
if (stored) {
setRecentlyViewed(JSON.parse(stored));
}
const stored = localStorage.getItem(STORAGE_KEY);
if (stored) {
const parsed = JSON.parse(stored);
if (Array.isArray(parsed)) {
setRecentlyViewed(parsed);
}
}
🤖 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 `@client/src/module/student/opensource/useRecentlyViewedRepos.ts` around lines
12 - 15, The code reads STORAGE_KEY from localStorage and calls
setRecentlyViewed(JSON.parse(stored)) without verifying the parsed value is an
array, which can cause RecentlyViewedSection to crash if storage contains
null/object/number; update the initialization in useRecentlyViewedRepos so after
parsing you assert Array.isArray(parsed) (and optionally that items match
expected repo-shape) before calling setRecentlyViewed, otherwise ignore the
value or set an empty array and remove or overwrite the bad STORAGE_KEY; refer
to the STORAGE_KEY constant, the setRecentlyViewed setter, and the
RecentlyViewedSection consumer when making this change.

@Sachinchaurasiya360 Sachinchaurasiya360 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Clean implementation. The useRecentlyViewedRepos hook correctly deduplicates, caps at 5, and handles localStorage errors gracefully. The RecentlyViewedSection has a proper early-return guard and integrates well with the existing deep-link and recommendation sections.

One item to verify: RecentlyViewedSection.tsx lives in _shared/ and imports type { OpenSourceRepo } from '../../../lib/types'. From that subdirectory, three ../ steps only reach client/src/module/ — the correct path should be ../../../../lib/types. If TypeScript resolves this via a path alias, that is fine; otherwise please correct the import path.

Approving and merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request good first issue Good for newcomers gssoc:approved Approved for GSSoC scoring level:intermediate Requires moderate project understanding quality:exceptional Exceptional implementation quality type:feature New feature implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add "recently viewed" repos section to RepoDiscoveryPage

3 participants