Overview
GitScope is a React-based GitHub repository dashboard built with a component-driven architecture. The application follows a unidirectional data flow pattern, with state management handled entirely through React’s built-in hooks (no external state libraries).Architecture Layers
Data Layer
Custom
useGitHub hook encapsulates all GitHub API communicationComponent Layer
Modular React components with CSS Modules for styling
State Layer
React hooks (
useState, useEffect, useCallback) for state managementPresentation Layer
CSS Variables + CSS Modules for theming and scoped styles
Data Layer: useGitHub Hook
The useGitHub hook (src/hooks/useGitHub.js) serves as the complete data access layer for the GitHub API.
Key Responsibilities
Token Management
Token Management
- Stores GitHub Personal Access Token in
localStorage - Automatically includes token in request headers via
Authorization: Bearer {token} - Provides
saveTokenfunction to persist or remove tokens - Token persists across sessions for authenticated rate limits (5,000 req/h vs 60 req/h)
Rate Limit Tracking
Rate Limit Tracking
Extracts rate limit headers from every API response:Exposes reactive
rateLimit state that updates automatically on each request.Error Handling
Error Handling
- 403: Rate limit exceeded → throws descriptive error
- 404: User not found → throws “Usuario no encontrado”
- Other: Parses JSON error message or falls back to HTTP status
API Methods
API Methods
The hook exposes four core methods:
getUser(username)→/users/:usernamegetRepos(username, page, per_page)→/users/:username/reposgetCommits(owner, repo, per_page)→/repos/:owner/:repo/commitsgetLanguages(owner, repo)→/repos/:owner/:repo/languages
Implementation Details
Location:src/hooks/useGitHub.js:1-63
All API methods use
useCallback to prevent unnecessary re-renders and maintain stable function references across renders.Component Architecture
GitScope follows a container/presentational component pattern with App.jsx as the root container.Component Hierarchy
Component Communication
State Management
All state lives inApp.jsx and is managed through React’s built-in hooks. No external state management libraries (Redux, Zustand, etc.) are used.
Core State Variables
| State | Type | Purpose | Persistence |
|---|---|---|---|
theme | string | 'light' or 'dark' | localStorage |
user | object | GitHub user profile data | session |
repos | array | Current page of repositories | session |
selectedRepo | object | Currently selected repository for commit view | session |
loading | boolean | Loading indicator state | session |
error | string | Error message to display | session |
page | number | Current pagination page (1-based) | session |
hasMore | boolean | Whether more repos exist | session |
currentUsername | string | Username being analyzed | session |
showToken | boolean | Token modal visibility | session |
State Management Patterns
1. Derived State from Hook
useGitHub hook manages token and rate limit state internally, exposing them as reactive values.
2. Async State Updates
Location:src/App.jsx:35-57
3. Effect-Based Pagination
Location:src/App.jsx:59-71
Caching Strategies
Language Chart Cache
TheLanguageChart component implements an in-memory cache using useRef to avoid redundant API calls.
Location: src/components/LanguageChart.jsx:27-42
Cache Characteristics
Scope
Component-level (not app-wide)
Lifetime
Persists while component is mounted
Key Format
username/repo-nameEviction
Cleared on component unmount
Benefits
- Reduces API calls: If user navigates away and back, languages aren’t re-fetched
- Improves rate limit usage: Only fetches each repo’s languages once per session
- Faster re-renders: Cached data resolves immediately with
Promise.resolve
The cache only stores the top 12 repositories’ language data to limit API consumption.
Pagination Implementation
GitScope uses client-side pagination with server-side data fetching.Strategy
- Fetch 30 repos per page from GitHub API
- Detect if more pages exist:
hasMore = data.length === PER_PAGE - Update
pagestate to trigger new fetch - Replace current
reposarray with new page data
src/components/RepoList.jsx:115-131
GitHub API Parameters
GitHub’s API automatically sorts by
updated in descending order, so the most recently updated repos appear first.Design Patterns
1. Custom Hook Pattern
Purpose: Encapsulate and reuse stateful logic Example:useGitHub hook abstracts all GitHub API logic into a reusable, testable unit.
2. Compound Component Pattern
Purpose: Related components that work together Example:RepoList contains filter controls, grid, and pagination as a cohesive unit.
3. Controlled Component Pattern
Purpose: Parent component controls child state Example: App.jsx controlsselectedRepo state and passes it to both RepoList and CommitPanel.
4. Optimistic UI Updates
Purpose: Improve perceived performance Example: Theme toggle updates immediately without waiting for localStorage write.5. Error Boundary Pattern (Manual)
Purpose: Graceful error handling Example: App-level error state with dismissible banner.Performance Optimizations
useCallback for Stable Function References
useCallback for Stable Function References
Prevents child component re-renders when functions are passed as props.
Lazy Component Mounting
Lazy Component Mounting
Conditional rendering ensures expensive components only mount when needed:
CommitPanelonly mounts whenselectedRepois setTokenModalonly mounts whenshowTokenis true
Debounced Animations
Debounced Animations
Staggered fade-up animations use CSS delays to avoid layout thrashing:
Promise.all for Parallel Fetches
Promise.all for Parallel Fetches
User profile and repositories load simultaneously:
CSS Modules for Scoped Styles
CSS Modules for Scoped Styles
Each component has isolated styles that don’t pollute global namespace, reducing CSS parsing overhead.
Event Flow Example
Let’s trace what happens when a user searches for “torvalds”:Error Handling Flow
Next Steps
Project Structure
Explore the file and folder organization
Tech Stack
Learn about the technologies and dependencies