ghgraph
v0.0.1
Published
Beautiful GitHub contribution graph component for React with support for public and private contributions
Maintainers
Readme
ghgraph
Beautiful GitHub contribution graph component for React with support for public and private contributions
Features
✅ Public & Private Contributions - Support for both public profiles and private data via API
✅ Zero Configuration - Works out of the box with just a username
✅ Secure by Design - Tokens never leave your server
✅ Customizable Themes - Light, dark, and custom color schemes
✅ Caching Built-in - Smart client-side caching with TTL
✅ TypeScript First - Fully typed with excellent IntelliSense
✅ Framework Agnostic - Works with Next.js, React, or any Node.js backend
Installation
npm install ghgraph
# or
yarn add ghgraph
# or
pnpm add ghgraphQuick Start
Public Data (No Setup Required)
import { ContributionGraph } from 'ghgraph'
export default function App() {
return <ContributionGraph username="torvalds" />
}Private Data (With Your API Route)
Step 1: Create API Route
For Next.js App Router (app/api/github-contributions/route.ts):
import { createGitHubHandler } from 'ghgraph/server'
export const GET = createGitHubHandler({
token: process.env.GITHUB_TOKEN!,
cache: {
enabled: true,
ttl: 3600000, // 1 hour
},
})Step 2: Use Component
import { ContributionGraph } from 'ghgraph'
export default function App() {
return (
<ContributionGraph
username="your-username"
includePrivate
apiEndpoint="/api/github-contributions"
/>
)
}API Reference
ContributionGraph Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| username | string | required | GitHub username |
| includePrivate | boolean | false | Include private contributions via API |
| apiEndpoint | string | '/api/github-contributions' | Custom API endpoint URL |
| theme | 'light' \| 'dark' \| 'auto' | 'auto' | Color theme |
| colors | ThemeColors | undefined | Custom color scheme |
| autoScroll | boolean | false | Auto-scroll to current month |
| showStats | boolean | true | Show contribution stats |
| showYearSelector | boolean | true | Show year dropdown |
| defaultYear | number | Current year | Initial year to display |
| className | string | '' | Additional CSS classes |
| cellSize | 'sm' \| 'md' \| 'lg' | 'md' | Cell size |
| cacheExpiry | number | 3600000 | Cache TTL in milliseconds |
| onYearChange | (year: number) => void | undefined | Year change callback |
| onDataLoad | (data: ContributionData) => void | undefined | Data load callback |
| onError | (error: Error) => void | undefined | Error callback |
ThemeColors Interface
interface ThemeColors {
level0?: string // No contributions
level1?: string // 1-3 contributions
level2?: string // 4-6 contributions
level3?: string // 7-9 contributions
level4?: string // 10+ contributions
today?: string // Today's cell color
specialDate?: string // Special date marker
}Setup Guide
Next.js App Router
Create app/api/github-contributions/route.ts:
import { createGitHubHandler } from 'ghgraph/server'
export const GET = createGitHubHandler({
token: process.env.GITHUB_TOKEN!,
cache: {
enabled: true,
ttl: 3600000,
},
})Next.js Pages Router
Create pages/api/github-contributions.ts:
import { NextApiRequest, NextApiResponse } from 'next'
import { Octokit } from '@octokit/rest'
import { fetchContributionsWithOctokit, fetchPRsWithOctokit } from 'ghgraph/server'
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const { year = new Date().getFullYear() } = req.query
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN })
try {
const [contributions, prs] = await Promise.all([
fetchContributionsWithOctokit(octokit, Number(year)),
fetchPRsWithOctokit(octokit, Number(year)),
])
res.json({
contributions: contributions.contributions,
prs: prs.length,
})
} catch (error) {
res.status(500).json({ error: 'Failed to fetch data' })
}
}Express.js
import express from 'express'
import { createGitHubHandler } from 'ghgraph/server'
const app = express()
const handler = createGitHubHandler({
token: process.env.GITHUB_TOKEN!,
cache: { enabled: true },
})
app.get('/api/github-contributions', async (req, res) => {
const request = new Request(`http://localhost${req.url}`)
const response = await handler(request)
const data = await response.json()
res.json(data)
})Customization
Custom Colors
<ContributionGraph
username="torvalds"
colors={{
level0: '#ebedf0',
level1: '#9be9a8',
level2: '#40c463',
level3: '#30a14e',
level4: '#216e39',
}}
/>Custom Cell Size
<ContributionGraph
username="torvalds"
cellSize="lg"
/>Auto-scroll to Current Month
<ContributionGraph
username="torvalds"
autoScroll
/>Hide Stats or Year Selector
<ContributionGraph
username="torvalds"
showStats={false}
showYearSelector={false}
/>Advanced Usage
Custom Data Fetching Hook
import { useContributionData } from 'ghgraph'
function MyComponent() {
const { data, loading, error, refetch } = useContributionData({
username: 'torvalds',
includePrivate: false,
year: 2024,
})
if (loading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
return <div>Total: {data.contributions.totalContributions}</div>
}Manual Cache Control
import { clearCache, clearAllCache } from 'ghgraph'
// Clear specific user/year cache
clearCache('torvalds', 2024)
// Clear all ghgraph cache
clearAllCache()Getting a GitHub Token
- Go to GitHub Settings > Developer Settings > Personal Access Tokens
- Click "Generate new token (classic)"
- Select scopes:
read:user- Read user profile datarepo- Access private repositories (for private contributions)
- Copy the token and add it to your
.envfile:
GITHUB_TOKEN=ghp_your_token_hereSecurity Best Practices
- ✅ Never expose tokens in client-side code
- ✅ Always use environment variables for tokens
- ✅ Keep tokens in server-side API routes only
- ✅ Use
.env.localand add it to.gitignore - ✅ Rotate tokens periodically
Caching
Client-Side Caching
The component automatically caches data in localStorage with a 1-hour default TTL. You can customize this:
<ContributionGraph
username="torvalds"
cacheExpiry={7200000} // 2 hours
/>Server-Side Caching
The API handler includes in-memory caching:
createGitHubHandler({
token: process.env.GITHUB_TOKEN!,
cache: {
enabled: true,
ttl: 3600000, // 1 hour
adapter: 'memory', // Future: 'redis'
},
})TypeScript Support
The package is written in TypeScript and includes full type definitions:
import type {
ContributionGraphProps,
ContributionData,
ThemeColors,
} from 'ghgraph'Troubleshooting
"Failed to fetch contributions"
- Public users: Verify the username is correct
- Private data: Ensure your API route is working and the token is valid
CORS Errors
If using a custom API endpoint on a different domain, ensure CORS is configured:
export async function GET(request: Request) {
const response = await handler(request)
response.headers.set('Access-Control-Allow-Origin', '*')
return response
}Styling Issues
The component uses Tailwind-style classes. If you're not using Tailwind, import the provided CSS:
import 'ghgraph/dist/styles.css'Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT © Pulkit
