feat(dashboard): Overview V2 - Codebase Intelligence#218
Conversation
- DashboardLayout: Added theme-aware Toaster, sidebar state persistence - Sidebar: Migrated to theme tokens, lucide-react icons - TopNav: Theme toggle button, shadcn Button, proper theme tokens - DashboardStats: Theme tokens for stat cards with indigo accent - DashboardHome: Full theme migration, lucide-react icons - RepoList: Theme tokens, lucide-react icons for repo cards - AddRepoForm: Migrated to shadcn Input, Label, Button components All hardcoded colors (bg-[#09090b], text-gray-400, border-white/5) replaced with theme tokens (bg-background, text-muted-foreground, border-border)
… mode support Components migrated: - RepoOverview: bg-muted, text-foreground, text-muted-foreground, border-border - StyleInsights: all cards and text now use theme tokens - ImpactAnalyzer: form inputs, cards, risk badges migrated - DependencyGraph: cards, controls, legend use theme tokens - SearchBox: input styling, focus states, badges - ResultCard: code blocks adapt to light/dark, all text themed - SearchPanel: cards, badges, empty state Replaced hardcoded colors: - bg-[#0a0a0c] → bg-muted/bg-card - border-white/5 → border-border - text-zinc-500/text-gray-400 → text-muted-foreground - text-white → text-foreground - text-blue-400 → text-primary All repo detail tabs now properly support light and dark modes.
- Created RepoSummaryCard component with auto-generated insights - Fetches data from /insights and /style-analysis endpoints - Shows: main summary, quick stats pills, critical files warning - Added useRepoInsights hook with caching support - Card only shows when repo status is 'indexed' - Gradient background with primary color theming - Loading skeleton while data fetches Phase 2.5a complete - the 'aha moment' is here!
WHAT: - Replace basic stats with intelligent codebase analysis - Auto-detect entry points from dependency graph - Show high-impact files with dependency counts - Architecture tree with core annotations - Code health indicators (type coverage, naming consistency) - Quick actions to navigate between tabs WHY: - Competitive differentiation from DeepWiki - DeepWiki = static documentation - CodeIntel = actionable intelligence - Help developers START WORKING, not just READ COMPONENTS: - CodebaseIntelligence.tsx: Main intelligence card - Updated RepoOverview.tsx: Uses new component - onTabChange prop for cross-tab navigation Data derived from existing APIs: - /dependencies: entry points, architecture - /style-analysis: health metrics - No backend changes needed
Bug: High-Impact Files section was empty
Cause: Relying on deps.metrics.most_critical_files from backend
but Entry Points (which worked) computed from edges directly
Fix: Compute critical files locally from same edge data
- Sort by in-degree (most dependents first)
- Consistent with Entry Points calculation
- No backend dependency for this data
|
@DevanshuNEU is attempting to deploy a commit to the Dev's projects Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughMigrates many UI surfaces to design-token classes and shared UI primitives, adds theme support and persisted sidebar state, introduces CodebaseIntelligence and RepoSummaryCard components, and adds a useRepoInsights hook plus related cache invalidation. Several components gained optional props (onTabChange, defaultBranch, loading). Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant RepoOverview
participant CodeIntel as CodebaseIntelligence
participant API as BackendAPI
participant Cache as LocalStorage
User->>RepoOverview: Open repository page
RepoOverview->>CodeIntel: Render intelligence (if repo indexed)
CodeIntel->>Cache: Check cached insights/style
alt Cache hit
Cache-->>CodeIntel: Return cached data
else Cache miss
CodeIntel->>API: GET /dependency-graph
API-->>CodeIntel: Return graph
CodeIntel->>API: GET /style-analysis
API-->>CodeIntel: Return style data
CodeIntel->>Cache: Store insights/style
end
CodeIntel->>CodeIntel: Compute metrics (degrees, entry points, health)
CodeIntel-->>User: Render intelligence UI
User->>CodeIntel: Click tab/action
CodeIntel->>RepoOverview: onTabChange(tab)
RepoOverview->>RepoOverview: Update active tab
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
frontend/src/components/dashboard/DashboardStats.tsx (1)
10-24: Add RAF cleanup to avoid state updates after unmount.Without cancelling the scheduled animation frame, React can attempt
setCountafter unmount. Add a cleanup to cancel the frame and guard the callback.🛠️ Suggested fix
useEffect(() => { if (end === 0) { setCount(0); return } let startTime: number | null = null + let frameId: number | null = null + let cancelled = false const animate = (timestamp: number) => { + if (cancelled) return if (!startTime) startTime = timestamp const progress = Math.min((timestamp - startTime) / duration, 1) const easeOut = 1 - Math.pow(1 - progress, 3) setCount(Math.floor(easeOut * end)) - if (progress < 1) requestAnimationFrame(animate) + if (progress < 1) frameId = requestAnimationFrame(animate) } - requestAnimationFrame(animate) + frameId = requestAnimationFrame(animate) + return () => { + cancelled = true + if (frameId !== null) cancelAnimationFrame(frameId) + } }, [end, duration])frontend/src/components/dashboard/CommandPalette.tsx (1)
49-76: Stale closure:filteredItemsandonClosemissing from dependency array.The keyboard handler references
filteredItemsandonClose, but the effect only re-runs whenisOpen,selectedIndex, orquerychange. Ifreposloads after the palette opens (whilequeryremains empty), the handler will reference an outdatedfilteredItemsarray, potentially invoking the wrong action or causing an index-out-of-bounds issue.🐛 Proposed fix
window.addEventListener('keydown', handleKeyDown) return () => window.removeEventListener('keydown', handleKeyDown) - }, [isOpen, selectedIndex, query]) + }, [isOpen, selectedIndex, filteredItems, onClose])Alternatively, remove
querysincefilteredItemsalready captures query changes. IncludingfilteredItemsensures the handler always sees the current list.frontend/src/components/DependencyGraph.tsx (1)
65-82: Filter threshold is bypassed for nodes with any edge.
allEdges.some(...)makes any single edge pass the filter, sominDeps/critical thresholds are effectively ignored for those nodes. Consider counting edges and comparing to the threshold.🐛 Suggested fix
- filteredNodes = allNodes.filter((node: any) => - (node.data.imports || 0) >= threshold || allEdges.some(e => e.target === node.id) - ) + filteredNodes = allNodes.filter((node: any) => { + const inCount = allEdges.filter(e => e.target === node.id).length + const depCount = Math.max(node.data.imports || 0, inCount) + return depCount >= threshold + })frontend/src/components/search/ResultCard.tsx (1)
10-18: Make GitHub links branch-aware.Hardcoding
mainbreaks repos whose default branch isn’tmain. Consider passing the repo branch into this component and using it when building the URL.🔧 Suggested change
interface ResultCardProps { result: SearchResult; rank: number; isExpanded?: boolean; aiSummary?: string; repoUrl?: string; + repoBranch?: string; } -export function ResultCard({ result, rank, isExpanded: initialExpanded = false, aiSummary, repoUrl }: ResultCardProps) { +export function ResultCard({ result, rank, isExpanded: initialExpanded = false, aiSummary, repoUrl, repoBranch = 'main' }: ResultCardProps) { ... - const githubUrl = repoUrl ? `${repoUrl}/blob/main/${cleanFilePath}#L${result.line_start}-L${result.line_end}` : null; + const githubUrl = repoUrl ? `${repoUrl}/blob/${repoBranch}/${cleanFilePath}#L${result.line_start}-L${result.line_end}` : null;Also applies to: 29-29
🤖 Fix all issues with AI agents
In `@frontend/src/components/CodebaseIntelligence.tsx`:
- Around line 96-102: The component currently uses repo.file_count as a fallback
for totalFunctions and then derives sizeDesc from that, which misreports
functions; update the logic so totalFunctions is only taken from
style?.summary?.total_functions (do not fall back to repo.file_count or
deps.total_files), display "N/A" in the UI when total_functions is
undefined/null, and compute sizeDesc strictly from the real totalFunctions value
(e.g. 'compact'/'medium-sized'/'large' only when totalFunctions is a number and
meets thresholds); adjust the equivalent logic referenced around the other block
(the usage at lines ~170-173) to follow the same rule and symbols
(totalFunctions, sizeDesc, repo.file_count).
- Around line 92-93: The current startHere picks criticalFiles[0] but the
comment asks for the most critical file that is also an entry point; change the
logic so startHere first searches criticalFiles for an item whose file is
present in entryPoints (e.g., use criticalFiles.find(cf => entryPoints.some(ep
=> ep.file === cf.file))). If none found, fall back to entryPoints[0]?.file or
null; update the variable startHere accordingly and reference the arrays
criticalFiles and entryPoints and the variable startHere in your change.
- Around line 370-381: The HealthIndicator component currently treats 0 as falsy
and shows "N/A"; change the prop type from { label: string, value: string |
null, threshold: number } to { label: string, value: string | number | null,
threshold: number }, replace the falsy check `if (!value)` with `if (value ==
null)` to only treat null/undefined as missing, and compute the numeric value
safely in HealthIndicator (e.g., if typeof value === 'number' use it, otherwise
parseFloat(value)) before comparing to threshold.
- Around line 34-36: The current guard in the useMemo that computes intelligence
is checking deps?.metrics, which hides the panel when metrics are missing even
if graph data exists; update the guard to gate on deps existence or graph data
instead (e.g., check deps != null or nodes.length > 0) so the intelligence
computation (inside the intelligence constant / useMemo) runs when deps is
present or when nodes/edges (extracted earlier with empty-array fallbacks)
contain data; adjust the conditional that returns null accordingly to reference
deps or nodes.length rather than deps?.metrics.
In `@frontend/src/components/dashboard/DashboardLayout.tsx`:
- Around line 19-27: The localStorage reads/writes around SIDEBAR_STORAGE_KEY
can throw and currently call JSON.parse directly; update the sidebarCollapsed
state initializer and the useEffect to guard against errors by wrapping
localStorage.getItem + JSON.parse in a try/catch and returning false on any
failure, and likewise wrap localStorage.setItem in a try/catch so failures are
no-ops; specifically modify the useState initializer for sidebarCollapsed and
the useEffect that calls localStorage.setItem(SIDEBAR_STORAGE_KEY,
JSON.stringify(sidebarCollapsed)) to handle exceptions safely.
In `@frontend/src/components/dashboard/DashboardStats.tsx`:
- Around line 39-64: The "Functions Indexed" stat in DashboardStats is using
totalFunctions (which sums repo.file_count from the Repository interface) so it
shows file count rather than function count; update DashboardStats to either
rename the stat to "Files Indexed" (change the label for the object with icon
Code2 / value animatedFunctions) or change the source to use the real function
count (pull style?.summary?.total_functions or the detailed insights source used
elsewhere and feed it into the animatedFunctions/totalFunctions calc), and
ensure any formatting/format flag remains consistent with the new metric name.
In `@frontend/src/components/dashboard/TopNav.tsx`:
- Around line 80-90: The theme toggle Button in TopNav is icon-only and lacks an
accessible name; update the Button (where toggleTheme is used and theme
determines Sun/Moon) to include a dynamic aria-label (or aria-labelledby) such
as aria-label={theme === 'dark' ? 'Switch to light mode' : 'Switch to dark
mode'} (or a localized equivalent) so screen readers announce the purpose; keep
existing props (variant, size, onClick, className) and ensure the label changes
with the theme.
In `@frontend/src/components/RepoList.tsx`:
- Around line 83-88: The UI label "Functions" is misleading because the
component uses repo.file_count; either change the displayed label to "Files" or
replace repo.file_count with the correct function-count metric (e.g.,
repo.function_count or repo.metrics.functions) if one exists on the Repository
object; update Repository type/props and any callers to pass the correct field
so RepoList.tsx renders the intended metric (look for the repo.file_count usage
in RepoList component and the Repository type/interface to locate and fix).
In `@frontend/src/components/RepoSummaryCard.tsx`:
- Around line 128-136: The label generation uses literal markdown (the variable
main in RepoSummaryCard.tsx) so `**${repo.name}**` will render asterisks; change
this to render plain text or a proper HTML element by removing the markdown and
using a <strong> element (e.g., build the summary as JSX or concatenate strings
with repo.name without asterisks) so the repository name is bolded properly in
the UI; update the code paths that produce main and any consumers that expect a
string to accept JSX if needed.
- Around line 101-103: The primaryLang selection uses Object.keys(languages)[0]
which may not be the dominant language; update the logic that sets primaryLang
to inspect the values in languages (handle both numeric values and objects with
percentage/count fields), sort the language entries by their numeric share
descending, and pick the top key as primaryLang (falling back to 'Unknown' if
languages is empty); locate and modify the constants languages and primaryLang
in RepoSummaryCard.tsx (referencing insights, style, and
style.language_distribution) to implement this deterministic selection.
In `@frontend/src/components/search/ResultCard.tsx`:
- Line 6: The theme check in ResultCard is using the raw theme value from
useTheme which can be "system", so change the hook usage to destructure
resolvedTheme (const { resolvedTheme } = useTheme()) and replace any checks like
theme === 'dark' with resolvedTheme === 'dark' (or a defensive fallback like
(resolvedTheme || theme) === 'dark') so the Prism theme selection respects the
OS preference; update all occurrences in the ResultCard component that compare
theme to 'dark'.
🧹 Nitpick comments (2)
frontend/src/components/dashboard/CommandPalette.tsx (2)
78-88: Consider checkingresponse.okbefore parsing JSON.If the API returns a 4xx/5xx status, the response body may not contain the expected
repositoriesfield, silently falling back to an empty list without surfacing the error to the user.♻️ Proposed improvement
const fetchRepos = async () => { try { const response = await fetch(`${API_URL}/repos`, { headers: { 'Authorization': `Bearer ${session?.access_token}` } }) + if (!response.ok) { + console.error('Failed to fetch repos:', response.status) + return + } const data = await response.json() setRepos(data.repositories || []) } catch (error) { console.error('Error fetching repos:', error) } }
102-107: Consider breaking long item definitions across multiple lines for readability.These single-line item definitions are dense and harder to scan during review. Multi-line formatting would improve maintainability.
♻️ Example formatting
- items.push({ id: 'action-add-repo', type: 'action', title: 'Add Repository', subtitle: 'Clone and index a new repository', icon: '➕', action: () => { window.dispatchEvent(new CustomEvent('openAddRepo')); navigate('/dashboard') } }) + items.push({ + id: 'action-add-repo', + type: 'action', + title: 'Add Repository', + subtitle: 'Clone and index a new repository', + icon: '➕', + action: () => { + window.dispatchEvent(new CustomEvent('openAddRepo')) + navigate('/dashboard') + } + })
CodebaseIntelligence.tsx: - Fix guard to work with deps/nodes instead of requiring metrics - Fix startHere to find critical file that's also entry point - Fix totalFunctions to only use real data, show N/A when missing - Fix HealthIndicator to handle 0 values (not treat as falsy) DashboardLayout.tsx: - Wrap localStorage operations in try/catch DashboardStats.tsx: - Rename 'Functions Indexed' to 'Files Indexed' (correct metric) TopNav.tsx: - Add aria-label to theme toggle for accessibility RepoList.tsx: - Change 'Functions' label to 'Files' (matches file_count) RepoSummaryCard.tsx: - Fix markdown asterisks - use JSX <strong> for repo name - Fix primaryLang to sort by dominant language value ResultCard.tsx: - Use resolvedTheme instead of theme for system theme support
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@frontend/src/components/RepoSummaryCard.tsx`:
- Around line 122-124: The sort assumes every namingConventions entry has a
percentage and uses parseFloat directly, which can produce NaN; update the sort
comparator used when building primaryNaming to defensively read percentage
(e.g., a[1]?.percentage or a[1]?.percentage ?? '0') and convert with a safe
parse that falls back to 0 for missing/invalid values, and when selecting
primaryNaming ensure you handle the case of an empty array before indexing so
namingStyle is null if none found; locate the sort and assignment around
primaryNaming, namingConventions, and namingStyle and apply these defensive
fallbacks.
In `@frontend/src/components/search/ResultCard.tsx`:
- Around line 92-101: The language badge can show "undefined" while
SyntaxHighlighter falls back to 'text'; update the badge in the ResultCard
component to use the same fallback as the highlighter (use result.language ||
'text') so the span that displays language uses the identical value as the
SyntaxHighlighter's language prop; locate the SyntaxHighlighter usage and the
adjacent span (the badge) and change the span's content to the same fallback
expression.
- Line 29: The GitHub URL is hardcoded to "main"; update the types and props to
carry the repository default branch and use it when constructing the URL: add
default_branch (string) to the SearchResult interface, update wherever
SearchResult instances are created so they include repository.default_branch,
and update ResultCard's props (and any callers) to accept and use
result.default_branch (or a prop named defaultBranch) in place of the literal
"main" when building githubUrl (the variable in ResultCard.tsx) so links work
for repos with master/develop/trunk, etc.
♻️ Duplicate comments (8)
frontend/src/components/dashboard/TopNav.tsx (1)
80-92: Past issue addressed: Accessible label added to theme toggle.The
aria-labelhas been correctly added to the icon-only button, addressing the previous accessibility concern.frontend/src/components/dashboard/DashboardLayout.tsx (1)
19-35: Past issue addressed: localStorage operations properly guarded.The
try/catchblocks have been correctly added around bothlocalStorage.getItemandlocalStorage.setItemoperations, preventing potential crashes from storage errors or quota limits.frontend/src/components/RepoSummaryCard.tsx (2)
106-115: Past issue addressed: Primary language selection now sorts by value.The language selection logic correctly handles both numeric values and objects with
percentage/countproperties, sorting descending to pick the dominant language.
56-58: Past issue addressed: Repository name rendered with JSX<strong>element.The markdown bold syntax has been replaced with proper JSX rendering using
<strong>{repo.name}</strong>.frontend/src/components/CodebaseIntelligence.tsx (4)
34-39: Past issue addressed: Guard now checks deps existence instead of metrics.The guard correctly checks
!deps && nodes.length === 0to allow the component to work when graph data exists but metrics are missing.
93-97: Past issue addressed:startHerenow properly intersects critical files with entry points.The logic correctly finds a critical file that is also an entry point before falling back to the first entry point.
99-108: Past issue addressed: Function count no longer uses file_count as proxy.
totalFunctionsis now strictly derived fromstyle?.summary?.total_functionswith proper null handling, and the UI conditionally renders "N/A" when unavailable.Also applies to: 177-182
379-391: Past issue addressed: Numeric 0 now handled correctly in HealthIndicator.The check
value == nullproperly distinguishes between missing data and a valid zero value, and the type signature includesnumber | null.
🧹 Nitpick comments (3)
frontend/src/components/dashboard/TopNav.tsx (1)
32-34: Handlesystemtheme value in toggle and aria-label.The
useThemehook fromnext-themescan return'system'as the theme value. Whentheme === 'system', the toggle will set it to'light'(since it's not'dark'), and the aria-label will say "Switch to dark mode" even though the system might already be in dark mode. Consider usingresolvedThemeinstead for accurate display, or explicitly handling the system case.♻️ Suggested improvement
export function TopNav({ onToggleSidebar, sidebarCollapsed, onOpenCommandPalette }: TopNavProps) { const { session, signOut } = useAuth() - const { theme, setTheme } = useTheme() + const { theme, setTheme, resolvedTheme } = useTheme() const [showUserMenu, setShowUserMenu] = useState(false) const userEmail = session?.user?.email || 'User' const userInitial = userEmail.charAt(0).toUpperCase() const toggleTheme = () => { - setTheme(theme === 'dark' ? 'light' : 'dark') + setTheme(resolvedTheme === 'dark' ? 'light' : 'dark') }And for the aria-label and icon:
- aria-label={theme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'} + aria-label={resolvedTheme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'} > - {theme === 'dark' ? ( + {resolvedTheme === 'dark' ? (Also applies to: 85-85
frontend/src/components/dashboard/DashboardLayout.tsx (1)
75-77: Toaster theme may not reflect system preference.Similar to TopNav, when
themeis'system', the Toaster receives'light'instead of the actual resolved theme. Consider usingresolvedThemefor accurate theming.♻️ Suggested fix
export function DashboardLayout({ children }: DashboardLayoutProps) { - const { theme } = useTheme() + const { resolvedTheme } = useTheme() // ... rest of component <Toaster - theme={theme === 'dark' ? 'dark' : 'light'} + theme={resolvedTheme === 'dark' ? 'dark' : 'light'} position="bottom-right" />frontend/src/components/search/ResultCard.tsx (1)
52-76: Add ARIA wiring for the expandable header.
The toggle button expands/collapses content but doesn’t expose state or control linkage to assistive tech.♿ Proposed accessibility fix
-import { useState, useRef, useEffect } from 'react'; +import { useState, useRef, useEffect, useId } from 'react'; export function ResultCard({ result, rank, isExpanded: initialExpanded = false, aiSummary, repoUrl }: ResultCardProps) { const [expanded, setExpanded] = useState(initialExpanded); const contentRef = useRef<HTMLDivElement>(null); const [contentHeight, setContentHeight] = useState<number | undefined>(initialExpanded ? undefined : 0); + const contentId = useId(); const { resolvedTheme } = useTheme(); @@ - <button onClick={() => setExpanded(!expanded)} className="w-full p-4 flex items-start justify-between text-left hover:bg-muted/50 transition-colors"> + <button + onClick={() => setExpanded(!expanded)} + aria-expanded={expanded} + aria-controls={contentId} + className="w-full p-4 flex items-start justify-between text-left hover:bg-muted/50 transition-colors" + > @@ - <div ref={contentRef} className="overflow-hidden transition-all duration-200 ease-out" style={{ height: contentHeight !== undefined ? contentHeight : 'auto' }}> + <div + id={contentId} + ref={contentRef} + className="overflow-hidden transition-all duration-200 ease-out" + style={{ height: contentHeight !== undefined ? contentHeight : 'auto' }} + >
- RepoSummaryCard: defensive namingConventions sort (handle NaN, empty array) - ResultCard: language badge uses same fallback as SyntaxHighlighter - ResultCard: use defaultBranch prop instead of hardcoded 'main' - SearchPanel: pass defaultBranch to ResultCard - DashboardHome: pass repo.branch to SearchPanel
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@frontend/src/components/RepoSummaryCard.tsx`:
- Around line 159-161: The code appends `(X consistency)` using
`(primaryNaming[1] as any).percentage` which can be undefined; update the block
in RepoSummaryCard.tsx that references primaryNaming to safely read percentage
(e.g., use nullish coalescing or a fallback like `?? '0'` or convert with
`parseFloat(... ?? '0')`) before both the >80 check and the string interpolation
so the displayed consistency never shows "undefined" and uses the same defensive
logic used in the sort code.
🧹 Nitpick comments (2)
frontend/src/components/RepoSummaryCard.tsx (2)
11-16: Consider handling query error states.The component handles loading but not errors. If either query fails, the component will render the summary with potentially missing data, which might lead to a confusing UI or incomplete information display.
♻️ Suggested enhancement
export function RepoSummaryCard({ repo, apiKey }: RepoSummaryCardProps) { - const { data: insights, isLoading: insightsLoading } = useRepoInsights({ repoId: repo.id, apiKey }) - const { data: style, isLoading: styleLoading } = useStyleAnalysis({ repoId: repo.id, apiKey }) + const { data: insights, isLoading: insightsLoading, isError: insightsError } = useRepoInsights({ repoId: repo.id, apiKey }) + const { data: style, isLoading: styleLoading, isError: styleError } = useStyleAnalysis({ repoId: repo.id, apiKey }) const isLoading = insightsLoading || styleLoading + const hasError = insightsError || styleErrorThen optionally render an error state or a minimal fallback when
hasErroris true.
155-155: Inconsistent number formatting.
functionCountusestoLocaleString()butfileCountis interpolated directly. For consistency across the summary text, both should use the same formatting.♻️ Suggested fix
- main += `${primaryLang} codebase with ${functionCount.toLocaleString()} functions across ${fileCount} files. ` + main += `${primaryLang} codebase with ${functionCount.toLocaleString()} functions across ${fileCount.toLocaleString()} files. `
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@frontend/src/components/RepoSummaryCard.tsx`:
- Around line 133-136: The code assumes insights.most_critical_files is an array
and f.file is a string; change the block that builds criticalFiles so it first
verifies Array.isArray(insights?.most_critical_files) before calling .slice(0,
3), then in the forEach callback guard f and f.file (e.g., if (!f || typeof
f.file !== 'string') continue or use a fallback string) before calling
.split('/').pop(); update the logic around insights, most_critical_files, the
.slice(0, 3) call and the forEach callback to avoid throwing when data is
missing or malformed.
♻️ Duplicate comments (1)
frontend/src/components/RepoSummaryCard.tsx (1)
106-112: Primary language sorting can mis-rank percentage strings.
Line 110–112 usesNumber(...), which turns"12%"intoNaN, so the sort can become unstable. PreferparseFloat(with fallback) to support percent strings.🔧 Suggested fix
- const sorted = langEntries.sort((a, b) => { - const valA = typeof a[1] === 'number' ? a[1] : (a[1] as any)?.percentage ?? (a[1] as any)?.count ?? 0 - const valB = typeof b[1] === 'number' ? b[1] : (b[1] as any)?.percentage ?? (b[1] as any)?.count ?? 0 - return Number(valB) - Number(valA) - }) + const sorted = langEntries.sort((a, b) => { + const valA = + typeof a[1] === 'number' + ? a[1] + : parseFloat((a[1] as any)?.percentage ?? (a[1] as any)?.count ?? a[1] ?? '0') || 0 + const valB = + typeof b[1] === 'number' + ? b[1] + : parseFloat((b[1] as any)?.percentage ?? (b[1] as any)?.count ?? b[1] ?? '0') || 0 + return valB - valA + })
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🧠 Overview V2: Codebase Intelligence
What Changed
Completely redesigned the Overview tab to provide actionable codebase intelligence instead of basic stats.
Why
Competitive Differentiation from DeepWiki:
New Features
🧠 Intelligence Hero Card
📁 Architecture Overview
⚡ Entry Points
📊 Code Health
Technical Details
CodebaseIntelligence.tsxRepoOverview.tsx- uses new intelligence componentDashboardHome.tsx- passesonTabChangefor cross-tab navigation/dependenciesand/style-analysisAPIsScreenshots
The Overview tab now shows:
Testing
Commits
c195280- feat(dashboard): Overview V2 - Codebase Intelligence1cbf10a- fix(overview): compute critical files from edge dataSummary by CodeRabbit
New Features
Improvements
Public API additions
✏️ Tip: You can customize this high-level summary in your review settings.