Skip to main content

ADR-002: GitHub Projects Showcase

StatusAccepted
Date2026-01-01
Decision MakersChristopher Joseph
Technical StoryCommunicate GitHub project portfolio to engineers and recruiters
Depends OnADR-001 (Enable Docs Plugin)

Summary for All Readers

This proposal creates a curated portfolio page at /projects showing selected GitHub projects with live statistics (stars, recent activity). Projects are hand-picked and organized by category rather than showing everything automatically. The page loads quickly because data is collected when the site is published, not when visitors view it.

For recruiters: See demonstrated skills, project impact, and technical depth at a glance. For engineers: Discover projects, view live stats, and find related blog posts and documentation.

Context and Problem Statement

As an engineer, communicating the breadth and depth of GitHub projects is valuable for:

  • Recruiters: Understanding technical capabilities and active contributions
  • Engineers: Discovering interesting projects, potential collaboration opportunities
  • Personal branding: Demonstrating continuous learning and open source involvement

Currently, the only GitHub visibility is a navbar link to the organization. There's no curated view of projects, their status, or their significance.

Decision Drivers

  • Curation over automation: Highlight meaningful projects, not just everything
  • Fresh data: Show current stars, activity, and status without manual updates
  • Context: Explain why projects matter, not just metadata
  • Performance: Data fetched at build time, no slow API calls when visitors browse
  • Resilience: Site builds should never fail due to GitHub API issues
  • Maintainability: Simple configuration, minimal ongoing effort
  • Audience awareness: Different needs for recruiters vs. technical visitors

Considered Options

Create a /projects page that:

  • Curates which projects to display via a projects.json config file
  • Fetches live metadata (stars, language, last updated) from GitHub API at build time using a simple Node.js script
  • Allows adding descriptions, categories, impact statements, and skills demonstrated
  • Groups projects by skill area and status

Implementation approach:

  1. Prebuild script (scripts/fetch-projects.js) runs before Docusaurus build
  2. Script reads projects.json, fetches GitHub data, writes src/data/projects.generated.json
  3. React page component at /src/pages/projects.tsx imports the generated data
  4. Graceful fallback to cached data if API fails

Pros:

  • Full curation control over which projects appear and how they're presented
  • Simpler than a Docusaurus plugin (easier to debug and maintain)
  • Live metadata without runtime API calls
  • Rich context for each project
  • Fast page loads (static HTML)
  • Builds succeed even if GitHub is down

Cons:

  • Requires build to update stats (deploy triggers fresh data)
  • Need to commit cached data for fallback

Option 2: Custom Docusaurus Plugin

Hook into Docusaurus lifecycle methods (loadContent) for data fetching.

Pros:

  • Integrated with Docusaurus build pipeline
  • Access to plugin lifecycle hooks

Cons:

  • More complex to implement and debug
  • Tied to Docusaurus internals
  • Overkill for this use case

Option 3: GitHub Profile Widget (Embed)

Use GitHub's profile README or third-party widgets to embed project data.

Pros: Zero development effort, always up-to-date Cons: No curation control, inconsistent styling, external dependency

Option 4: Static Markdown Projects Page

Manually maintain a Markdown page listing projects.

Pros: Simple, no API needed Cons: Data goes stale quickly, manual maintenance burden

Decision Outcome

Chosen option: Option 1 - Hybrid Projects Page with Build-time Data Script

This balances curation (what recruiters and engineers want to see) with freshness (live stats that build credibility), while keeping implementation simple and resilient.

Data Model

Configuration File (projects.json)

{
"$schema": "./projects.schema.json",
"projects": [
{
"repo": "amiable-dev/stentorosaur",
"category": "active",
"featured": true,
"skills": ["TypeScript", "Plugin Development", "GitHub API"],
"title": "Stentorosaur",
"description": "GitHub-issue-based status monitoring plugin for Docusaurus",
"impact": "Powers real-time status pages with zero infrastructure",
"role": "Creator & Maintainer",
"highlights": [
"Published to npm with 500+ weekly downloads",
"Powers the /status page on this site"
],
"tags": ["docusaurus", "monitoring", "open-source"],
"relatedPosts": ["/stentorosaur-release"],
"relatedDocs": ["/docs/adrs/ADR-002-github-projects-showcase"]
}
]
}

Enriched at Build Time

The script adds from GitHub API:

  • stars: Star count
  • language: Primary language
  • lastUpdated: Last push date
  • openIssues: Open issue count
  • license: License name
  • fetchedAt: Timestamp for cache freshness display

Categories

CategoryDisplay LabelDescription
activeActiveCurrently in development
maintainedMaintainedStable, accepting contributions
historicalHistoricalNo longer maintained, preserved for reference

Implementation Plan

Phase 1: Build Script

Create scripts/fetch-projects.js:

// Pseudocode
1. Read projects.json
2. For each project:
- Fetch GitHub API (with GITHUB_TOKEN from env)
- Merge curated data with API response
3. Write to src/data/projects.generated.json
4. On API failure:
- Log warning (don't fail build)
- Use existing cached file if available
- Mark project with `dataStale: true`

Add to package.json:

{
"scripts": {
"prebuild": "node scripts/fetch-projects.js",
"build": "docusaurus build"
}
}

Phase 2: Projects Page Component

Create /src/pages/projects.tsx:

  • Hero section: "What I Build" with portfolio summary
  • Featured projects section (1-2 expanded cards)
  • Skill-based groupings (alternative to just Active/Historical)
  • Project cards showing:
    • Title and curated description
    • Impact statement (recruiter-friendly)
    • Stars, language, last activity badges
    • Skills/tech stack tags
    • Links to repo, blog posts, docs
  • Filter by category and skill
  • "Last synced" timestamp for transparency

Phase 3: Integration

  1. Create projects.json with initial curation
  2. Add Projects link to navbar
  3. Cross-link from relevant blog posts
  4. Commit initial projects.generated.json for fallback

Phase 4: Styling

  • Match site theme (pink-red light, cyan-blue dark)
  • Responsive design for mobile
  • Accessible cards (ARIA labels, keyboard navigation)
  • Hover states and visual hierarchy

Error Handling and Resilience

Key principle: The build should never fail due to GitHub API issues.

Security Considerations

ConcernMitigation
Token in CI/CDUse GitHub Actions secrets or hosting provider env vars
Token in client bundleScript runs at build time only; token never shipped to browser
Rate limitsAuthenticated requests get 5,000/hour; batch requests; cache aggressively
Private reposExcluded by default; only public repos in projects.json

UI Design

┌─────────────────────────────────────────────────────────────┐
│ What I Build │
│ Open source projects and technical explorations │
│ Last synced: Jan 1, 2026 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─ FEATURED ───────────────────────────────────────────┐ │
│ │ Stentorosaur ⭐ 42 │ │
│ │ GitHub-issue-based status monitoring for Docusaurus │ │
│ │ │ │
│ │ IMPACT: Powers real-time status pages with zero │ │
│ │ infrastructure costs │ │
│ │ │ │
│ │ Skills: TypeScript, Plugin Dev, GitHub API │ │
│ │ Role: Creator & Maintainer │ │
│ │ │ │
│ │ [View Repo] [Read Blog Post] [See Architecture] │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ─── By Skill ─────────────────────────────────────────── │
│ [All] [TypeScript] [Python] [DevOps] [Frontend] │
│ │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
│ │ amiable-docusaurus │ │ cli-tool-example │ │
│ │ This website │ │ Python CLI framework │ │
│ │ ⭐ 12 TypeScript │ │ ⭐ 89 Python │ │
│ │ [ACTIVE] │ │ [MAINTAINED] │ │
│ └─────────────────────────┘ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

Consequences

Positive

  • Curated portfolio presentation tailored for recruiters
  • Live stats build credibility (not manually inflated)
  • Skill-based grouping shows breadth of capabilities
  • Cross-linking with blog and docs content
  • Resilient builds that succeed regardless of GitHub availability
  • Simple implementation (prebuild script vs. complex plugin)

Negative

  • Build-time data means stats update only on deploy
  • Need to update projects.json when adding new projects
  • Cached data may be stale (mitigated by showing sync timestamp)

Risks

RiskLikelihoodImpactMitigation
GitHub API down during buildLowNoneGraceful fallback to cached data
Rate limits exceededLowLowUse token (5k/hr); limit to ~20 projects
Stale curated descriptionsMediumMediumQuarterly review; compare to GitHub descriptions in CI
Token exposureLowHighBuild-time only; never in client bundle; use secrets
Abandoned projects hurt perceptionMediumLowUse "Historical" label; limit display to meaningful work

Success Metrics

  • Projects page becomes top-5 visited page within 6 months
  • Recruiters mention portfolio or projects in interviews
  • Engineers engage with project links (GitHub referrals from site)
  • Build success rate remains >99% (API issues don't cause failures)

Future Enhancements

  1. Project detail pages: Auto-generate /projects/{slug} from README
  2. Contribution graphs: Show commit activity heatmaps
  3. Skills matrix: Aggregate technologies across all projects
  4. Automated curation suggestions: GitHub Action that suggests new projects to add
  • ADR-001: Enable Docs Plugin (enables cross-linking to project documentation)