Skip to content

Commit 81c071c

Browse files
authored
feat(themes): add random theme selection via ?theme=random (JhaSourav07#115)
## Description Fixes JhaSourav07#66 Adds support for ?theme=random as a valid theme value on the /api/streak endpoint. When passed, the API dynamically picks a random theme from the available themes object on every request, giving users a surprise theme on every load. - Changes made in app/api/streak/route.ts: Added an isRandomTheme flag that checks if theme === 'random'. If true, a random key is picked from the themes object using Math.random(), with a || themes.dark fallback to ensure no crash if the selection somehow fails. - Also extended the cacheControl condition to disable caching when isRandomTheme is true: const cacheControl = refresh || isRandomTheme ? 'no-cache, no-store, must-revalidate' : `public, s-maxage=${secondsToMidnight}, stale-while-revalidate=86400`; Without this, the CDN would cache the first random SVG and serve the same theme to all users for hours, defeating the purpose of the feature entirely. - Changes made in README.md: Added random to the Theme Presets table with _varies_ for all color columns since the values change dynamically on every load. No other files were modified. ## Pillar - 🛠️ Other (Bug fix, refactoring, docs) ## Working Video https://collection.cloudinary.com/dqvm8dce2/73286b27f012f3021856fee1142847bf ## Checklist before requesting a review: - I have read the `CONTRIBUTING.md` file. - I have tested these changes locally (`localhost:3000/api/streak?user=YOUR_USERNAME&theme=random`). - I have run `npm run format` and `npm run lint` locally and resolved all errors. - My commits follow the Conventional Commits format. - I have updated `README.md` added a new 'random' theme preset. - I have started the repo. - I have made sure that i have only one commit to merge in this PR.
2 parents a2291dd + bf1a564 commit 81c071c

3 files changed

Lines changed: 23 additions & 89 deletions

File tree

README.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,15 @@ URL Parameter > Theme Default > System Fallback
9494

9595
### Theme Presets
9696

97-
| Theme | Preview | `bg` | `accent` | `text` |
98-
| ------------------ | ------------------- | -------- | -------- | -------- |
99-
| `auto` | System light / dark | _adapts_ | _adapts_ | _adapts_ |
100-
| `dark` _(default)_ | GitHub dark | `0d1117` | `58a6ff` | `c9d1d9` |
101-
| `neon` | Cyberpunk | `000000` | `ff00ff` | `00ffcc` |
102-
| `dracula` | Dracula Pro | `282a36` | `bd93f9` | `f8f8f2` |
103-
| `github` | GitHub green | `0d1117` | `238636` | `ffffff` |
104-
| `light` | Clean & minimal | `ffffff` | `0969da` | `24292f` |
97+
| Theme | Preview | `bg` | `accent` | `text` |
98+
| ------------------ | ------------------------ | -------- | -------- | -------- |
99+
| `auto` | System light / dark | _adapts_ | _adapts_ | _adapts_ |
100+
| `dark` _(default)_ | GitHub dark | `0d1117` | `58a6ff` | `c9d1d9` |
101+
| `neon` | Cyberpunk | `000000` | `ff00ff` | `00ffcc` |
102+
| `dracula` | Dracula Pro | `282a36` | `bd93f9` | `f8f8f2` |
103+
| `github` | GitHub green | `0d1117` | `238636` | `ffffff` |
104+
| `light` | Clean & minimal | `ffffff` | `0969da` | `24292f` |
105+
| `random` | Surprise theme on reload | _varies_ | _varies_ | _varies_ |
105106

106107
> **`auto` uses CSS `@media (prefers-color-scheme)`** inside the SVG so the badge switches between the `light` and `dark` palettes based on the viewer's OS setting — no JavaScript required. This is ideal for GitHub profile READMEs where visitors may use either mode.
107108

app/api/streak/route.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,16 @@ export async function GET(request: Request) {
2222

2323
const themeName = searchParams.get('theme') || 'dark';
2424
const isAutoTheme = themeName === 'auto';
25-
const selectedTheme = isAutoTheme ? themes.light : themes[themeName] || themes.dark;
25+
const isRandomTheme = themeName === 'random';
26+
const selectedTheme = (() => {
27+
if (isAutoTheme) return themes.light;
28+
if (isRandomTheme) {
29+
const themeKeys = Object.keys(themes);
30+
const randomKey = themeKeys[Math.floor(Math.random() * themeKeys.length)];
31+
return themes[randomKey] || themes.dark;
32+
}
33+
return themes[themeName] || themes.dark;
34+
})();
2635

2736
const rawSpeed = searchParams.get('speed') || '8s';
2837
const speed = /^\d+(\.\d+)?s$/.test(rawSpeed) ? rawSpeed : '8s';
@@ -58,9 +67,10 @@ export async function GET(request: Request) {
5867

5968
// 4. Calculate Cache Control (Reset at UTC Midnight)
6069
const secondsToMidnight = getSecondsUntilUTCMidnight();
61-
const cacheControl = refresh
62-
? 'no-cache, no-store, must-revalidate'
63-
: `public, s-maxage=${secondsToMidnight}, stale-while-revalidate=86400`;
70+
const cacheControl =
71+
refresh || isRandomTheme
72+
? 'no-cache, no-store, must-revalidate'
73+
: `public, s-maxage=${secondsToMidnight}, stale-while-revalidate=86400`;
6474

6575
// 5. Return the Image Response
6676
return new NextResponse(svg, {

package-lock.json

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

0 commit comments

Comments
 (0)