Add loading skeletons across pages#117
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
💤 Files with no reviewable changes (1)
WalkthroughA new ChangesSkeleton components and page wiring
Estimated code review effort: 2 (Simple) | ~12 minutes Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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/Orgexplorerskeletons.jsx`:
- Line 1: Add the "use client" directive at the top of Orgexplorerskeletons so
React treats it as a client component; this file uses NetworkSkeleton with
Math.random(), so update the module header before the React import and keep the
rest of the component logic unchanged.
- Around line 188-193: NetworkSkeleton is generating node coordinates with
Math.random() during render, which causes SSR hydration mismatches and re-render
jitter. Update the NetworkSkeleton component to initialize the nodes once using
the already-imported useState lazy initializer (or equivalent one-time
initialization) so the positions stay stable for the lifetime of the mount and
the render output remains deterministic.
In `@src/pages/AnalyticsPage.jsx`:
- Around line 55-58: The hook order in AnalyticsPage is unstable because
useAdvancedMetrics is called after the early returns, so move the
useAdvancedMetrics(filteredPulls) call above the loading/model guard to keep
hooks invoked consistently on every render. Update the AnalyticsPage component
so all hooks, including useAdvancedMetrics, run before any conditional returns,
and leave the loading and null checks after the hook declarations.
In `@src/pages/OverviewPage.jsx`:
- Line 9: The loading skeleton width is mismatched with the actual OverviewPage
layout, causing a layout shift when content loads. Update the skeleton sizing in
OverviewSkeleton (and any related skeleton components it reuses) to match the
page’s maxWidth of 1100 rather than the current w-295 width, so the placeholder
and final content align consistently on wide viewports.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7d0e707a-a795-4dbf-9aac-72652268ed5b
📒 Files selected for processing (7)
src/components/Orgexplorerskeletons.jsxsrc/pages/AnalyticsPage.jsxsrc/pages/ContributorsPage.jsxsrc/pages/GovernancePage.jsxsrc/pages/NetworkPage.jsxsrc/pages/OverviewPage.jsxsrc/pages/RepositoriesPage.jsx
| @@ -0,0 +1,313 @@ | |||
| import React, { useState } from "react"; | |||
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Add "use client" directive.
As per path instructions, ensure that "use client" is being used for files matching **/*.{jsx}. This file uses Math.random() in NetworkSkeleton, which is a client-only feature that will cause hydration mismatches under SSR.
🔧 Proposed fix
+"use client";
+
import React, { useState } from "react";📝 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.
| import React, { useState } from "react"; | |
| "use client"; | |
| import React, { useState } from "react"; |
🤖 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/Orgexplorerskeletons.jsx` at line 1, Add the "use client"
directive at the top of Orgexplorerskeletons so React treats it as a client
component; this file uses NetworkSkeleton with Math.random(), so update the
module header before the React import and keep the rest of the component logic
unchanged.
Source: Path instructions
| export function NetworkSkeleton() { | ||
| const nodes = Array.from({ length: 26 }).map(() => ({ | ||
| x: 8 + Math.random() * 84, | ||
| y: 10 + Math.random() * 75, | ||
| size: 8 + Math.random() * 10, | ||
| })); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Math.random() in render body causes hydration mismatch and visual instability.
NetworkSkeleton generates random node positions on every render. Under SSR, server and client produce different values → hydration mismatch. On the client, every re-render regenerates positions → visual jitter. The already-imported useState should be used to memoize the nodes once per mount.
🔒 Proposed fix using useState lazy initializer
export function NetworkSkeleton() {
- const nodes = Array.from({ length: 26 }).map(() => ({
- x: 8 + Math.random() * 84,
- y: 10 + Math.random() * 75,
- size: 8 + Math.random() * 10,
- }));
+ const [nodes] = useState(() =>
+ Array.from({ length: 26 }).map(() => ({
+ x: 8 + Math.random() * 84,
+ y: 10 + Math.random() * 75,
+ size: 8 + Math.random() * 10,
+ }))
+ );🤖 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/Orgexplorerskeletons.jsx` around lines 188 - 193,
NetworkSkeleton is generating node coordinates with Math.random() during render,
which causes SSR hydration mismatches and re-render jitter. Update the
NetworkSkeleton component to initialize the nodes once using the
already-imported useState lazy initializer (or equivalent one-time
initialization) so the positions stay stable for the lifetime of the mount and
the render output remains deterministic.
| import { AiOutlineInfoCircle } from "react-icons/ai"; | ||
| import AnalysisBanner from '../components/AnalysisBanner' | ||
|
|
||
| import { OverviewSkeleton } from '../components/Orgexplorerskeletons' |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Skeleton wiring is correct; flagging a width mismatch between skeleton and page layout.
The early return at line 32 is placed after all hooks (useState, useRef, useEffect), so no Rules of Hooks violation. The OverviewSkeleton is prop-less and safe to render during loading.
However, the skeleton uses w-295 (≈1180px) while the actual page uses maxWidth: 1100 (inline style). This 80px difference will cause a visible layout shift when the skeleton is replaced by real content on wider viewports. This applies to all six skeleton components.
Also applies to: 32-32
🤖 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/pages/OverviewPage.jsx` at line 9, The loading skeleton width is
mismatched with the actual OverviewPage layout, causing a layout shift when
content loads. Update the skeleton sizing in OverviewSkeleton (and any related
skeleton components it reuses) to match the page’s maxWidth of 1100 rather than
the current w-295 width, so the placeholder and final content align consistently
on wide viewports.
|
Please resolve the merge conflicts before review. Your PR will only be reviewed by a maintainer after all conflicts have been resolved. 📺 Watch this video to understand why conflicts occur and how to resolve them: |
Addressed Issues:
Fixes #
Currently these pages show a blank screen / generic spinner while data loads (repo list, contributor stats, network graph, etc). On slower connections this blank gap can last long enough that it looks like the app has crashed or frozen, rather than just loading. Layout-matched skeletons reduce that perceived load time and avoid layout shift once real data arrives.
Screenshots/Recordings:
Before

Video:
Recording.2026-07-08.NO.Skeleton.mp4
After:

Video:
Recording.2026-07-08.With.Skeleton.mp4
Additional Notes:
Changes
OverviewSkeleton— header, 4 stat cards, language distribution + high-impact repos, 6 nav cardsRepositorySkeleton— banner, search/filter row, tab pills, table rowsContributorSkeleton— bus factor + freshness cards, contributor tableNetworkSkeleton— toggle controls + scattered pulsing nodesAnalyticsSkeleton— filter row, chart placeholder, advanced analytics controlsGovernanceSkeleton— stat cards, resolution list, tab bar, status panelBar,Box,Circle,Pill) built on Tailwind'sanimate-pulse, no extra CSS neededChecklist
We encourage contributors to use AI tools responsibly when creating Pull Requests. While AI can be a valuable aid, it is essential to ensure that your contributions meet the task requirements, build successfully, include relevant tests, and pass all linters. Submissions that do not meet these standards may be closed without warning to maintain the quality and integrity of the project. Please take the time to understand the changes you are proposing and their impact.
Summary by CodeRabbit