Skip to content

Commit e156a5a

Browse files
authored
feat: add ?year= parameter to generate past year monoliths (JhaSourav07#94)
## Description Closes JhaSourav07#79 Adds support for a '?year=' URL parameter that allows users to generate a 3D isometric monolith for any specific past year, not just the default last 365 days. ## Pillar - [ ] 🎨 Pillar 1 - New Theme Design - [ ] 📐 Pillar 2 - Geometric SVG Improvement - [x] 🕐 Pillar 3 -Time zone Logic Optimization - [ ] 🛠️ Other (Bug fix, refactoring, docs) ## Visual Preview **Default (no year param)** ![default](https://github.com/user-attachments/assets/fe196a7f-e423-4876-87a4-1009bfd753ac) **?year=2023** ![2023](https://github.com/user-attachments/assets/aaae24c9-b6a6-4a70-be1e-2655b5120b43) **?year=2024** ![2024](https://github.com/user-attachments/assets/30637c2e-0897-4f0d-90af-7a66e5bd20b9) ## Checklist before requesting a review: - [x] I have read the `CONTRIBUTING.md` file. - [x] I have tested these changes locally ('localhost:3000/api/streak?user=Disha286&year=2023'). - [x] I have run 'npm run format' and 'npm run lint' locally and resolved all errors. - [x] My commits follow the Conventional Commits format. - [x] I have updated 'README.md' if I added a new theme or URL parameter. - [x] I have starred the repo. - [x] I have made sure that I have only one commit to merge in this PR. - [x] The SVG output matches the CommitPulse "premium quality" aesthetic standard.
2 parents 7131b69 + 5923905 commit e156a5a

5 files changed

Lines changed: 116 additions & 25 deletions

File tree

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ URL Parameter > Theme Default > System Fallback
8787
| `speed` | `string` | No | `8s` | Radar scan animation duration (e.g. `4s`, `12s`) |
8888
| `scale` | `string` | No | `linear` | Tower height scaling: `linear` or `log` (logarithmic) |
8989
| `refresh` | `boolean` | No | `false` | Bypass cache for real-time data |
90+
| `year` | `string` | No || Calendar year to render (e.g. `2023`, `2024`) |
9091

9192
### Theme Presets
9293

@@ -123,6 +124,10 @@ URL Parameter > Theme Default > System Fallback
123124
<!-- Fast scan + logarithmic scaling for power users -->
124125

125126
![](https://commitpulse.vercel.app/api/streak?user=jhasourav07&speed=4s&scale=log)
127+
128+
<!-- View contributions for a specific past year -->
129+
130+
![](https://commitpulse.vercel.app/api/streak?user=jhasourav07&year=2023)
126131
```
127132

128133
---

app/api/streak/route.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ export async function GET(request: Request) {
1616
return new NextResponse('Missing "user" parameter', { status: 400 });
1717
}
1818

19+
const yearParam = searchParams.get('year');
20+
const from = yearParam ? `${yearParam}-01-01T00:00:00Z` : undefined;
21+
const to = yearParam ? `${yearParam}-12-31T23:59:59Z` : undefined;
22+
1923
const themeName = searchParams.get('theme') || 'dark';
2024
const isAutoTheme = themeName === 'auto';
2125
const selectedTheme = isAutoTheme ? themes.light : themes[themeName] || themes.dark;
@@ -47,7 +51,7 @@ export async function GET(request: Request) {
4751

4852
const refresh = searchParams.get('refresh') === 'true';
4953

50-
const calendar = await fetchGitHubContributions(user, { bypassCache: refresh });
54+
const calendar = await fetchGitHubContributions(user, { bypassCache: refresh, from, to });
5155
const stats = calculateStreak(calendar);
5256

5357
const svg = generateSVG(stats, params, calendar);

lib/github.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ type GitHubContributionResponse = {
5858

5959
type FetchOptions = {
6060
bypassCache?: boolean;
61+
from?: string;
62+
to?: string;
6163
};
6264

6365
export const GITHUB_CACHE_TTL_MS = 5 * 60 * 1000;
@@ -79,8 +81,12 @@ const contributionsCache = new TTLCache<ContributionCalendar>();
7981
const profileCache = new TTLCache<GitHubUserProfile>();
8082
const reposCache = new TTLCache<GitHubRepo[]>();
8183

82-
function cacheKey(kind: 'contributions' | 'profile' | 'repos', username: string): string {
83-
return `${kind}:${username.toLowerCase()}`;
84+
function cacheKey(
85+
kind: 'contributions' | 'profile' | 'repos',
86+
username: string,
87+
year?: string
88+
): string {
89+
return year ? `${kind}:${username.toLowerCase()}:${year}` : `${kind}:${username.toLowerCase()}`;
8490
}
8591

8692
export function clearGitHubApiCacheForTests(): void {
@@ -98,17 +104,17 @@ export async function fetchGitHubContributions(
98104
username: string,
99105
options: FetchOptions = {}
100106
): Promise<ContributionCalendar> {
101-
const key = cacheKey('contributions', username);
107+
const key = cacheKey('contributions', username, options.from?.substring(0, 4));
102108

103109
if (!options.bypassCache) {
104110
const cached = contributionsCache.get(key);
105111
if (cached) return cached;
106112
}
107113

108114
const query = `
109-
query($login: String!) {
115+
query($login: String!, $from: DateTime, $to: DateTime) {
110116
user(login: $login) {
111-
contributionsCollection {
117+
contributionsCollection(from: $from, to: $to) {
112118
contributionCalendar {
113119
totalContributions
114120
weeks {
@@ -127,7 +133,10 @@ export async function fetchGitHubContributions(
127133
const res = await fetchWithRetry(GITHUB_GRAPHQL_URL, {
128134
method: 'POST',
129135
headers: getHeaders(),
130-
body: JSON.stringify({ query, variables: { login: username } }),
136+
body: JSON.stringify({
137+
query,
138+
variables: { login: username, from: options.from, to: options.to },
139+
}),
131140
cache: 'no-store', // Cache handled by our in-memory layer + API route headers
132141
});
133142

package-lock.json

Lines changed: 89 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
},
1717
"dependencies": {
1818
"@tailwindcss/postcss": "^4.2.2",
19-
"@vercel/analytics": "^2.0.1",
19+
"@vercel/analytics": "^1.6.1",
2020
"framer-motion": "^12.38.0",
2121
"html-to-image": "^1.11.13",
2222
"lucide-react": "^1.8.0",
23-
"next": "16.2.3",
23+
"next": "^16.2.3",
2424
"react": "19.2.4",
2525
"react-dom": "19.2.4"
2626
},

0 commit comments

Comments
 (0)