Skip to main content
The GitHub Contributions component displays a GitHub-style contribution graph showing coding activity over time.

Overview

Location: src/app/components/sections/GithubContributions.tsx This component integrates the react-github-calendar library to visualize GitHub contribution data in the familiar heatmap calendar format.

Implementation

import React, { useEffect, useState } from "react";
import GitHubCalendar from "react-github-calendar";

const GithubContributions: React.FC = () => {
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const timer = setTimeout(() => {
      setLoading(false);
    }, 0);

    return () => clearTimeout(timer);
  }, []);

  return (
    <div
      className="flex py-2 px-3 max-lg:col-span-1 max-lg:row-span-1 col-span-4 row-span-2 col-start-1 row-start-7 bg-spotify-light-dark rounded-xl h-fit"
      id="contribution"
    >
      {loading ? (
        <div className="rounded-md p-4 max-w-lg w-full mx-auto">
          <div className="animate-pulse flex space-x-4">
            <div className="flex-1 space-y-6 py-1">
              <div className="h-2 bg-spotify-green rounded"></div>
              <div className="space-y-3">
                <div className="grid grid-cols-3 gap-4">
                  <div className="h-2 bg-spotify-green rounded col-span-2"></div>
                  <div className="h-2 bg-spotify-green rounded col-span-1"></div>
                </div>
                <div className="h-2 bg-spotify-green rounded"></div>
              </div>
            </div>
          </div>
        </div>
      ) : (
        <div className="w-full items-center content-center justify-center justify-items-center">
          <GitHubCalendar
            username="LuaanNguyen"
            blockSize={11}
            blockMargin={2}
            fontSize={12}
            colorScheme="dark"
            theme={{
              dark: ['#161616', '#0e4429', '#006d32', '#26a641', '#39d353'],
              light: ['#ebedf0', '#9be9a8', '#40c463', '#30a14e', '#216e39']
            }}
          />
        </div>
      )}
    </div>
  );
};

export default GithubContributions;

Features

Loading State

The component displays a skeleton loader while the GitHub calendar data loads:
const [loading, setLoading] = useState(true);

useEffect(() => {
  const timer = setTimeout(() => {
    setLoading(false);
  }, 0);

  return () => clearTimeout(timer);
}, []);
The setTimeout with 0ms delay ensures the loading state is displayed briefly, even if data loads instantly, preventing layout shift.

Skeleton Loader Design

<div className="rounded-md p-4 max-w-lg w-full mx-auto">
  <div className="animate-pulse flex space-x-4">
    <div className="flex-1 space-y-6 py-1">
      <div className="h-2 bg-spotify-green rounded"></div>
      <div className="space-y-3">
        <div className="grid grid-cols-3 gap-4">
          <div className="h-2 bg-spotify-green rounded col-span-2"></div>
          <div className="h-2 bg-spotify-green rounded col-span-1"></div>
        </div>
        <div className="h-2 bg-spotify-green rounded"></div>
      </div>
    </div>
  </div>
</div>
The skeleton uses animate-pulse for a smooth loading animation with Spotify-green placeholder bars.

GitHub Calendar Configuration

username
string
required
GitHub username to fetch contribution data forExample: "LuaanNguyen"
blockSize
number
default:"11"
Size of each contribution square in pixels
blockMargin
number
default:"2"
Spacing between contribution squares in pixels
fontSize
number
default:"12"
Font size for calendar labels (month names, days)
colorScheme
'light' | 'dark'
default:"dark"
Color scheme for the calendar (matches site theme)
theme
object
required
Custom color palette for contribution levels

Color Theme

The component uses a custom dark theme matching GitHub’s contribution graph:
theme: {
  dark: [
    '#161616',  // Level 0: No contributions (darkest)
    '#0e4429',  // Level 1: Low contributions
    '#006d32',  // Level 2: Medium-low contributions
    '#26a641',  // Level 3: Medium-high contributions
    '#39d353',  // Level 4: High contributions (brightest green)
  ],
  light: [
    '#ebedf0',  // Light theme fallback
    '#9be9a8',
    '#40c463',
    '#30a14e',
    '#216e39'
  ]
}
The dark theme colors progress from dark grey (no activity) to bright green (high activity), providing clear visual feedback on contribution frequency.

Grid Layout

Desktop Layout

.github-contributions {
  grid-column: span 4;      /* Takes 4 columns */
  grid-row: span 2;         /* Takes 2 rows */
  grid-column-start: 1;     /* Starts at column 1 */
  grid-row-start: 7;        /* Starts at row 7 */
}

Mobile Responsive

max-lg:col-span-1 max-lg:row-span-1  /* Single cell on tablet/mobile */

Styling

Container Styles

/* Main container */
.github-contributions {
  display: flex;
  padding: 0.5rem 0.75rem;      /* py-2 px-3 */
  background: #121212;           /* bg-spotify-light-dark */
  border-radius: 0.75rem;        /* rounded-xl */
  height: fit-content;           /* h-fit */
}

/* Inner container */
.calendar-wrapper {
  width: 100%;
  align-items: center;
  justify-content: center;
  justify-items: center;
}

Skeleton Loader Styles

/* Skeleton container */
.skeleton {
  border-radius: 0.375rem;       /* rounded-md */
  padding: 1rem;                 /* p-4 */
  max-width: 32rem;              /* max-w-lg */
  width: 100%;
  margin: 0 auto;                /* mx-auto */
}

/* Pulse animation */
@keyframes pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

.animate-pulse {
  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

Data Source

The component fetches contribution data from GitHub’s public API via the react-github-calendar library:
https://github-contributions-api.jogruber.de/v4/{username}
No authentication is required as it uses publicly available contribution data from the GitHub profile.

Calendar Features

The GitHub calendar displays:
  • 12 months of contribution history
  • Week labels (Mon, Wed, Fri)
  • Month labels across the top
  • Hover tooltips showing contribution count for each day
  • Responsive sizing that adapts to container width

Contribution Levels

The calendar uses 5 intensity levels:
LevelColorDescription
0#161616No contributions
1#0e44291-3 contributions
2#006d324-6 contributions
3#26a6417-9 contributions
4#39d35310+ contributions
The exact contribution thresholds are determined by GitHub’s algorithm and may vary.

Error Handling

The react-github-calendar library handles API errors gracefully:
  • Network failures show empty calendar
  • Invalid usernames display error message
  • Rate limiting is handled automatically

Performance

Lazy Loading

The component can be lazy-loaded to improve initial page load:
import dynamic from 'next/dynamic';

const GithubContributions = dynamic(
  () => import('./sections/GithubContributions'),
  { ssr: false }
);

Cleanup

The component properly cleans up timers on unmount:
useEffect(() => {
  const timer = setTimeout(() => {
    setLoading(false);
  }, 0);

  return () => clearTimeout(timer);  // Cleanup
}, []);

Dependencies

{
  "react": "useState, useEffect hooks",
  "react-github-calendar": "GitHub contribution calendar component"
}

Library Version

Install the required package:
npm install react-github-calendar

Accessibility

  • Calendar includes ARIA labels for screen readers
  • Keyboard navigation supported
  • Semantic HTML structure
  • High contrast colors for visibility
  • Focus indicators on interactive elements

Customization Options

To customize the calendar appearance:
Adjust blockSize and blockMargin props:
blockSize={15}      // Larger squares
blockMargin={4}     // More spacing

Build docs developers (and LLMs) love