Skip to content

feat: implement loading context and skeleton components for improved …#78

Open
anish27863 wants to merge 7 commits into
kunalverma2512:mainfrom
anish27863:main
Open

feat: implement loading context and skeleton components for improved …#78
anish27863 wants to merge 7 commits into
kunalverma2512:mainfrom
anish27863:main

Conversation

@anish27863
Copy link
Copy Markdown

@anish27863 anish27863 commented May 18, 2026

Navigation UX Fix Summary

I improved route navigation feedback across the frontend by adding:

  • A global loading overlay powered by React Context, shown during route changes.
  • A fade-in route transition wrapper so page switches feel smooth instead of abrupt.
  • Skeleton loaders for major pages: Dashboard, Account Center (Profile), and Explore.
  • Layout-stable placeholders using animate-pulse to reduce visual jumps while loading.

All new UI follows the existing responsive brutalist black-and-white style (no rounded or colorful elements).

Summary by CodeRabbit

  • New Features

    • Added animated skeleton loading screens for Dashboard and Account Center pages during data fetching.
    • Implemented smooth fade-in page transitions for a more polished navigation experience.
  • Visual Improvements

    • Enhanced loading state indicators with improved placeholder layouts across authenticated sections.

Review Change Stack

@github-actions
Copy link
Copy Markdown

🚀 PR Received Successfully

Hello @anish27863,

Thank you for taking the initiative to contribute to this project.

Please ensure that your PR follows all project guidelines properly before requesting review.

⚠️ Important Instructions

  • Maintain proper code quality and structure
  • Do not make unnecessary changes/files
  • Ensure responsiveness across devices
  • Follow existing project conventions strictly
  • Attach screenshots/videos for UI-related changes
  • Resolve merge conflicts before requesting review
  • Avoid AI-generated low quality PRs or copied implementations

📌 Mandatory for GSSoC'26 Participants

Joining the community group and announcement channel is compulsory for all contributors participating through GSSoC'26.

Failure to follow contribution guidelines may lead to PR rejection.

We appreciate your effort and wish you a great open-source journey ahead. ✨

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

Warning

Rate limit exceeded

@anish27863 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 26 minutes and 1 second before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3204da02-1992-4285-b078-c957ceb9cd24

📥 Commits

Reviewing files that changed from the base of the PR and between db4d42f and 785da02.

📒 Files selected for processing (17)
  • frontend/src/App.jsx
  • frontend/src/components/codeforces/ConnectBanner.jsx
  • frontend/src/components/dashboard/DashboardExecutiveSummary.jsx
  • frontend/src/components/github/GitHubComponents.jsx
  • frontend/src/components/shared/Navbar.jsx
  • frontend/src/components/shared/ProtectedRoute.jsx
  • frontend/src/components/shared/PublicRoute.jsx
  • frontend/src/components/shared/skeletons/PageSkeletons.jsx
  • frontend/src/context/AuthContext.jsx
  • frontend/src/pages/AccountCenterPage.jsx
  • frontend/src/pages/CodeforcesPage.jsx
  • frontend/src/pages/GitHubCallbackPage.jsx
  • frontend/src/pages/GitHubIntelligencePage.jsx
  • frontend/src/pages/LoginPage.jsx
  • frontend/src/pages/SignupPage.jsx
  • frontend/src/utils/githubHelpers.js
  • server/server.js
📝 Walkthrough

Walkthrough

This PR refactors loading state handling across the frontend by introducing page fade-in animations, shared skeleton placeholder components, and per-page loading UI while simplifying route guards. The backend server startup also disables database connection initialization.

Changes

Page Fade-in Animations and Loading State Refactor

Layer / File(s) Summary
Page Fade-in Animation and App Routing Refactor
frontend/src/index.css, frontend/src/App.jsx
Adds CSS page-fade-in animation (260ms opacity/transform). Refactors App.jsx to extract routes into AppRoutes component that uses useLocation() and keys a wrapper div by location.key, re-triggering fade-in on navigation while preserving route structure.
Shared Page Skeleton Components
frontend/src/components/shared/skeletons/PageSkeletons.jsx
Introduces SkeletonBlock helper and exports DashboardPageSkeleton (header, multi-column grid, bottom bar) and AccountCenterSkeleton (bordered header, black-themed profile area, responsive grid) as reusable loading placeholders.
Route Guard Simplification
frontend/src/components/shared/ProtectedRoute.jsx, frontend/src/components/shared/PublicRoute.jsx
ProtectedRoute and PublicRoute now return null during auth loading instead of showing inline Loader components. Route protection and redirect logic unchanged.
Page-Level Skeleton Integration
frontend/src/pages/DashboardPage.jsx, frontend/src/pages/AccountCenterPage.jsx, frontend/src/pages/ExplorePage.jsx
DashboardPage renders DashboardPageSkeleton during loading and updates Codeforces widget to use animate-pulse skeleton card. AccountCenterPage renders AccountCenterSkeleton when authLoading or user unavailable. ExplorePage whitespace cleaned.
Server Startup Configuration
server/server.js
Database connection call commented out, preventing DB connection during server startup.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • kunalverma2512/CodeLens#72: Directly related route guard changes in ProtectedRoute.jsx and PublicRoute.jsx; this PR removes inline loaders while the prior PR introduced them.

Suggested labels

enhancement, Frontend, GSSoC26, responsive, type:feature, type:refactor, level:intermediate, quality:clean, type:accessibility, gssoc:approved

Poem

🐰 The routes now fade with grace and style,
Skeletons dance while pages compile,
No loaders block the guardian's way,
Just placeholders gleaming—hip, hip, hooray!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is truncated and incomplete ('…'), making it unclear what specific improvement the PR addresses. Provide the complete PR title. It should clearly state the main feature or improvement (e.g., 'feat: add skeleton loading components and route fade-in transitions').
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (2)
frontend/src/components/shared/skeletons/PageSkeletons.jsx (1)

33-41: ⚡ Quick win

Prefer SkeletonBlock for consistent skeleton styling.

Lines 35, 37-38 manually replicate skeleton styling instead of using the SkeletonBlock helper. For maintainability, consider using SkeletonBlock with custom classes or extracting these as a variant.

♻️ Suggested refactor
         <div className="mb-12 p-6 border-[4px] border-black bg-black">
           <div className="flex items-center gap-5">
-            <div className="w-16 h-16 border-[3px] border-white bg-gray-300 animate-pulse" />
+            <SkeletonBlock className="w-16 h-16 border-[3px] border-white bg-gray-300" />
             <div className="w-full">
-              <div className="h-7 w-60 bg-gray-300 border-[2px] border-white animate-pulse mb-2" />
-              <div className="h-4 w-72 bg-gray-300 border-[2px] border-white animate-pulse" />
+              <SkeletonBlock className="h-7 w-60 bg-gray-300 border-[2px] border-white mb-2" />
+              <SkeletonBlock className="h-4 w-72 bg-gray-300 border-[2px] border-white" />
             </div>
           </div>
         </div>

Note: SkeletonBlock already includes animate-pulse, so it can be removed from the custom classes.

🤖 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 `@frontend/src/components/shared/skeletons/PageSkeletons.jsx` around lines 33 -
41, Replace the manually styled skeleton divs in the PageSkeletons component
with the shared SkeletonBlock helper: swap the avatar div (w-16 h-16
border-[3px] border-white bg-gray-300 animate-pulse) for <SkeletonBlock
className="w-16 h-16 border-[3px] border-white bg-gray-300" /> and replace the
two text bars (h-7 w-60 ... and h-4 w-72 ...) with <SkeletonBlock className="h-7
w-60 border-[2px] border-white mb-2 bg-gray-300" /> and <SkeletonBlock
className="h-4 w-72 border-[2px] border-white bg-gray-300" /> respectively;
remove the explicit animate-pulse classes because SkeletonBlock already provides
the animation and adjust import/usage of SkeletonBlock in PageSkeletons.jsx
accordingly.
frontend/src/components/shared/GlobalLoadingOverlay.jsx (1)

7-10: ⚡ Quick win

Add live loading semantics for assistive technologies.

The overlay is visually clear, but it doesn’t announce loading state to screen readers. Add status semantics and hide the decorative spinner.

Proposed patch
-    <div className="fixed inset-0 z-[80] bg-white/85 flex items-center justify-center">
+    <div
+      role="status"
+      aria-live="polite"
+      aria-busy="true"
+      className="fixed inset-0 z-[80] bg-white/85 flex items-center justify-center"
+    >
       <div className="flex flex-col items-center gap-4">
-        <div className="w-12 h-12 border-[4px] border-black border-t-transparent animate-spin" />
+        <div aria-hidden="true" className="w-12 h-12 border-[4px] border-black border-t-transparent animate-spin" />
         <p className="text-xs font-black uppercase tracking-[0.22em] text-black">Loading</p>
       </div>
     </div>
🤖 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 `@frontend/src/components/shared/GlobalLoadingOverlay.jsx` around lines 7 - 10,
The overlay lacks screen-reader semantics — add a live status and hide the
decorative spinner: give the loading text element (the <p>Loading</p>)
role="status" and aria-live="polite" (or aria-live="assertive" if needed for
urgency) so assistive tech announces the state, and mark the decorative spinner
div with aria-hidden="true" to prevent it from being read; keep the visible text
for sighted users but ensure the status attributes are applied on the element
rendering "Loading" in GlobalLoadingOverlay.jsx.
🤖 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 `@frontend/src/components/shared/RouteFrame.jsx`:
- Around line 10-19: The loading effect in RouteFrame.jsx only depends on
location.pathname so same-path navigations that change query/hash don't trigger
the loading overlay; update the useEffect dependency to include the router
location key (or include location.search and location.hash) so the effect runs
for those navigations, i.e. change the dependency array referenced in the
useEffect that uses firstRender.current and setLoading to include location.key
(or location.search and location.hash) so the timer logic and clearing (timer,
setLoading, firstRender) run on query/hash changes as well.

In `@frontend/src/pages/AccountCenterPage.jsx`:
- Line 334: The component AccountCenterPage currently uses an artificial 320ms
delay via setTimeout to set pageReady (state variable) which unnecessarily slows
rendering; remove the timeout and instead setPageReady(true) immediately when
authLoading is false and user is present (or implement a true minimum-time
pattern only if there was an actual prior loading phase). Locate the
useEffect(s) referencing pageReady/setPageReady and authLoading/user and replace
the setTimeout-based logic with an immediate state update (or conditional
minimum-time logic) so the UI renders as soon as authentication data is ready.

In `@frontend/src/pages/DashboardPage.jsx`:
- Line 14: Remove the artificial 320ms delay by deleting the setTimeout that
sets pageReady and instead set pageReady directly when loading becomes false;
update the DashboardPage component (references: pageReady, setPageReady,
loading) so that once loading is false you call setPageReady(true) immediately
(or derive readiness directly from loading) and remove the timeout logic; if
skeleton flashing must be addressed, implement it in the data-fetching layer or
use a minimal debounce/conditional render there rather than a hardcoded timeout
in the component.

In `@frontend/src/pages/ExplorePage.jsx`:
- Line 18: The artificial 360ms boot delay should be removed: change the initial
state for isBootLoading to false (useState(false)) and delete the
useEffect/setTimeout block that sets isBootLoading after 360ms (remove any
references to the 360ms timer), or if you must keep parity with other pages
replace the hardcoded timeout with the same behavior used in
Dashboard/AccountCenter; update usages of isBootLoading/setIsBootLoading
accordingly so ExplorePage renders immediately with no artificial delay.

---

Nitpick comments:
In `@frontend/src/components/shared/GlobalLoadingOverlay.jsx`:
- Around line 7-10: The overlay lacks screen-reader semantics — add a live
status and hide the decorative spinner: give the loading text element (the
<p>Loading</p>) role="status" and aria-live="polite" (or aria-live="assertive"
if needed for urgency) so assistive tech announces the state, and mark the
decorative spinner div with aria-hidden="true" to prevent it from being read;
keep the visible text for sighted users but ensure the status attributes are
applied on the element rendering "Loading" in GlobalLoadingOverlay.jsx.

In `@frontend/src/components/shared/skeletons/PageSkeletons.jsx`:
- Around line 33-41: Replace the manually styled skeleton divs in the
PageSkeletons component with the shared SkeletonBlock helper: swap the avatar
div (w-16 h-16 border-[3px] border-white bg-gray-300 animate-pulse) for
<SkeletonBlock className="w-16 h-16 border-[3px] border-white bg-gray-300" />
and replace the two text bars (h-7 w-60 ... and h-4 w-72 ...) with
<SkeletonBlock className="h-7 w-60 border-[2px] border-white mb-2 bg-gray-300"
/> and <SkeletonBlock className="h-4 w-72 border-[2px] border-white bg-gray-300"
/> respectively; remove the explicit animate-pulse classes because SkeletonBlock
already provides the animation and adjust import/usage of SkeletonBlock in
PageSkeletons.jsx accordingly.
🪄 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: ca7c39a3-b007-4137-ad08-879e3e52f49f

📥 Commits

Reviewing files that changed from the base of the PR and between d2f35e0 and f6125cc.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • frontend/src/App.jsx
  • frontend/src/components/shared/GlobalLoadingOverlay.jsx
  • frontend/src/components/shared/RouteFrame.jsx
  • frontend/src/components/shared/skeletons/PageSkeletons.jsx
  • frontend/src/context/LoadingContext.jsx
  • frontend/src/index.css
  • frontend/src/pages/AccountCenterPage.jsx
  • frontend/src/pages/DashboardPage.jsx
  • frontend/src/pages/ExplorePage.jsx

Comment thread frontend/src/components/shared/RouteFrame.jsx Outdated
Comment thread frontend/src/pages/AccountCenterPage.jsx Outdated
Comment thread frontend/src/pages/DashboardPage.jsx Outdated
Comment thread frontend/src/pages/ExplorePage.jsx Outdated
@anish27863
Copy link
Copy Markdown
Author

please consider this for my gssoc26 contribution

@kunalverma2512
Copy link
Copy Markdown
Owner

@anish27863 provide a video for your work and showing those changes in interface

@anish27863
Copy link
Copy Markdown
Author

Screen.Recording.2026-05-20.153405.mp4

@kunalverma2512 please checkout this Ui demo

@kunalverma2512
Copy link
Copy Markdown
Owner

@coderabbitai Please provide a complete and detailed review of this PR.

Specifically review:

  • What this PR actually changes in the project architecture and user experience
  • Whether the loading context implementation is properly designed and justified
  • What optimizations or improvements were introduced compared to the previous implementation
  • Whether the skeleton loaders and route transition system are implemented efficiently and without unnecessary complexity
  • Any potential performance, maintainability, scalability, or UX concerns
  • Whether the contribution is meaningful and valid for the project, or if parts feel redundant/unnecessary
  • Any better alternatives or refactors that should be considered before merge
  • Check for unnecessary re-renders, artificial delays, duplicated logic, or avoidable global state usage
  • Review code quality, folder structure, naming consistency, responsiveness, and adherence to existing project conventions
  • Verify if all modified files are actually required for this feature

Please do a strict full PR review instead of only nitpick comments.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== App.jsx ==="
cat frontend/src/App.jsx

echo ""
echo "=== GlobalLoadingOverlay.jsx ==="
cat frontend/src/components/shared/GlobalLoadingOverlay.jsx

echo ""
echo "=== RouteFrame.jsx ==="
cat frontend/src/components/shared/RouteFrame.jsx

echo ""
echo "=== PageSkeletons.jsx ==="
cat frontend/src/components/shared/skeletons/PageSkeletons.jsx

echo ""
echo "=== LoadingContext.jsx ==="
cat frontend/src/context/LoadingContext.jsx

echo ""
echo "=== index.css ==="
cat frontend/src/index.css

echo ""
echo "=== AccountCenterPage.jsx ==="
cat frontend/src/pages/AccountCenterPage.jsx

echo ""
echo "=== DashboardPage.jsx ==="
cat frontend/src/pages/DashboardPage.jsx

echo ""
echo "=== ExplorePage.jsx ==="
cat frontend/src/pages/ExplorePage.jsx

echo ""
echo "=== Check existing loading-related files ==="
fd -e jsx -e js . frontend/src --exec grep -l "loading\|Loading\|skeleton\|Skeleton" {} 2>/dev/null

echo ""
echo "=== Check existing context files ==="
ls frontend/src/context/

echo ""
echo "=== Check useLoading usage across codebase ==="
rg -n "useLoading\|LoadingProvider\|LoadingContext" frontend/src/

echo ""
echo "=== Check RouteFrame usage ==="
rg -n "RouteFrame" frontend/src/

echo ""
echo "=== Check GlobalLoadingOverlay usage ==="
rg -n "GlobalLoadingOverlay" frontend/src/

echo ""
echo "=== Check for existing LoaderSwitcher ==="
rg -n "LoaderSwitcher" frontend/src/

echo ""
echo "=== Check package.json for relevant deps ==="
cat frontend/package.json 2>/dev/null || cat package.json 2>/dev/null

Length of output: 40279


@kunalverma2512 Here is the complete, strict review of PR #78 as requested.


Full PR Review — feat: Loading Context, Skeletons & Route Transitions

1. What This PR Actually Changes

The PR introduces:

  • A global LoadingContext + GlobalLoadingOverlay (spinner)
  • A RouteFrame wrapper that fires the overlay on every route change using hardcoded timers
  • Three skeleton components (DashboardPageSkeleton, AccountCenterSkeleton, ExplorePageSkeleton)
  • A CSS page-fade-in keyframe animation applied by RouteFrame
  • Uses skeletons in DashboardPage (auth-loading gate) and AccountCenterPage (auth-loading gate)

Architectural impact: LoadingProvider is placed outside BrowserRouter, and RouteFrame sits inside it. The whole subtree of Routes is now wrapped in a keyed div that remounts on every navigation.


2. Critical Issues

🔴 ExplorePageSkeleton is dead code

The actual ExplorePage.jsx has zero skeleton usage:

// ExplorePage.jsx (actual file)
export default function ExplorePage() {
  return (
    <div className="w-full bg-white flex flex-col">
      <ExploreHero />
      ...
    </div>
  );
}

ExplorePageSkeleton is exported from PageSkeletons.jsx but never imported or used anywhere. It should either be wired up or removed. The AI-generated summary was misleading on this point.

🔴 Full subtree remount on every navigation (performance)

In RouteFrame.jsx, the key is placed on the returned div, not on RouteFrame itself at the call site:

<div key={location.key || location.pathname} className="page-fade-in ...">
  {children}
</div>

When location.key changes, React treats this as a new element and unmounts + remounts the entire subtree — including Routes, every active route component, and all their children. This destroys all local component state on every navigation and is significantly more expensive than a pure CSS fade. This is not a good pattern. The correct approach is to apply the animation class using a CSS transition without remounting children, or to key only the specific animated wrapper around a single route rather than the entire route tree.

🔴 Hardcoded artificial delays — not real loading

// RouteFrame.jsx
const timeoutMs = firstRender.current ? 180 : 280;
const timer = setTimeout(() => setLoading(false), timeoutMs);

These timers are not tied to any actual data fetching or async operation. The overlay appears and disappears based on a made-up duration, not because the page actually finished loading. This means:

  • On fast connections the overlay flashes unnecessarily
  • On slow connections it disappears while data is still loading
  • It adds visual noise without real feedback value

Better alternative: Show the overlay only when actual async operations are in flight (API calls, lazy-loaded chunks), not on a fixed timer.

🔴 Conflicting dual-loading UX

On navigating to /dashboard while auth is still resolving, both systems activate simultaneously:

  • RouteFrame shows the GlobalLoadingOverlay (full-screen white spinner)
  • DashboardPage shows DashboardPageSkeleton (layout placeholder)

The overlay at z-[80] covers the skeleton entirely, making the skeleton work invisible. The user sees the spinner, it disappears after 280ms, then the skeleton may still be visible. These two systems need to be coordinated or one should be removed.


3. Design & Architecture Issues

🟠 LoadingContext is over-engineered for its actual usage

After reading the full codebase, useLoading is called in exactly one placeRouteFrame.jsx. The entire context infrastructure (createContext, useMemo, useContext, provider, overlay) exists solely to pass a boolean from LoadingProvider (outside router) into RouteFrame (inside router).

useLoading usage: rg -n "useLoading" → 0 results outside RouteFrame

This is classic over-engineering. Options:

  • Move the overlay into MainLayout with a simple prop, or
  • Move LoadingProvider inside BrowserRouter where it can be used in more places, or
  • Use a simpler approach like a CSS-only transition without global state

🟠 showLoading / hideLoading helpers are never called

const value = useMemo(() => ({
  isLoading,
  setLoading,
  showLoading: () => setLoading(true),   // ← never used
  hideLoading: () => setLoading(false),  // ← never used
}), [isLoading]);

These add API surface and complexity but are unused. Either they should be used (replacing raw setLoading) or removed. Also, setLoading (a raw useState setter) should ideally not be exposed directly — prefer named helpers.

🟠 useMemo dependency causes unnecessary re-renders

const value = useMemo(() => ({ ... }), [isLoading]);

isLoading in the dependency array means the entire context value object is recreated on every loading toggle. Every consumer of the context re-renders twice per navigation (once when isLoading → true, once when isLoading → false). Since setLoading/showLoading/hideLoading don't depend on isLoading, they should be memoized separately with useCallback:

const showLoading = useCallback(() => setLoading(true), []);
const hideLoading = useCallback(() => setLoading(false), []);
const value = useMemo(() => ({ isLoading, showLoading, hideLoading }), [isLoading, showLoading, hideLoading]);

🟠 firstRender ref approach is fragile

const firstRender = useRef(true);

If RouteFrame ever unmounts and remounts (e.g., due to the key trick it itself applies), this ref resets to true, causing the shorter 180ms timeout to fire again unexpectedly. The distinction between first/subsequent render also adds complexity for a 100ms difference that users can't perceive.


4. Skeleton Implementation Review

Component Quality Issue
DashboardPageSkeleton ✅ Good Layout roughly matches real page
AccountCenterSkeleton ✅ Good Adheres to brutalist style
ExplorePageSkeleton ❌ Dead code Never used in ExplorePage

Style concern: SkeletonBlock applies border-[2px] border-black animate-pulse — the black border pulses with the background, which looks unusual. Standard skeletons use borderless blocks. This may be intentional for the brutalist style but reads as visual noise.

Inconsistent coverage: Many pages have no skeletons at all — CodeforcesPage, GitHubIntelligencePage, PracticePage, ApexAIPage, AlgoVersePage, etc. The improvement is partial and inconsistent.


5. AccountCenterPage — Simplified, But Correct

The final implementation is clean:

if (authLoading || !user) {
  return <AccountCenterSkeleton />;
}

No artificial pageReady timer — this correctly gates on real auth state. ✅


6. DashboardPage — Also Clean

if (loading) {
  return <DashboardPageSkeleton />;
}

Replaces the old LoaderSwitcher with a skeleton. This is the best use of skeletons in the PR. ✅


7. Existing LoaderSwitcher Inconsistency

LoaderSwitcher still exists and is still used in ProtectedRoute.jsx and PublicRoute.jsx:

frontend/src/components/shared/ProtectedRoute.jsx:3: import Loader from "./loaders/LoaderSwitcher";
frontend/src/components/shared/PublicRoute.jsx:3: import Loader from "./loaders/LoaderSwitcher";

The PR introduces a new loading system but doesn't clean up the old one. This leaves two parallel loading UIs in the codebase.


8. Code Quality & Structure

Item Status
Folder structure (components/shared/skeletons/) ✅ Good
Naming (GlobalLoadingOverlay, RouteFrame) ✅ Clear
Accessibility (aria-hidden, role="status", aria-live) on overlay ✅ Good
useLoading error boundary (throw new Error) ✅ Good pattern
CSS keyframe in index.css ✅ Appropriate placement
Brutalist style adherence ✅ Consistent
No TypeScript — consistent with existing project

9. Summary Verdict

Aspect Verdict
DashboardPage skeleton (auth-gated) ✅ Merge-ready
AccountCenterPage skeleton (auth-gated) ✅ Merge-ready
CSS fade animation ✅ Merge-ready
ExplorePageSkeleton ❌ Dead code, wire it up or remove
GlobalLoadingOverlay + RouteFrame artificial timers ❌ Not recommended — misleading UX
LoadingContext infrastructure ⚠️ Over-engineered for current usage
Full subtree remount via key ❌ Performance concern
showLoading/hideLoading unused helpers ❌ Remove or use

Recommended Actions Before Merge

  1. Wire up or remove ExplorePageSkeleton — it's currently dead code.
  2. Remove or rethink RouteFrame — artificial delays are not real loading signals. If a fade-in animation is desired, use a CSS-only approach (e.g., <Outlet> with animate class) without the global state machinery.
  3. Remove showLoading/hideLoading from context if unused, or document/use them.
  4. Consolidate with LoaderSwitcher — either replace it with the skeleton system or keep only one loading primitive.
  5. Don't use key on the inner div of RouteFrame — it causes unnecessary remounts. Apply the CSS class without a key-based remount strategy.

The skeleton components themselves are well-crafted and the auth-gated usage in DashboardPage and AccountCenterPage is a genuine improvement. The main concerns are the over-engineered context, artificial delays, and dead code.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a 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

🤖 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 `@frontend/src/App.jsx`:
- Line 38: The wrapper div in App.jsx uses key={location.key}, which forces a
full remount of the entire routed subtree (including <Routes>) on every
navigation; change this to avoid remounting page components by replacing
key={location.key} with a key that only changes on actual path changes (e.g.,
key={location.pathname}) or remove the key entirely and apply the CSS keyframe
to an inner element that you intentionally want to remount/animate (for example,
move the key to the element that wraps the page content or to the Routes child),
ensuring you update the JSX where the div with className "page-fade-in w-full
flex-1 flex flex-col" is declared.

In `@frontend/src/components/shared/ProtectedRoute.jsx`:
- Around line 7-9: The guard currently returns null while auth resolves in
ProtectedRoute.jsx (if (loading) return null;), producing a blank frame; replace
that null with a shared guard fallback component (e.g., render an
<AuthGuardFallback /> or <GuardSkeleton />) so the UI shows a consistent loading
state during authentication resolution, keeping the existing redirect behavior
(if (!isAuthenticated) return <Navigate ... />) and wiring the fallback into the
same component where loading and isAuthenticated are checked.

In `@server/server.js`:
- Line 8: Re-enable the fail-fast DB initialization by calling connectDB()
before starting the HTTP listener and only call server/app listen after
connectDB resolves; if connectDB throws or rejects, log the error and exit
process with non-zero status. Locate the connectDB call and the server start
(e.g., connectDB and app.listen or server.listen in server/server.js) and
move/restore the call so the listener is invoked inside the successful-connect
branch or after await connectDB(), with proper try/catch that logs the error and
calls process.exit(1) on failure.
🪄 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: 570c897f-39e8-4d50-9fac-7f7b93813a48

📥 Commits

Reviewing files that changed from the base of the PR and between f6125cc and db4d42f.

⛔ Files ignored due to path filters (1)
  • server/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • frontend/src/App.jsx
  • frontend/src/components/shared/ProtectedRoute.jsx
  • frontend/src/components/shared/PublicRoute.jsx
  • frontend/src/components/shared/skeletons/PageSkeletons.jsx
  • frontend/src/pages/AccountCenterPage.jsx
  • frontend/src/pages/DashboardPage.jsx
  • frontend/src/pages/ExplorePage.jsx
  • server/server.js
💤 Files with no reviewable changes (1)
  • frontend/src/pages/ExplorePage.jsx

Comment thread frontend/src/App.jsx Outdated
Comment thread frontend/src/components/shared/ProtectedRoute.jsx Outdated
Comment thread server/server.js Outdated
@anish27863
Copy link
Copy Markdown
Author

@coderabbitai Please provide a complete and detailed review of this PR.

Specifically review:

What this PR actually changes in the project architecture and user experience
Whether the loading context implementation is properly designed and justified
What optimizations or improvements were introduced compared to the previous implementation
Whether the skeleton loaders and route transition system are implemented efficiently and without unnecessary complexity
Any potential performance, maintainability, scalability, or UX concerns
Whether the contribution is meaningful and valid for the project, or if parts feel redundant/unnecessary
Any better alternatives or refactors that should be considered before merge
Check for unnecessary re-renders, artificial delays, duplicated logic, or avoidable global state usage
Review code quality, folder structure, naming consistency, responsiveness, and adherence to existing project conventions
Verify if all modified files are actually required for this feature
Please do a strict full PR review instead of only nitpick comments.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Tip

For best results, initiate chat on the files or code changes.

@anish27863 The comprehensive review requested was already completed in this thread (see kunalverma2512's request above). As the PR author, here is a focused summary of what you need to address before this can be merged:


✅ Parts That Are Merge-Ready

  • DashboardPageSkeleton — correctly gated on real auth loading state
  • AccountCenterSkeleton — correctly gated on real auth loading state
  • CSS page-fade-in animation in index.css

❌ Issues You Must Fix

  1. ExplorePageSkeleton is dead code — it is exported from PageSkeletons.jsx but never imported or used in ExplorePage.jsx. Either wire it up or delete it.

  2. RouteFrame uses fake timers, not real loading signals:

    // This is not tied to any actual async operation
    const timer = setTimeout(() => setLoading(false), 280);

    Remove the artificial delays. If you want a fade-in animation, just apply the .page-fade-in CSS class directly on the route wrapper — no timers, no context needed.

  3. Full subtree remount on every navigation — the key on the div inside RouteFrame forces React to unmount and remount the entire <Routes> tree on every page change, destroying all local state and hurting performance. Remove the key prop from the inner div.

  4. showLoading/hideLoading helpers in LoadingContext are never called anywhere — remove them or use them.

  5. LoadingContext + GlobalLoadingOverlay are over-engineered for what they do: useLoading is called in exactly one place (RouteFrame). The entire context infrastructure can be replaced with a simple local state or CSS-only solution.

  6. Overlay and skeleton conflict — on routes like /dashboard, the GlobalLoadingOverlay (z-index 80) completely covers the DashboardPageSkeleton, making the skeleton invisible. These two systems need to be coordinated or one must be removed.

  7. LoaderSwitcher still exists in ProtectedRoute.jsx and PublicRoute.jsx — the PR introduces a new loading system but leaves the old one in place. Decide on one approach and clean up the other.


Recommended Minimal Fix Path

The simplest path to a clean, mergeable PR:

  • Keep the skeleton components (DashboardPageSkeleton, AccountCenterSkeleton) as-is — they're good.
  • Delete LoadingContext.jsx, GlobalLoadingOverlay.jsx, and RouteFrame.jsx entirely.
  • Apply .page-fade-in directly in AppRoutes without a key-based remount.
  • Wire up or delete ExplorePageSkeleton.

This keeps the genuine UX improvements (skeletons) while removing the over-engineered and problematic parts.

@anish27863
Copy link
Copy Markdown
Author

@kunalverma2512 please check it out

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