DEV Community

Cover image for Ever Spent Hours Looking for an Open Source Issue to Contribute To? Those Days Are Over.

Ever Spent Hours Looking for an Open Source Issue to Contribute To? Those Days Are Over.

DEV Weekend Challenge: Community

This is a submission for the DEV Weekend Challenge: Community

The Community

Open source contributors — specifically, developers who want to contribute but don't know where to start.

If you've ever searched GitHub for "good first issue," you know the problem: thousands of results, no way to tell which repos actually welcome newcomers, and no sense of whether an issue labeled "easy" will take you an hour or a week. Many "good first issues" sit in abandoned repos where no one will ever review your PR. Others are mislabeled — they require deep domain knowledge despite the friendly tag.

Tools like Good First Issue, Up For Grabs, and GitHub's own search help surface these issues — but they stop at listing them. They don't tell you whether the repository behind an issue is healthy, actively maintained, or will actually review your pull request. They don't estimate how difficult the work really is beyond whatever label someone applied months ago.

The open source contributor community loses potential members every day to this friction. IssueScout is built to close that gap — not by replacing these tools, but by adding the intelligence layer they're missing.

AI analysis for almost all repos

What I Built

IssueScout is an open source issue discovery platform that helps developers find their ideal first contribution. It enriches GitHub's "good first issue" results with two things no existing tool provides:

Explore issues dashboard

1. Community Health Score (0-100) — A 7-factor score computed per repository:

  • Has CONTRIBUTING.md (15 pts)
  • Has a license (10 pts)
  • Has a code of conduct (5 pts)
  • Recent commit activity within 30/90 days (20 pts)
  • Star count as a popularity signal (15 pts)
  • Average issue response time (20 pts)
  • Merged PR count as a maintenance signal (15 pts)

A repo scoring 80+ is actively maintained, welcomes contributors, and will likely review your PR. A repo scoring 20 might have a "good first issue" label but no one home.

2. AI Difficulty Estimation — Each issue gets a difficulty rating (Easy / Medium / Hard) using a two-tier approach: a fast rule-based analyzer checks keywords, labels, and comment count first. If confidence is below 80%, it falls back to GPT-4o-mini for deeper analysis. A purple sparkle icon indicates when AI was used — full transparency, no black boxes.

What else makes IssueScout different:

  • Personalized "For You" tab — During onboarding, IssueScout detects your GitHub languages and starred repo topics, then recommends issues matching your stack with a match score
  • 18 label filters across 4 categories — Beginner-friendly, contribution type, issue area, and events (Hacktoberfest). Labels use OR logic so you can combine freely
  • Bookmarks with archiving — Save issues for later, archive completed ones. Full issue snapshots are preserved even if the original changes on GitHub
  • Progressive loading — Issues appear instantly from GitHub, health scores and difficulty badges fill in asynchronously as enrichment completes. No loading spinners, no waiting
  • Per-user API tokens — Each user's GitHub OAuth token powers their searches (5,000 req/hr per user). The app scales linearly with users instead of hitting a shared rate limit wall
  • Cookie-consented analytics — GA4 only loads after explicit opt-in. Decline and zero tracking scripts touch your browser
  • SEO-ready — Sitemap, robots.txt, JSON-LD structured data with search action, OG images, web app manifest — all driven by environment variables so self-hosters can point to their own domain
  • Dark mode — System preference detection with manual toggle

Demo

Live app: issuescout.dev

Sign in with GitHub to start exploring. The app uses your GitHub OAuth token for API requests, so there's no shared rate limit bottleneck.

How it works:

  1. Sign in with GitHub — IssueScout auto-detects your languages and interests from your repos and stars
  2. Search for issues by language, keyword, or browse "For You" recommendations matched to your stack
  3. Filter by 18 labels across 4 categories, sort by newest/most commented/most reactions/best community
  4. Check the health score — green (70+) means the repo actively welcomes contributors
  5. Check the difficulty — find issues that match your experience level, with AI transparency
  6. Click through to the issue detail page for a full community health breakdown, getting-started guide, and repo stats
  7. Bookmark issues you want to tackle later, archive the ones you've completed

Code

The entire codebase is open source under the MIT license:

Repository:
turazashvili/issuescout.dev

Key files:

How I Built It

Stack: Next.js 16 (App Router) · TypeScript · Tailwind CSS v4 · shadcn/ui · NextAuth v5 · MongoDB Atlas · OpenAI GPT-4o-mini · GitHub GraphQL API · Vercel

Architecture decisions that mattered:

Per-user OAuth tokens instead of a server PAT. GitHub's API gives 5,000 requests/hour per authenticated user. Instead of burning through a single server token, each user's own OAuth token powers their searches. This means the app scales linearly with users — 100 concurrent users = 500K requests/hour of capacity. Tokens are revoked server-side on sign-out.

Two-phase progressive loading. The search API returns raw GitHub results instantly. A separate enrichment endpoint handles health scores and difficulty estimation in the background. Issue cards render immediately with skeleton badges that fill in as enrichment completes. The user never stares at a loading spinner.

Two-level caching. Issue difficulty is cached for 24 hours (L1). Repo health scores are cached permanently in an IndexedRepo collection with stale-while-revalidate at 48 hours (L2). The first user to hit a repo pays the cost; every subsequent user gets instant results. Over time, the IndexedRepo collection builds into a growing database of scored repositories.

Rule-based AI with transparent fallback. Most issues can be classified by keywords and labels alone ("typo" -> Easy, "refactor authentication" -> Hard). GPT-4o-mini only fires when the rule engine isn't confident enough. The purple sparkle on the difficulty badge tells users exactly when AI was involved. This keeps costs minimal and latency low.

Environment-driven configuration. Every deployment-specific value — site URL, NextAuth URL, GA measurement ID — lives in environment variables. Self-hosters can fork the repo, set their own env vars, and have a fully branded instance without changing a single line of code. The cookie consent banner and analytics are opt-in: leave NEXT_PUBLIC_GA_MEASUREMENT_ID unset and no tracking scripts load.

SEO from day one. Dynamic sitemap and robots.txt generated from NEXT_PUBLIC_SITE_URL. JSON-LD structured data with WebSite schema and SearchAction so Google understands the search functionality. Per-page metadata via layout wrappers (since all pages are client components). Edge-rendered OG image with branded design. Web app manifest for PWA-ready installs.

What I learned building this:

  • GitHub's issue search API doesn't support stars: or forks: qualifiers — those only work on repository search. Had to build difficulty filtering as a post-fetch step with over-fetching and client-side filtering.
  • Mongoose's { new: true } option is deprecated in v9 — use { returnDocument: "after" }.
  • NextAuth JWT tokens are static snapshots. Storing mutable state (like onboardingCompleted) in the JWT means it goes stale after the user completes onboarding mid-session. The fix: always verify against the database via an API call.
  • GitHub GraphQL reserves query as a parameter name, so you can't use it as a variable name in your operations — had to rename to $searchQuery.
  • MongoDB's language field name conflicts with text indexes (it's reserved for language override). Renamed to programmingLanguage in the search log model.
  • Radix UI Select with position="item-aligned" (the default) hijacks page scroll — fixed with position="popper" on every SelectContent.

Supported by Vexrail.

Top comments (5)

Collapse
 
jamescarter_001 profile image
James Carter

Wow! My son was looking for these easy issues to contribute. big help! but i think we will use self hosted version, no offense. haha.

starred the repo.

Collapse
 
jackie_cole_man profile image
Jack Coleman

This might be useful, but not sure if really good for newbies.

Collapse
 
dmitriy_tr_b62c23b profile image
D T

Thank you Nikoloz, very insightful. Btw are you on LinkedIn? Wanna follow

Collapse
 
axrisi profile image
Nikoloz Turazashvili (@axrisi)

Thank you! Yes, follow me here:
linkedin.com/in/turazashvili/

Collapse
 
beso_6ac41f4bdc profile image
BT

Very useful! Thanks!