{"id":50383508,"url":"https://github.com/agoudbg/github-profile-competition","last_synced_at":"2026-05-31T14:00:29.938Z","repository":{"id":360218039,"uuid":"1249086460","full_name":"agoudbg/github-profile-competition","owner":"agoudbg","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-27T06:42:58.000Z","size":276,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-30T13:32:30.477Z","etag":null,"topics":["ai","ai-analysis","ai-generated-content","compare","competition","contribution","github","github-profile","leaderboard","llm","nextjs","profile","rank","react"],"latest_commit_sha":null,"homepage":"https://github-profile-competition.agou.im","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/agoudbg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-25T10:38:23.000Z","updated_at":"2026-05-27T12:11:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/agoudbg/github-profile-competition","commit_stats":null,"previous_names":["agoudbg/github-profile-competition"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/agoudbg/github-profile-competition","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agoudbg%2Fgithub-profile-competition","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agoudbg%2Fgithub-profile-competition/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agoudbg%2Fgithub-profile-competition/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agoudbg%2Fgithub-profile-competition/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/agoudbg","download_url":"https://codeload.github.com/agoudbg/github-profile-competition/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agoudbg%2Fgithub-profile-competition/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33733754,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","ai-analysis","ai-generated-content","compare","competition","contribution","github","github-profile","leaderboard","llm","nextjs","profile","rank","react"],"created_at":"2026-05-30T13:30:28.760Z","updated_at":"2026-05-31T14:00:29.786Z","avatar_url":"https://github.com/agoudbg.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GitHub Profile Competition\n\nA Next.js app that compares two GitHub accounts across public profile, repository, impact, contribution, and activity signals. It can call an OpenAI-compatible chat completion endpoint to generate Chinese analysis while keeping provider configuration on the server.\n\n## Getting started\n\n```bash\npnpm install\npnpm dev\n```\n\nOpen `http://localhost:3000`.\n\n## Environment\n\nCopy `.env.example` to `.env.local` and fill the values you need.\n\n```bash\nGITHUB_TOKEN=optional_github_token\nOPENAI_API_KEY=required_for_real_llm_analysis\nOPENAI_BASE_URL=https://api.openai.com/v1\nOPENAI_MODEL=gpt-4o-mini\nLLM_MAX_TOOL_CALLS=8\nLLM_REQUEST_TIMEOUT_MS=300000\nABUSE_PROTECTION_ENABLED=true\nABUSE_RATE_LIMIT_WINDOW_SECONDS=900\nABUSE_RATE_LIMIT_MAX=5\nABUSE_CONCURRENT_MAX=1\nABUSE_LIMIT_SALT=required_in_production\nLEADERBOARD_DATABASE_PATH=.data/leaderboard.sqlite\nCOMPARISON_CACHE_DATABASE_PATH=.data/comparison-cache.sqlite\n```\n\n`GITHUB_TOKEN` is optional. Without it, the app still uses public REST endpoints and public events, but contribution confidence is lower.\n`LLM_MAX_TOOL_CALLS` controls the maximum total GitHub tool calls the model can make during one comparison. The default is 8 and runtime values are clamped to 4-20.\n`LLM_REQUEST_TIMEOUT_MS` controls the timeout for each provider request. The default is 300000 milliseconds.\n\n## Abuse protection\n\nCompare requests are protected before expensive GitHub and LLM calls run. The default guard allows five valid compare requests per client every 15 minutes and one in-flight compare request per client. Invalid JSON and validation failures return `400` before consuming rate-limit capacity.\n\nSet `ABUSE_LIMIT_SALT` to a stable secret value in production so client identifiers are hashed before they are used as in-memory keys. This lightweight guard is suitable as a first line of defense; for multi-instance serverless deployments, replace the in-memory store in `src/lib/abuse.ts` with Redis, KV, or another shared store.\n\n## Leaderboard\n\nCompared users are saved to SQLite with system-only scores, per-dimension scores, update time, and scoring version. Historical snapshots are retained, while the leaderboard ranks each user by their latest snapshot only. The UI shows up to the top 1,000 users and loads 100 users per page. Set `LEADERBOARD_DATABASE_PATH` to choose the SQLite file location; it defaults to `.data/leaderboard.sqlite`.\n\n## Comparison result cache\n\nComparison results are cached in SQLite for up to 30 days. User pairs are stored as unordered groups, so `a` vs `b` and `b` vs `a` reuse the same cached result. Set `COMPARISON_CACHE_DATABASE_PATH` to choose the SQLite file location; it defaults to `.data/comparison-cache.sqlite`.\n\n## Scripts\n\n```bash\npnpm lint\npnpm typecheck\npnpm test\npnpm build\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagoudbg%2Fgithub-profile-competition","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fagoudbg%2Fgithub-profile-competition","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagoudbg%2Fgithub-profile-competition/lists"}