ReferenceArchitecture

Architecture

The application uses a deliberate four-layer split so product logic stays out of the page entrypoint and GitHub-specific behavior stays on the server.

3-Layer Separation Plus View Layer

Page (app/) -> View (views/) -> API Route (app/api/) -> Service (services/)
LayerLocationResponsibility
Pagesrc/app/analyzer/page.jsServer component that only renders the view
Viewsrc/views/AnalyzerView/Client-side state, form handling, event handlers, and rendering
API Routesrc/app/api/analyze/route.jsValidates input, sanitizes URLs, calls the service layer, formats response
Servicesrc/services/Server-only GitHub API fetches, scoring, caching, orchestration

Data Flow

User pastes URLs
  -> RepoForm validates with Zod
  -> AnalyzerView sends POST via Axios
  -> API route sanitizes URLs
  -> analyzer.service orchestrates
       -> github.service fetches data with Octokit
       -> scoring.service computes scores
       -> cache.service stores results
  -> JSON response with repos + summary + rateLimit
  -> View renders tables, cards, and export actions

Why This Split Works

  • The page layer stays trivial and cache-safe.
  • The view layer owns UX concerns without mixing in Octokit or scoring logic.
  • The API route becomes the boundary for validation and sanitization.
  • The service layer remains testable and reusable.

Main Service Responsibilities

ServiceResponsibility
analyzer.service.jsOrchestrates multi-repo analysis and proactive rate-limit checks
github.service.jsGitHub API integration via Octokit and throttling plugin
scoring.service.jsNormalization, weighted scoring, and difficulty classification
cache.service.jsIn-memory TTL cache keyed by normalized owner/repo

Project Structure

src/
├── app/
│   ├── globals.css
│   ├── layout.js
│   ├── page.js
│   ├── analyzer/page.js
│   └── api/analyze/route.js
├── views/
│   └── AnalyzerView/
│       ├── index.js
│       ├── RepoForm.js
│       ├── ResultsTable.js
│       ├── RepoCard.js
│       ├── SummaryCard.js
│       ├── ScoreBadge.js
│       └── LoadingState.js
├── services/
│   ├── cache.service.js
│   ├── github.service.js
│   ├── scoring.service.js
│   └── analyzer.service.js
├── lib/
│   ├── axios.js
│   ├── validators.js
│   ├── constants.js
│   └── utils.js
└── components/
    ├── ErrorBoundary.js
    ├── ThemeProvider.js
    └── ui/

Design Assumption

The architecture assumes the expensive and rate-limited operations stay server-side. The client only sends repository URLs and receives structured results. That keeps secrets out of the browser and avoids duplicating logic between the UI and API path.