Project Overview
This project provides a serverless Cloudflare Workers application that fetches, visualizes, and analyzes GitHub user data. It exposes multiple API endpoints to retrieve contribution heatmaps, badge status, and AI-generated insights. Frontend applications integrate with these routes for real-time profile analytics.
Problem Statement
Developers and teams lack a unified, extensible service to:
- Aggregate GitHub profile metrics across repositories
- Generate visual assets (heatmaps, badges) on the fly
- Receive contextual AI-driven commentary on activity patterns
Main Capabilities
- Contribution Heatmaps: Render SVG calendars showing daily commit activity
- Badge Generation: Produce status badges (e.g., “Top Collaborator”, “Issue Closer”)
- AI Insights: Summarize trends and suggest improvement areas via OpenAI integration
- Extensible API Routes:
/api/heatmap/:username
/api/badge/:username/:badgeType
/api/insights/:username
When to Use
- Embedding dynamic GitHub profile visuals in personal sites or dashboards
- Automating badge updates in README files or status pages
- Providing project maintainers with AI-driven summaries of contributor behavior
- Building internal analytics tools without managing servers
Example: Fetching a Contribution Heatmap
Developers can call the heatmap endpoint directly or within their frontend code.
# Replace YOUR_DOMAIN and USERNAME
curl https://YOUR_DOMAIN/api/heatmap/USERNAME \
-H "Authorization: Bearer $GITHUB_TOKEN" \
--output heatmap.svg
# Display inline in HTML
<img src="https://YOUR_DOMAIN/api/heatmap/USERNAME" alt="Contribution Heatmap">
Use this service when you need up-to-date, on-demand GitHub profile analytics without maintaining backend infrastructure.
Getting Started & Deployment
This guide walks you through installing dependencies, configuring environment variables, and deploying the GitHub Profile Analyzer on Cloudflare Workers using Wrangler.
Prerequisites
- Node.js v14+ and npm or Yarn
- Cloudflare account with Workers & KV enabled
- One or more GitHub Personal Access Tokens (no scopes required)
- Frontend origin URL (e.g. https://localhost:3000)
1. Install Wrangler CLI
Use npm or Yarn to install Wrangler globally:
npm install -g wrangler
# or
yarn global add @cloudflare/wrangler
Authenticate with your Cloudflare account:
wrangler login
2. Clone the Repository
git clone https://github.com/0xarchit/github-profile-analyzer.git
cd github-profile-analyzer
3. Configure wrangler.toml
Create or update wrangler.toml
at project root:
name = "github-profile-analyzer"
type = "javascript"
account_id = "<YOUR_ACCOUNT_ID>"
workers_dev = true
# Bind a KV namespace for caching contributions
kv_namespaces = [
{ binding = "CONTRIB_CACHE", id = "<KV_NAMESPACE_ID>" }
]
[vars]
# These can also be set via Wrangler secrets
FRONTEND_ORIGIN = "https://localhost:3000"
- Replace
<YOUR_ACCOUNT_ID>
with your Cloudflare account ID. - Create a KV namespace in the Cloudflare dashboard and replace
<KV_NAMESPACE_ID>
.
4. Set Environment Variables & Secrets
Store sensitive values as Wrangler secrets:
# Comma-separated GitHub tokens (rotate to avoid rate limits)
wrangler secret put GITHUB_TOKENS
# Your frontend’s origin for CORS checks
wrangler secret put FRONTEND_ORIGIN
You’ll be prompted to paste each value. Wrangler stores these securely and injects them at runtime.
5. Local Development
Run a local dev server with live reloading:
wrangler dev --local --env dev
- Visits APIs at http://127.0.0.1:8787
- Supports testing
/api
,/contributions
,/badge
endpoints against live GitHub
6. Deploy to Cloudflare
Publish your Worker to Cloudflare’s edge:
wrangler publish
On success, Wrangler prints your Worker’s URL, e.g.:
https://github-profile-analyzer.YOUR_SUBDOMAIN.workers.dev
7. Verify the Deployment
- Fetch AI-powered profile report:
curl "https://<your-worker>.workers.dev/api?user=octocat"
- Retrieve SVG heatmap:
curl "https://<your-worker>.workers.dev/contributions?username=octocat"
- Check badge statuses:
curl "https://<your-worker>.workers.dev/api/badges?user=octocat"
Tips & Best Practices
- Rotate multiple GitHub tokens to distribute rate limits.
- Purge or expire KV entries via the Cloudflare dashboard when debugging caching.
- Use
workers_dev = false
and configureroute
&zone_id
in production to bind to a custom domain. - Monitor usage and errors in the Cloudflare dashboard’s Logs & Analytics.
API Reference
This section documents all HTTP endpoints exposed by the Cloudflare Workers in this repository. Each endpoint’s path, parameters, responses, and usage examples appear below.
Badge Extraction Endpoint
Script: badge.js
URL: GET https://<your-domain>/badge?username=<github_username>
Parameters
• username
(required): GitHub login whose achievements you want to probe.
Response (200)
Content-Type: application/json
Cache-Control: max-age=900
{
"pull-shark": "https://github.githubassets.com/assets/pull-shark-default-498c279a747d.png",
"yolo": "https://github.githubassets.com/assets/yolo-default-be0bbff04951.png"
}
Error Responses
- 400 if
username
is missing. - 500 on network or internal errors.
Example
curl "https://<your-domain>/badge?username=octocat"
Contribution Graph Endpoint
Script: contri-graph.js
URL: GET https://<your-domain>/contributions?username=<github_username>
CORS
Only requests with Origin
or Referer
matching your FRONTEND_ORIGIN
are allowed. Others yield 403.
Parameters
• username
(required): GitHub login to render the contribution heatmap.
Response (200)
Content-Type: image/svg+xml
Cache-Control: public, max-age=3600
The body is an SVG heatmap matching GitHub’s dark‐mode style.
Error Responses
- 400 if
username
is missing. - 403 if CORS check fails.
- 500 on GitHub API or rendering errors.
Example (img tag)
<img
src="https://<your-domain>/contributions?username=octocat"
alt="Octocat’s contribution heatmap" />
Global Hit Counter
Script: count.js
URL: GET https://<your-domain>/cnt
Description
Atomically increments a single-row counter in D1 and returns the total hits.
Response (200)
Content-Type: application/json
{ "hits": 42 }
Example
const res = await fetch("https://<your-domain>/cnt");
const { hits } = await res.json();
console.log(`Total hits: ${hits}`);
User‐Specific Count Update
Script: count.js
URL: POST https://<your-domain>/add
Request Body
Content-Type: application/json
{
"username": "octocat",
"increment": 3 // optional, defaults to 1
}
Response (200)
Content-Type: application/json
{
"username": "octocat",
"hits": 7
}
D1 Schema
CREATE TABLE user_counts (
username TEXT PRIMARY KEY,
hits INTEGER DEFAULT 0
);
Example
curl -X POST https://<your-domain>/add \
-H "Content-Type: application/json" \
-d '{"username":"octocat","increment":2}'
Profile Analysis Endpoint
Script: worker.js
URL: GET https://<your-domain>/profile?username=<github_username>
Description
Aggregates GitHub profile data, badges, contributions, and repositories, then applies AI-based scoring and recommendations. Returns a detailed JSON report.
Parameters
• username
(required): GitHub login to analyze.
Response (200)
Content-Type: application/json
{
"profile": {
"login": "octocat",
"name": "The Octocat",
"bio": "GitHub mascot",
"followers": 3500,
"following": 9
},
"badges": { /* slug→URL map */ },
"contributions": { /* heatmap data or SVG string */ },
"repositories": [
{ "name": "hello-world", "stars": 150, "language": "JavaScript" },
/* … */
],
"insights": {
"score": 87,
"recommendations": [
"Add a README to your newer repos.",
"Contribute to open source projects in Go."
]
}
}
Error Responses
- 400 if
username
is missing. - 502 on upstream GitHub/API failures.
Example
import fetch from "node-fetch";
async function getProfile(username) {
const res = await fetch(`https://<your-domain>/profile?username=${username}`);
if (!res.ok) throw new Error(`Error ${res.status}`);
return await res.json();
}
getProfile("octocat").then(console.log);
Frontend Interface
Script: worker.js
URL: GET https://<your-domain>/
Serves the static HTML/CSS/JS UI. Users enter a GitHub username to trigger the Profile Analysis Endpoint. Simply point your browser at the root URL to use the app.
Development & Contribution Guide
This guide helps you understand the codebase, run it locally, add new features, and submit pull requests.
1. Code Organization
- worker.js – Main Cloudflare Worker. Routes requests, aggregates data from GitHub, D1, and AI, then serves JSON or HTML.
- badge.js – Checks GitHub achievement badges via HEAD requests; exports badge asset mapping and status checker.
- contri-graph.js – Fetches contribution data via GraphQL and renders an SVG heatmap.
- count.js – Provides
/cnt
and/add
endpoints to track global and per-user hit counts in D1. - README.md – High-level overview, setup, and available API routes.
2. Prerequisites
- Node.js 16+
- Wrangler 2.x (
npm install -g wrangler
) - A GitHub account and Personal Access Tokens (for GraphQL and API rate limits)
- (Optional) Cloudflare account with a D1 database
3. Local Setup
- Fork and clone the repo:
git clone https://github.com/<your-user>/github-profile-analyzer.git cd github-profile-analyzer
- Install dependencies:
npm install
- Copy environment template and populate values:
cp .env.example .env
# .env GITHUB_TOKENS=token1,token2 # comma-separated GitHub PATs FRONTEND_ORIGIN=https://app.example.com D1_DB_BINDING=GPA_D1_DB # name used in wrangler.toml
- Configure
wrangler.toml
(example):name = "github-profile-analyzer" main = "worker.js" compatibility_date = "2025-01-01" [vars] GITHUB_TOKENS = "${GITHUB_TOKENS}" FRONTEND_ORIGIN = "${FRONTEND_ORIGIN}" [[d1_databases]] binding = "GPA_D1_DB" database_name = "profile_counts"
4. Running Locally
Start the worker in dev mode:
wrangler dev --env .env
- Default bind: http://127.0.0.1:8787
- Test endpoints with cURL or browser:
curl "http://127.0.0.1:8787/?username=octocat" curl "http://127.0.0.1:8787/contributions?username=octocat" curl "http://127.0.0.1:8787/cnt" curl -X POST "http://127.0.0.1:8787/add?username=octocat"
5. Adding New Features
- Define a route in the
handleRequest
function inworker.js
:if (url.pathname === '/status') { return new Response(JSON.stringify({ version: '1.2.0' }), { headers: { 'Content-Type': 'application/json' } }); }
- Implement logic in a new module (e.g.,
status.js
), export a handler:// status.js export function getStatus() { return { uptime: Date.now() - START_TIME }; }
- Import and invoke in
worker.js
:import { getStatus } from './status.js'; // inside handleRequest if (url.pathname === '/status') { return new Response(JSON.stringify(getStatus()), { headers: { 'Content-Type': 'application/json' } }); }
- Test locally via
wrangler dev
and cURL.
6. Extending Badge List
- Open
badge.js
, update thebadgeAssets
map:badgeAssets['new-badge'] = 'https://github.githubassets.com/assets/new-badge-default-...png';
- Ensure slug matches GitHub’s achievement URL pattern.
- Deploy and test:
curl "https://<your-worker>/?username=octocat"
7. Database & Counters
- The D1 binding named in
.env
andwrangler.toml
backs/cnt
and/add
. - To modify schema, use D1 migrations:
wrangler d1 migrations apply GPA_D1_DB
- Review
count.js
for table and query structure.
8. Contribution Workflow
- Branching
- Use
feature/<short-description>
orfix/<short-description>
.
- Use
- Commit Messages
- Start with a verb: “Add”, “Fix”, “Update”.
- Pull Request
- Target
main
branch of0xarchit/github-profile-analyzer
. - Include:
- Feature overview
- Setup changes
- Testing instructions (cURL/browser)
- Target
- Review & Merge
- Address review comments.
- Squash commits when merging to keep history clean.
9. Submission Checklist
- Code compiles and runs under
wrangler dev
- Environment variables documented in
.env.example
- New routes covered by manual tests
- README.md updated with new endpoint(s)
- PR description includes testing steps
Thank you for contributing!