From bf1a564ff3d773f7373bb453235c13035d5bbdc9 Mon Sep 17 00:00:00 2001 From: Subhooo5 Date: Sat, 16 May 2026 16:10:48 +0530 Subject: [PATCH] feat(themes): add random theme selection via ?theme=random --- README.md | 17 ++++----- app/api/streak/route.ts | 18 +++++++--- package-lock.json | 77 ----------------------------------------- 3 files changed, 23 insertions(+), 89 deletions(-) diff --git a/README.md b/README.md index f398e68..63217ae 100644 --- a/README.md +++ b/README.md @@ -92,14 +92,15 @@ URL Parameter > Theme Default > System Fallback ### Theme Presets -| Theme | Preview | `bg` | `accent` | `text` | -| ------------------ | ------------------- | -------- | -------- | -------- | -| `auto` | System light / dark | _adapts_ | _adapts_ | _adapts_ | -| `dark` _(default)_ | GitHub dark | `0d1117` | `58a6ff` | `c9d1d9` | -| `neon` | Cyberpunk | `000000` | `ff00ff` | `00ffcc` | -| `dracula` | Dracula Pro | `282a36` | `bd93f9` | `f8f8f2` | -| `github` | GitHub green | `0d1117` | `238636` | `ffffff` | -| `light` | Clean & minimal | `ffffff` | `0969da` | `24292f` | +| Theme | Preview | `bg` | `accent` | `text` | +| ------------------ | ------------------------ | -------- | -------- | -------- | +| `auto` | System light / dark | _adapts_ | _adapts_ | _adapts_ | +| `dark` _(default)_ | GitHub dark | `0d1117` | `58a6ff` | `c9d1d9` | +| `neon` | Cyberpunk | `000000` | `ff00ff` | `00ffcc` | +| `dracula` | Dracula Pro | `282a36` | `bd93f9` | `f8f8f2` | +| `github` | GitHub green | `0d1117` | `238636` | `ffffff` | +| `light` | Clean & minimal | `ffffff` | `0969da` | `24292f` | +| `random` | Surprise theme on reload | _varies_ | _varies_ | _varies_ | > **`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. diff --git a/app/api/streak/route.ts b/app/api/streak/route.ts index 60863a7..c131ec2 100644 --- a/app/api/streak/route.ts +++ b/app/api/streak/route.ts @@ -22,7 +22,16 @@ export async function GET(request: Request) { const themeName = searchParams.get('theme') || 'dark'; const isAutoTheme = themeName === 'auto'; - const selectedTheme = isAutoTheme ? themes.light : themes[themeName] || themes.dark; + const isRandomTheme = themeName === 'random'; + const selectedTheme = (() => { + if (isAutoTheme) return themes.light; + if (isRandomTheme) { + const themeKeys = Object.keys(themes); + const randomKey = themeKeys[Math.floor(Math.random() * themeKeys.length)]; + return themes[randomKey] || themes.dark; + } + return themes[themeName] || themes.dark; + })(); const rawSpeed = searchParams.get('speed') || '8s'; const speed = /^\d+(\.\d+)?s$/.test(rawSpeed) ? rawSpeed : '8s'; @@ -58,9 +67,10 @@ export async function GET(request: Request) { // 4. Calculate Cache Control (Reset at UTC Midnight) const secondsToMidnight = getSecondsUntilUTCMidnight(); - const cacheControl = refresh - ? 'no-cache, no-store, must-revalidate' - : `public, s-maxage=${secondsToMidnight}, stale-while-revalidate=86400`; + const cacheControl = + refresh || isRandomTheme + ? 'no-cache, no-store, must-revalidate' + : `public, s-maxage=${secondsToMidnight}, stale-while-revalidate=86400`; // 5. Return the Image Response return new NextResponse(svg, { diff --git a/package-lock.json b/package-lock.json index 5afd9f8..8275a1e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1253,19 +1253,6 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -3444,15 +3431,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/call-bind": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", @@ -7523,18 +7501,6 @@ "node": ">=18" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -7544,19 +7510,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "node_modules/stable-hash": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", @@ -7803,36 +7756,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/terser": { - "version": "5.47.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.47.1.tgz", - "integrity": "sha512-tPbLXTI6ohPASb/1YViL428oEHu6/qv1OxqYnfaonVCFHqx4+wCd95pHrQWsL5X4pl90CTyW9piSAsS2L0VoMw==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "peer": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",