Skip to main content

Overview

GitScope integrates with the GitHub REST API v3 to fetch user profiles, repositories, commits, and language statistics. All API communication is handled through the useGitHub custom hook.

Base Configuration

The API integration uses the official GitHub REST API endpoint:
const BASE = 'https://api.github.com'

API Endpoints

GitScope uses the following GitHub REST API endpoints:
FunctionEndpointPurpose
getUserGET /users/:usernameFetch user profile data
getReposGET /users/:username/reposList user repositories
getCommitsGET /repos/:owner/:repo/commitsGet repository commits
getLanguagesGET /repos/:owner/:repo/languagesGet repository languages

Authentication

Bearer Token

The API supports both authenticated and unauthenticated requests. Authentication is handled via Bearer token in the Authorization header:
const headers = () => {
  const h = { 'Accept': 'application/vnd.github+json' }
  if (token) h['Authorization'] = `Bearer ${token}`
  return h
}
Without authentication, the API rate limit is 60 requests/hour. With a Personal Access Token, it increases to 5,000 requests/hour.

Required Headers

All requests include the GitHub API version header:
'Accept': 'application/vnd.github+json'

Request Pattern

The hook implements a centralized request function that handles URL construction, query parameters, and error handling:
const request = async (path, params = {}) => {
  const url = new URL(`${BASE}${path}`)
  Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v))
  
  const res = await fetch(url.toString(), { headers: headers() })
  
  // Rate limit extraction (see below)
  // Error handling (see error-handling.mdx)
  
  return res.json()
}

Query Parameters

Query parameters are dynamically added to the URL:
getRepos('username', 1, 30)
// GET /users/username/repos?page=1&per_page=30&sort=updated&direction=desc

Rate Limit Tracking

Header Extraction

GitHub includes rate limit information in every API response header. The hook extracts these values:
const remaining = res.headers.get('x-ratelimit-remaining')
const limit = res.headers.get('x-ratelimit-limit')
const reset = res.headers.get('x-ratelimit-reset')

if (remaining !== null) {
  setRateLimit({ 
    remaining: +remaining, 
    limit: +limit, 
    reset: +reset * 1000  // Convert to milliseconds
  })
}

Rate Limit Object

The rate limit state exposes three properties:
rateLimit.remaining
number
Number of requests remaining in the current window
rateLimit.limit
number
Total request limit per hour (60 or 5000)
rateLimit.reset
number
Unix timestamp (in milliseconds) when the rate limit resets

Visual Indicator

The Header component displays a color-coded rate limit indicator:
  • 🟢 Green → More than 50% available
  • 🟡 Yellow → Between 20% and 50%
  • 🔴 Red → Less than 20%

Response Format

User Profile Response

{
  "login": "username",
  "avatar_url": "https://avatars.githubusercontent.com/u/123456",
  "name": "User Name",
  "company": "@company",
  "blog": "https://example.com",
  "location": "City, Country",
  "bio": "Bio text",
  "twitter_username": "handle",
  "public_repos": 42,
  "public_gists": 10,
  "followers": 100,
  "following": 50
}

Repository Response

[
  {
    "id": 123456789,
    "name": "repo-name",
    "full_name": "owner/repo-name",
    "description": "Repository description",
    "html_url": "https://github.com/owner/repo-name",
    "stargazers_count": 42,
    "forks_count": 10,
    "language": "JavaScript",
    "updated_at": "2026-03-04T12:00:00Z",
    "size": 1024,
    "license": { "name": "MIT License" },
    "open_issues_count": 5
  }
]

Commits Response

[
  {
    "sha": "abc123def456",
    "commit": {
      "author": {
        "name": "Author Name",
        "email": "[email protected]",
        "date": "2026-03-04T12:00:00Z"
      },
      "message": "Commit message"
    },
    "author": {
      "login": "username",
      "avatar_url": "https://avatars.githubusercontent.com/u/123456"
    }
  }
]

Languages Response

{
  "JavaScript": 12345,
  "CSS": 5678,
  "HTML": 1234
}
The values represent bytes of code, not file count or percentage.

API Consumption

Typical request consumption per user search:
  • 1 request → User profile (getUser)
  • 1 request per page → Repositories (getRepos)
  • 1 request per repo → Commits when expanded (getCommits)
  • Up to 12 parallel requests → Language statistics for chart (getLanguages)
Without a token, analyzing a single user can consume 15-20 requests (profile + repos + languages), leaving only 40 requests remaining in the hour.

Token Storage

Personal Access Tokens are stored in browser localStorage:
const saveToken = (t) => {
  setToken(t)
  if (t) localStorage.setItem('gh_token', t)
  else localStorage.removeItem('gh_token')
}
Tokens are stored client-side only. Never commit tokens to version control or expose them in client-side code.

API Documentation

For complete GitHub REST API documentation, see:

Build docs developers (and LLMs) love