ADR-002: GitHub Projects Showcase
| Status | Accepted |
|---|---|
| Date | 2026-01-01 |
| Decision Makers | Christopher Joseph |
| Technical Story | Communicate GitHub project portfolio to engineers and recruiters |
| Depends On | ADR-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
Option 1: Hybrid Projects Page with Build-time Data Script (Recommended)
Create a /projects page that:
- Curates which projects to display via a
projects.jsonconfig 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:
- Prebuild script (
scripts/fetch-projects.js) runs before Docusaurus build - Script reads
projects.json, fetches GitHub data, writessrc/data/projects.generated.json - React page component at
/src/pages/projects.tsximports the generated data - 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 countlanguage: Primary languagelastUpdated: Last push dateopenIssues: Open issue countlicense: License namefetchedAt: Timestamp for cache freshness display
Categories
| Category | Display Label | Description |
|---|---|---|
active | Active | Currently in development |
maintained | Maintained | Stable, accepting contributions |
historical | Historical | No 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
- Create
projects.jsonwith initial curation - Add Projects link to navbar
- Cross-link from relevant blog posts
- Commit initial
projects.generated.jsonfor 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
| Concern | Mitigation |
|---|---|
| Token in CI/CD | Use GitHub Actions secrets or hosting provider env vars |
| Token in client bundle | Script runs at build time only; token never shipped to browser |
| Rate limits | Authenticated requests get 5,000/hour; batch requests; cache aggressively |
| Private repos | Excluded 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.jsonwhen adding new projects - Cached data may be stale (mitigated by showing sync timestamp)
Risks
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| GitHub API down during build | Low | None | Graceful fallback to cached data |
| Rate limits exceeded | Low | Low | Use token (5k/hr); limit to ~20 projects |
| Stale curated descriptions | Medium | Medium | Quarterly review; compare to GitHub descriptions in CI |
| Token exposure | Low | High | Build-time only; never in client bundle; use secrets |
| Abandoned projects hurt perception | Medium | Low | Use "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
- Project detail pages: Auto-generate
/projects/{slug}from README - Contribution graphs: Show commit activity heatmaps
- Skills matrix: Aggregate technologies across all projects
- Automated curation suggestions: GitHub Action that suggests new projects to add
Related Decisions
- ADR-001: Enable Docs Plugin (enables cross-linking to project documentation)