From a1c2c9d2ec431fae198018bb3c7fb8d5d9933061 Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Sat, 30 Aug 2025 16:15:36 +0900 Subject: [PATCH 01/51] Include notice about project sustainability and support Added a notice from the project owner regarding financial support and service sustainability. --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index b3549e74..88e97d94 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,22 @@ + +> ⚠️ **Notice from the Project Owner** +> +> Hello everyone, +> I am the owner of this project. +> +> Currently, due to the increase in users and traffic, the cost of maintaining this service has become quite high, and it is becoming financially difficult to sustain. +> As costs continue to rise, there is a possibility that the service may have to be discontinued. +> We are now at a stage where monetization and financial support are essential. +> +> Your support in the following ways would be greatly appreciated: +> +> 1. Financial support: [GitHub Sponsors](https://github.com/sponsors/ryo-ma) +> 2. Reducing server load through self-hosting (by forking on GitHub and deploying to Vercel) + + # Quick Start Add the following code to your readme. When pasting the code into your profile's From d983a1698dbf1c91f5a10cbfcdf2c04fd834e01f Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Sat, 30 Aug 2025 16:18:19 +0900 Subject: [PATCH 02/51] Fix format --- README.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 88e97d94..cadbc02d 100644 --- a/README.md +++ b/README.md @@ -21,21 +21,23 @@ - > ⚠️ **Notice from the Project Owner** > -> Hello everyone, -> I am the owner of this project. +> Hello everyone,\ +> I am the owner of this project. > -> Currently, due to the increase in users and traffic, the cost of maintaining this service has become quite high, and it is becoming financially difficult to sustain. -> As costs continue to rise, there is a possibility that the service may have to be discontinued. -> We are now at a stage where monetization and financial support are essential. +> Currently, due to the increase in users and traffic, the cost of maintaining +> this service has become quite high, and it is becoming financially difficult +> to sustain.\ +> As costs continue to rise, there is a possibility that the service may have to +> be discontinued.\ +> We are now at a stage where monetization and financial support are essential. > -> Your support in the following ways would be greatly appreciated: +> Your support in the following ways would be greatly appreciated: > -> 1. Financial support: [GitHub Sponsors](https://github.com/sponsors/ryo-ma) -> 2. Reducing server load through self-hosting (by forking on GitHub and deploying to Vercel) - +> 1. Financial support: [GitHub Sponsors](https://github.com/sponsors/ryo-ma) +> 2. Reducing server load through self-hosting (by forking on GitHub and +> deploying to Vercel) # Quick Start From 5cc9b86eb1c2494a87a61bccd43fdfecbc151486 Mon Sep 17 00:00:00 2001 From: Manish Raghavendra <72656694+manishraghavendra@users.noreply.github.com> Date: Mon, 8 Sep 2025 05:36:36 +0530 Subject: [PATCH 03/51] updated deno.json (#369) --- deno.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deno.json b/deno.json index 2212a01b..66acc4b5 100644 --- a/deno.json +++ b/deno.json @@ -1,7 +1,7 @@ { "tasks": { - "start": "deno run -A debug.ts", - "debug": "deno run --inspect-brk -A debug.ts", + "start": "deno run -A main.ts", + "debug": "deno run --inspect-brk -A main.ts", "format": "deno fmt", "lint": "deno lint", "test": "ENV_TYPE=test deno test --allow-env" From cc6947ecad5f2ec203f7ae18757eae0dd2285846 Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Thu, 2 Oct 2025 09:14:22 +0900 Subject: [PATCH 04/51] Add sponsors section to README Added a section for sponsors, listing monthly and one-time contributions. --- README.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/README.md b/README.md index cadbc02d..8d757069 100644 --- a/README.md +++ b/README.md @@ -559,3 +559,38 @@ Check [CONTRIBUTING.md](./CONTRIBUTING.md) for more details. This product is licensed under the [MIT License](https://github.com/ryo-ma/github-profile-trophy/blob/master/LICENSE). + + + +--- + +# 🙏 Sponsors + +Thank you so much to all the amazing sponsors who support this project! +Your contributions help keep development going and make this work possible. + +## 💖 Monthly Sponsors + +* @chenfeng-huang — $10 / month +* @holly-hacker — $2 / month +* @skillerious — $2 / month (since Aug 17, 2024) +* @LudovicGardy — $10 / month (since Aug 15, 2024) +* @alexcastrodev — $10 / month (since Oct 13, 2023, previously $50 / month) +* @great-work-told-is — $10 / month (since Apr 12, 2023) +* @Ilithy — $5 / month (since Jul 21, 2022) +* @weakish — $2 / month (since Jan 22, 2022) +* @Kazuhito00 — $2 / month (since Jan 19, 2022) +* @KATO-Hiro — $2 / month (since Jan 5, 2022) +* @batazor — $2 / month (since Oct 28, 2021) +* @port19x — $2 / month (since Jan 27, 2022) + +## 🎁 One-Time Sponsors + +* @JoqarSabon — $5 (May 24, 2024) +* @syaghoubi00 — $5 (Jan 28, 2024) +* @pylapp — $20 (Jan 15, 2024) +* @Dobefu — $10 (Dec 22, 2024) +* @michele-lorenzoni — $10 (Nov 26, 2024) +* @skillerious — $10 (Aug 17, 2024) + + From 7b6da5d56ec149923becff212dfc44b9f89337a6 Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Thu, 2 Oct 2025 09:15:52 +0900 Subject: [PATCH 05/51] Add GitHub links to sponsor names in README Updated sponsor list with GitHub links for each sponsor. --- README.md | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 8d757069..42efed9f 100644 --- a/README.md +++ b/README.md @@ -560,10 +560,6 @@ Check [CONTRIBUTING.md](./CONTRIBUTING.md) for more details. This product is licensed under the [MIT License](https://github.com/ryo-ma/github-profile-trophy/blob/master/LICENSE). - - ---- - # 🙏 Sponsors Thank you so much to all the amazing sponsors who support this project! @@ -571,26 +567,26 @@ Your contributions help keep development going and make this work possible. ## 💖 Monthly Sponsors -* @chenfeng-huang — $10 / month -* @holly-hacker — $2 / month -* @skillerious — $2 / month (since Aug 17, 2024) -* @LudovicGardy — $10 / month (since Aug 15, 2024) -* @alexcastrodev — $10 / month (since Oct 13, 2023, previously $50 / month) -* @great-work-told-is — $10 / month (since Apr 12, 2023) -* @Ilithy — $5 / month (since Jul 21, 2022) -* @weakish — $2 / month (since Jan 22, 2022) -* @Kazuhito00 — $2 / month (since Jan 19, 2022) -* @KATO-Hiro — $2 / month (since Jan 5, 2022) -* @batazor — $2 / month (since Oct 28, 2021) -* @port19x — $2 / month (since Jan 27, 2022) +* [@chenfeng-huang](https://github.com/chenfeng-huang) — $10 / month +* [@holly-hacker](https://github.com/holly-hacker) — $2 / month +* [@skillerious](https://github.com/skillerious) — $2 / month (since Aug 17, 2024) +* [@LudovicGardy](https://github.com/LudovicGardy) — $10 / month (since Aug 15, 2024) +* [@alexcastrodev](https://github.com/alexcastrodev) — $10 / month (since Oct 13, 2023, previously $50 / month) +* [@great-work-told-is](https://github.com/great-work-told-is) — $10 / month (since Apr 12, 2023) +* [@Ilithy](https://github.com/Ilithy) — $5 / month (since Jul 21, 2022) +* [@weakish](https://github.com/weakish) — $2 / month (since Jan 22, 2022) +* [@Kazuhito00](https://github.com/Kazuhito00) — $2 / month (since Jan 19, 2022) +* [@KATO-Hiro](https://github.com/KATO-Hiro) — $2 / month (since Jan 5, 2022) +* [@batazor](https://github.com/batazor) — $2 / month (since Oct 28, 2021) +* [@port19x](https://github.com/port19x) — $2 / month (since Jan 27, 2022) ## 🎁 One-Time Sponsors -* @JoqarSabon — $5 (May 24, 2024) -* @syaghoubi00 — $5 (Jan 28, 2024) -* @pylapp — $20 (Jan 15, 2024) -* @Dobefu — $10 (Dec 22, 2024) -* @michele-lorenzoni — $10 (Nov 26, 2024) -* @skillerious — $10 (Aug 17, 2024) +* [@JoqarSabon](https://github.com/JoqarSabon) — $5 (May 24, 2024) +* [@syaghoubi00](https://github.com/syaghoubi00) — $5 (Jan 28, 2024) +* [@pylapp](https://github.com/pylapp) — $20 (Jan 15, 2024) +* [@Dobefu](https://github.com/Dobefu) — $10 (Dec 22, 2024) +* [@michele-lorenzoni](https://github.com/michele-lorenzoni) — $10 (Nov 26, 2024) +* [@skillerious](https://github.com/skillerious) — $10 (Aug 17, 2024) From d9e5b3e1d3c6b49af3d3a1e5f085034ccb0e9672 Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Sat, 4 Oct 2025 07:38:21 +0900 Subject: [PATCH 06/51] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 42efed9f..f71f51e8 100644 --- a/README.md +++ b/README.md @@ -582,6 +582,7 @@ Your contributions help keep development going and make this work possible. ## 🎁 One-Time Sponsors +* [@arnabnandy7](https://github.com/arnabnandy7) — $10 (Oct 3, 2025) * [@JoqarSabon](https://github.com/JoqarSabon) — $5 (May 24, 2024) * [@syaghoubi00](https://github.com/syaghoubi00) — $5 (Jan 28, 2024) * [@pylapp](https://github.com/pylapp) — $20 (Jan 15, 2024) From 5b9081719746ed8619d32d7818f2d119ebd147f4 Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Thu, 23 Oct 2025 14:58:41 +0900 Subject: [PATCH 07/51] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f71f51e8..e8a4f4b6 100644 --- a/README.md +++ b/README.md @@ -567,6 +567,7 @@ Your contributions help keep development going and make this work possible. ## 💖 Monthly Sponsors +* [@pmsosa](https://github.com/pmsosa) — $10 / month * [@chenfeng-huang](https://github.com/chenfeng-huang) — $10 / month * [@holly-hacker](https://github.com/holly-hacker) — $2 / month * [@skillerious](https://github.com/skillerious) — $2 / month (since Aug 17, 2024) From 9561b70a17583d6932387503ae0dd3462d86b7ca Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Wed, 5 Nov 2025 01:54:04 +0900 Subject: [PATCH 08/51] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e8a4f4b6..62d37086 100644 --- a/README.md +++ b/README.md @@ -583,6 +583,7 @@ Your contributions help keep development going and make this work possible. ## 🎁 One-Time Sponsors +* [@WilliamCorota](https://github.com/WilliamCorota) — $5 (November 5, 2025) * [@arnabnandy7](https://github.com/arnabnandy7) — $10 (Oct 3, 2025) * [@JoqarSabon](https://github.com/JoqarSabon) — $5 (May 24, 2024) * [@syaghoubi00](https://github.com/syaghoubi00) — $5 (Jan 28, 2024) From 5d093da4780cf9241bea95d5ccd5b1e4ab02be4d Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Wed, 5 Nov 2025 01:55:00 +0900 Subject: [PATCH 09/51] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 62d37086..ce1ce3d2 100644 --- a/README.md +++ b/README.md @@ -583,7 +583,7 @@ Your contributions help keep development going and make this work possible. ## 🎁 One-Time Sponsors -* [@WilliamCorota](https://github.com/WilliamCorota) — $5 (November 5, 2025) +* [@WilliamCorotan](https://github.com/WilliamCorotan) — $5 (November 5, 2025) * [@arnabnandy7](https://github.com/arnabnandy7) — $10 (Oct 3, 2025) * [@JoqarSabon](https://github.com/JoqarSabon) — $5 (May 24, 2024) * [@syaghoubi00](https://github.com/syaghoubi00) — $5 (Jan 28, 2024) From d4b62d889581e4a24818640da66fadaad6f0c5e1 Mon Sep 17 00:00:00 2001 From: Christina Ertural <52951132+QuantumChemist@users.noreply.github.com> Date: Mon, 10 Nov 2025 15:32:00 +0100 Subject: [PATCH 10/51] Replaced createdAt with date of earliest repo for merged accounts (#377) * Refactor UserInfo class to calculate duration based on earliest repository creation date * Remove repository creation date from Repository type and adjust duration calculations to use user activity creation date * Refactor UserInfo class to calculate duration based on earliest repository creation date * Add repository name logging in UserInfo class for debugging * Add logging for earliest repository creation date and duration calculation in UserInfo class * Add repository name and creation date to user repository query * Remove debug logging for repository name and earliest creation date in UserInfo class * deno task format * Refactor UserInfo class to optimize stargazers and languages aggregation, and streamline earliest repository date calculation * undo last commit * Refactor earliest repository date calculation for improved clarity and efficiency * remove info that was used for debugging * deno task format * remove info that was used for debugging --- src/Schemas/index.ts | 1 + src/user_info.ts | 25 ++++++++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/Schemas/index.ts b/src/Schemas/index.ts index 2c7e3f34..8ac83d72 100644 --- a/src/Schemas/index.ts +++ b/src/Schemas/index.ts @@ -54,6 +54,7 @@ export const queryUserRepository = ` stargazers { totalCount } + createdAt } } } diff --git a/src/user_info.ts b/src/user_info.ts index 805402d6..5d1e2867 100644 --- a/src/user_info.ts +++ b/src/user_info.ts @@ -3,6 +3,7 @@ type Stargazers = { totalCount: number }; type Repository = { languages: { nodes: Language[] }; stargazers: Stargazers; + createdAt: string; }; export type GitHubUserRepository = { repositories: { @@ -81,20 +82,30 @@ export class UserInfo { }); } }); + + // Find the earliest repository creation date + let earliestRepoDate = userActivity.createdAt; // start with the oldest possible + + earliestRepoDate = userRepository.repositories.nodes.reduce( + (earliest, node) => { + return new Date(node.createdAt).getTime() < new Date(earliest).getTime() + ? node.createdAt + : earliest; + }, + earliestRepoDate, + ); + const durationTime = new Date().getTime() - - new Date(userActivity.createdAt).getTime(); + new Date(earliestRepoDate).getTime(); const durationYear = new Date(durationTime).getUTCFullYear() - 1970; const durationDays = Math.floor( durationTime / (1000 * 60 * 60 * 24) / 100, ); - const ancientAccount = - new Date(userActivity.createdAt).getFullYear() <= 2010 ? 1 : 0; - const joined2020 = new Date(userActivity.createdAt).getFullYear() == 2020 - ? 1 - : 0; - const ogAccount = new Date(userActivity.createdAt).getFullYear() <= 2008 + const ancientAccount = new Date(earliestRepoDate).getFullYear() <= 2010 ? 1 : 0; + const joined2020 = new Date(earliestRepoDate).getFullYear() == 2020 ? 1 : 0; + const ogAccount = new Date(earliestRepoDate).getFullYear() <= 2008 ? 1 : 0; this.totalCommits = totalCommits; this.totalFollowers = userActivity.followers.totalCount; From b94874a939f928c26573af52f41883e030da6a97 Mon Sep 17 00:00:00 2001 From: Aniket Vaishnav <37221337+OBrutus@users.noreply.github.com> Date: Sat, 22 Nov 2025 04:33:21 +0530 Subject: [PATCH 11/51] fix: deno fmt --check which failed the Github Action flow (#381) --- README.md | 55 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index ce1ce3d2..106433a8 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ > > 1. Financial support: [GitHub Sponsors](https://github.com/sponsors/ryo-ma) > 2. Reducing server load through self-hosting (by forking on GitHub and -> deploying to Vercel) +> deploying to Vercel) # Quick Start @@ -562,34 +562,37 @@ This product is licensed under the # 🙏 Sponsors -Thank you so much to all the amazing sponsors who support this project! -Your contributions help keep development going and make this work possible. +Thank you so much to all the amazing sponsors who support this project! Your +contributions help keep development going and make this work possible. ## 💖 Monthly Sponsors -* [@pmsosa](https://github.com/pmsosa) — $10 / month -* [@chenfeng-huang](https://github.com/chenfeng-huang) — $10 / month -* [@holly-hacker](https://github.com/holly-hacker) — $2 / month -* [@skillerious](https://github.com/skillerious) — $2 / month (since Aug 17, 2024) -* [@LudovicGardy](https://github.com/LudovicGardy) — $10 / month (since Aug 15, 2024) -* [@alexcastrodev](https://github.com/alexcastrodev) — $10 / month (since Oct 13, 2023, previously $50 / month) -* [@great-work-told-is](https://github.com/great-work-told-is) — $10 / month (since Apr 12, 2023) -* [@Ilithy](https://github.com/Ilithy) — $5 / month (since Jul 21, 2022) -* [@weakish](https://github.com/weakish) — $2 / month (since Jan 22, 2022) -* [@Kazuhito00](https://github.com/Kazuhito00) — $2 / month (since Jan 19, 2022) -* [@KATO-Hiro](https://github.com/KATO-Hiro) — $2 / month (since Jan 5, 2022) -* [@batazor](https://github.com/batazor) — $2 / month (since Oct 28, 2021) -* [@port19x](https://github.com/port19x) — $2 / month (since Jan 27, 2022) +- [@pmsosa](https://github.com/pmsosa) — $10 / month +- [@chenfeng-huang](https://github.com/chenfeng-huang) — $10 / month +- [@holly-hacker](https://github.com/holly-hacker) — $2 / month +- [@skillerious](https://github.com/skillerious) — $2 / month (since Aug + 17, 2024) +- [@LudovicGardy](https://github.com/LudovicGardy) — $10 / month (since Aug + 15, 2024) +- [@alexcastrodev](https://github.com/alexcastrodev) — $10 / month (since Oct + 13, 2023, previously $50 / month) +- [@great-work-told-is](https://github.com/great-work-told-is) — $10 / month + (since Apr 12, 2023) +- [@Ilithy](https://github.com/Ilithy) — $5 / month (since Jul 21, 2022) +- [@weakish](https://github.com/weakish) — $2 / month (since Jan 22, 2022) +- [@Kazuhito00](https://github.com/Kazuhito00) — $2 / month (since Jan 19, 2022) +- [@KATO-Hiro](https://github.com/KATO-Hiro) — $2 / month (since Jan 5, 2022) +- [@batazor](https://github.com/batazor) — $2 / month (since Oct 28, 2021) +- [@port19x](https://github.com/port19x) — $2 / month (since Jan 27, 2022) ## 🎁 One-Time Sponsors -* [@WilliamCorotan](https://github.com/WilliamCorotan) — $5 (November 5, 2025) -* [@arnabnandy7](https://github.com/arnabnandy7) — $10 (Oct 3, 2025) -* [@JoqarSabon](https://github.com/JoqarSabon) — $5 (May 24, 2024) -* [@syaghoubi00](https://github.com/syaghoubi00) — $5 (Jan 28, 2024) -* [@pylapp](https://github.com/pylapp) — $20 (Jan 15, 2024) -* [@Dobefu](https://github.com/Dobefu) — $10 (Dec 22, 2024) -* [@michele-lorenzoni](https://github.com/michele-lorenzoni) — $10 (Nov 26, 2024) -* [@skillerious](https://github.com/skillerious) — $10 (Aug 17, 2024) - - +- [@WilliamCorotan](https://github.com/WilliamCorotan) — $5 (November 5, 2025) +- [@arnabnandy7](https://github.com/arnabnandy7) — $10 (Oct 3, 2025) +- [@JoqarSabon](https://github.com/JoqarSabon) — $5 (May 24, 2024) +- [@syaghoubi00](https://github.com/syaghoubi00) — $5 (Jan 28, 2024) +- [@pylapp](https://github.com/pylapp) — $20 (Jan 15, 2024) +- [@Dobefu](https://github.com/Dobefu) — $10 (Dec 22, 2024) +- [@michele-lorenzoni](https://github.com/michele-lorenzoni) — $10 (Nov + 26, 2024) +- [@skillerious](https://github.com/skillerious) — $10 (Aug 17, 2024) From fe11abe6ecc8f46f27f2f7d77b877b3007e32e16 Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Sat, 22 Nov 2025 22:54:13 +0900 Subject: [PATCH 12/51] Optimize code for function duration time --- api/index.ts | 58 ++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/api/index.ts b/api/index.ts index 0534237d..a96d56b4 100644 --- a/api/index.ts +++ b/api/index.ts @@ -34,33 +34,6 @@ async function app(req: Request): Promise { const row = params.getNumberValue("row", CONSTANTS.DEFAULT_MAX_ROW); const column = params.getNumberValue("column", CONSTANTS.DEFAULT_MAX_COLUMN); const themeParam: string = params.getStringValue("theme", "default"); - let theme: Theme = COLORS.default; - if (Object.keys(COLORS).includes(themeParam)) { - theme = COLORS[themeParam]; - } - const marginWidth = params.getNumberValue( - "margin-w", - CONSTANTS.DEFAULT_MARGIN_W, - ); - const paddingHeight = params.getNumberValue( - "margin-h", - CONSTANTS.DEFAULT_MARGIN_H, - ); - const noBackground = params.getBooleanValue( - "no-bg", - CONSTANTS.DEFAULT_NO_BACKGROUND, - ); - const noFrame = params.getBooleanValue( - "no-frame", - CONSTANTS.DEFAULT_NO_FRAME, - ); - const titles: Array = params.getAll("title").flatMap((r) => - r.split(",") - ).map((r) => r.trim()); - const ranks: Array = params.getAll("rank").flatMap((r) => - r.split(",") - ).map((r) => r.trim()); - if (username === null) { const [base] = req.url.split("?"); const error = new Error400( @@ -111,10 +84,37 @@ async function app(req: Request): Promise { error.render(), { status: error.status, - headers: new Headers({ "Content-Type": "text" }), + headers: new Headers({ "Content-Type": "text", "Cache-Control": `public, max-age=${CONSTANTS.CACHE_MAX_AGE}`}), }, ); } + let theme: Theme = COLORS.default; + if (Object.keys(COLORS).includes(themeParam)) { + theme = COLORS[themeParam]; + } + const marginWidth = params.getNumberValue( + "margin-w", + CONSTANTS.DEFAULT_MARGIN_W, + ); + const paddingHeight = params.getNumberValue( + "margin-h", + CONSTANTS.DEFAULT_MARGIN_H, + ); + const noBackground = params.getBooleanValue( + "no-bg", + CONSTANTS.DEFAULT_NO_BACKGROUND, + ); + const noFrame = params.getBooleanValue( + "no-frame", + CONSTANTS.DEFAULT_NO_FRAME, + ); + const titles: Array = params.getAll("title").flatMap((r) => + r.split(",") + ).map((r) => r.trim()); + const ranks: Array = params.getAll("rank").flatMap((r) => + r.split(",") + ).map((r) => r.trim()); + const userKeyCache = ["v1", username].join("-"); const userInfoCached = await cacheProvider.get(userKeyCache) || "{}"; let userInfo = JSON.parse(userInfoCached); @@ -127,7 +127,7 @@ async function app(req: Request): Promise { ErrorPage({ error: userResponseInfo }).render(), { status: userResponseInfo.code, - headers: new Headers({ "Content-Type": "text" }), + headers: new Headers({ "Content-Type": "text", "Cache-Control": `public, max-age=${CONSTANTS.CACHE_MAX_AGE}` }), }, ); } From 72245888deb4c098dba029c668ee5f4ceb6bdb40 Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Sat, 22 Nov 2025 23:12:39 +0900 Subject: [PATCH 13/51] Fix format --- api/index.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/api/index.ts b/api/index.ts index a96d56b4..daa117e2 100644 --- a/api/index.ts +++ b/api/index.ts @@ -84,7 +84,10 @@ async function app(req: Request): Promise { error.render(), { status: error.status, - headers: new Headers({ "Content-Type": "text", "Cache-Control": `public, max-age=${CONSTANTS.CACHE_MAX_AGE}`}), + headers: new Headers({ + "Content-Type": "text", + "Cache-Control": `public, max-age=${CONSTANTS.CACHE_MAX_AGE}`, + }), }, ); } @@ -127,7 +130,10 @@ async function app(req: Request): Promise { ErrorPage({ error: userResponseInfo }).render(), { status: userResponseInfo.code, - headers: new Headers({ "Content-Type": "text", "Cache-Control": `public, max-age=${CONSTANTS.CACHE_MAX_AGE}` }), + headers: new Headers({ + "Content-Type": "text", + "Cache-Control": `public, max-age=${CONSTANTS.CACHE_MAX_AGE}`, + }), }, ); } From 20908aff9736613ffdb8a7adf96aa1e2963a4d15 Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Sat, 22 Nov 2025 23:18:27 +0900 Subject: [PATCH 14/51] Improve cache parformance --- api/index.ts | 14 +++++++++++--- src/utils.ts | 4 +++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/api/index.ts b/api/index.ts index daa117e2..6f39b93b 100644 --- a/api/index.ts +++ b/api/index.ts @@ -13,10 +13,18 @@ import { cacheProvider } from "../src/config/cache.ts"; const serviceProvider = new GithubApiService(); const client = new GithubRepositoryService(serviceProvider).repository; +// Build cache control header with optimized caching strategy +const cacheControlHeader = [ + "public", + `max-age=${CONSTANTS.CACHE_MAX_AGE}`, + `s-maxage=${CONSTANTS.CDN_CACHE_MAX_AGE}`, + `stale-while-revalidate=${CONSTANTS.STALE_WHILE_REVALIDATE}`, +].join(", "); + const defaultHeaders = new Headers( { "Content-Type": "image/svg+xml", - "Cache-Control": `public, max-age=${CONSTANTS.CACHE_MAX_AGE}`, + "Cache-Control": cacheControlHeader, }, ); @@ -86,7 +94,7 @@ async function app(req: Request): Promise { status: error.status, headers: new Headers({ "Content-Type": "text", - "Cache-Control": `public, max-age=${CONSTANTS.CACHE_MAX_AGE}`, + "Cache-Control": cacheControlHeader, }), }, ); @@ -132,7 +140,7 @@ async function app(req: Request): Promise { status: userResponseInfo.code, headers: new Headers({ "Content-Type": "text", - "Cache-Control": `public, max-age=${CONSTANTS.CACHE_MAX_AGE}`, + "Cache-Control": cacheControlHeader, }), }, ); diff --git a/src/utils.ts b/src/utils.ts index 86f90ced..9d529731 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -52,6 +52,8 @@ const HOUR_IN_MILLISECONDS = 60 * 60 * 1000; export const CONSTANTS = { CACHE_MAX_AGE: 18800, + CDN_CACHE_MAX_AGE: 28800, // 8 hours for CDN edge cache + STALE_WHILE_REVALIDATE: 86400, // 24 hours - serve stale while revalidating DEFAULT_PANEL_SIZE: 110, DEFAULT_MAX_COLUMN: 8, DEFAULT_MAX_ROW: 3, @@ -60,7 +62,7 @@ export const CONSTANTS = { DEFAULT_NO_BACKGROUND: false, DEFAULT_NO_FRAME: false, DEFAULT_GITHUB_API: "https://api.github.com/graphql", - DEFAULT_GITHUB_RETRY_DELAY: 1000, + DEFAULT_GITHUB_RETRY_DELAY: 500, REVALIDATE_TIME: HOUR_IN_MILLISECONDS, REDIS_TTL: HOUR_IN_MILLISECONDS * 4, }; From f88e07535bc5258ed302225ddf7f7c199ce25b89 Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Tue, 25 Nov 2025 15:53:25 +0900 Subject: [PATCH 15/51] Fix promises process --- src/Services/GithubApiService.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Services/GithubApiService.ts b/src/Services/GithubApiService.ts index d226e3cb..db43ad5f 100644 --- a/src/Services/GithubApiService.ts +++ b/src/Services/GithubApiService.ts @@ -56,20 +56,16 @@ export class GithubApiService extends GithubRepository { } async requestUserInfo(username: string): Promise { // Avoid to call others if one of them is null - const repository = await this.requestUserRepository(username); - - if (repository instanceof ServiceError) { - Logger.error(repository); - return repository; - } const promises = Promise.allSettled([ + this.requestUserRepository(username), this.requestUserActivity(username), this.requestUserIssue(username), this.requestUserPullRequest(username), ]); - const [activity, issue, pullRequest] = await promises; + const [repository, activity, issue, pullRequest] = await promises; const status = [ + repository.status, activity.status, issue.status, pullRequest.status, @@ -84,7 +80,7 @@ export class GithubApiService extends GithubRepository { (activity as PromiseFulfilledResult).value, (issue as PromiseFulfilledResult).value, (pullRequest as PromiseFulfilledResult).value, - repository, + (repository as PromiseFulfilledResult).value, ); } From 135c24e31c3126c73489ba3550485dd0a070fa1f Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Tue, 25 Nov 2025 16:01:04 +0900 Subject: [PATCH 16/51] Add try catch for github api --- src/Services/GithubApiService.ts | 37 ++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/Services/GithubApiService.ts b/src/Services/GithubApiService.ts index db43ad5f..52be0f21 100644 --- a/src/Services/GithubApiService.ts +++ b/src/Services/GithubApiService.ts @@ -63,25 +63,30 @@ export class GithubApiService extends GithubRepository { this.requestUserIssue(username), this.requestUserPullRequest(username), ]); - const [repository, activity, issue, pullRequest] = await promises; - const status = [ - repository.status, - activity.status, - issue.status, - pullRequest.status, - ]; + try { + const [repository, activity, issue, pullRequest] = await promises; + const status = [ + repository.status, + activity.status, + issue.status, + pullRequest.status, + ]; + + if (status.includes("rejected")) { + Logger.error(`Can not find a user with username:' ${username}'`); + return new ServiceError("Not found", EServiceKindError.NOT_FOUND); + } - if (status.includes("rejected")) { - Logger.error(`Can not find a user with username:' ${username}'`); + return new UserInfo( + (activity as PromiseFulfilledResult).value, + (issue as PromiseFulfilledResult).value, + (pullRequest as PromiseFulfilledResult).value, + (repository as PromiseFulfilledResult).value, + ); + } catch { + Logger.error(`Error fetching user info for username: ${username}`); return new ServiceError("Not found", EServiceKindError.NOT_FOUND); } - - return new UserInfo( - (activity as PromiseFulfilledResult).value, - (issue as PromiseFulfilledResult).value, - (pullRequest as PromiseFulfilledResult).value, - (repository as PromiseFulfilledResult).value, - ); } async executeQuery( From 70619a1348979674864db7a3a5f8f712dca48935 Mon Sep 17 00:00:00 2001 From: Really Him Date: Thu, 27 Nov 2025 01:52:44 -0500 Subject: [PATCH 17/51] Update monthly sponsors list in README.md (#384) Adding @hesreallyhim (me) to the list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 106433a8..69270a40 100644 --- a/README.md +++ b/README.md @@ -567,6 +567,7 @@ contributions help keep development going and make this work possible. ## 💖 Monthly Sponsors +- [@hesreallyhim](https://github.com/hesreallyhim) - $10 / month - [@pmsosa](https://github.com/pmsosa) — $10 / month - [@chenfeng-huang](https://github.com/chenfeng-huang) — $10 / month - [@holly-hacker](https://github.com/holly-hacker) — $2 / month From 4047b3725ae9894e29a32cc80b22e517a854b147 Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Tue, 2 Dec 2025 22:51:07 +0900 Subject: [PATCH 18/51] Support Docker --- Dockerfile | 13 +++++++++++++ docker-compose.yml | 9 +++++++++ 2 files changed, 22 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..99a50349 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM denoland/deno:latest + +# Create working directory +WORKDIR /app + +# Copy source +COPY . . + +# Compile the main app +RUN deno cache main.ts + +# Run the app +CMD ["deno", "run", "-A", "main.ts"] diff --git a/docker-compose.yml b/docker-compose.yml index 9036241a..5d576a0f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,3 +5,12 @@ services: image: redis:latest ports: - "6379:6379" + deno-app: + build: . + volumes: + - .:/app + ports: + - "80:8080" + environment: + - DENO_ENV=development + command: ["deno", "run", "--watch", "-A", "main.ts"] From 805065caaf21c75e9c5d0dd3efffa3bc36325be4 Mon Sep 17 00:00:00 2001 From: ryo-ma Date: Wed, 3 Dec 2025 10:33:37 +0900 Subject: [PATCH 19/51] Change base url --- README.md | 84 ++++++++++++++++++++++++++-------------------------- api/index.ts | 6 ++-- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 69270a40..3d1f79a3 100644 --- a/README.md +++ b/README.md @@ -45,11 +45,11 @@ Add the following code to your readme. When pasting the code into your profile's readme, change the `?username=` value to your GitHub's username. ``` -[![trophy](https://github-profile-trophy.vercel.app/?username=ryo-ma)](https://github.com/ryo-ma/github-profile-trophy) +[![trophy](https://github-profile-trophy.com/?username=ryo-ma)](https://github.com/ryo-ma/github-profile-trophy) ```

- +

## Use theme @@ -57,7 +57,7 @@ readme, change the `?username=` value to your GitHub's username. Add optional parameter of the theme. ``` -[![trophy](https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=onedark)](https://github.com/ryo-ma/github-profile-trophy) +[![trophy](https://github-profile-trophy.com/?username=ryo-ma&theme=onedark)](https://github.com/ryo-ma/github-profile-trophy) ```

@@ -120,7 +120,7 @@ conditions, I will consider adding a trophy. I am waiting for contributions. You can filter the display by specifying the titles of trophy. ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&title=Followers +https://github-profile-trophy.com/?username=ryo-ma&title=Followers ```

@@ -130,7 +130,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&title=Followers If you want to specify multiple titles. ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&title=Stars,Followers +https://github-profile-trophy.com/?username=ryo-ma&title=Stars,Followers ```

@@ -140,7 +140,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&title=Stars,Followers You can also exclude the trophies you don't want to display. ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&title=-Stars,-Followers +https://github-profile-trophy.com/?username=ryo-ma&title=-Stars,-Followers ``` ## Filter by ranks @@ -149,7 +149,7 @@ You can filter the display by specifying the ranks.\ `Available values: SECRET SSS SS S AAA AA A B C` ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&rank=S +https://github-profile-trophy.com/?username=ryo-ma&rank=S ```

@@ -159,7 +159,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&rank=S If you want to specify multiple ranks. ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&rank=S,AAA +https://github-profile-trophy.com/?username=ryo-ma&rank=S,AAA ```

@@ -169,7 +169,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&rank=S,AAA You can also exclude ranks. ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&rank=-C,-B +https://github-profile-trophy.com/?username=ryo-ma&rank=-C,-B ``` **NOTE: Since `UNKNOWN` is denoted by `?`, in order to include or exclude it you @@ -186,19 +186,19 @@ Trophy will be hidden if it exceeds the range of both row and column. Restrict only row ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&row=2 +https://github-profile-trophy.com/?username=ryo-ma&row=2 ``` Restrict only column ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&column=2 +https://github-profile-trophy.com/?username=ryo-ma&column=2 ``` Restrict row & column ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&row=2&column=3 +https://github-profile-trophy.com/?username=ryo-ma&row=2&column=3 ```

@@ -208,7 +208,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&row=2&column=3 Adaptive column ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&column=-1 +https://github-profile-trophy.com/?username=ryo-ma&column=-1 ``` You can set `column` to `-1` to adapt the width to the number of trophies, the @@ -248,7 +248,7 @@ Available themes. ### flat ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=flat +https://github-profile-trophy.com/?username=ryo-ma&theme=flat ```

@@ -258,7 +258,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=flat ### onedark ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=onedark +https://github-profile-trophy.com/?username=ryo-ma&theme=onedark ```

@@ -268,7 +268,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=onedark ### gruvbox ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=gruvbox +https://github-profile-trophy.com/?username=ryo-ma&theme=gruvbox ```

@@ -278,7 +278,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=gruvbox ### dracula ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=dracula +https://github-profile-trophy.com/?username=ryo-ma&theme=dracula ```

@@ -288,7 +288,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=dracula ### monokai ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=monokai +https://github-profile-trophy.com/?username=ryo-ma&theme=monokai ```

@@ -298,7 +298,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=monokai ### chalk ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=chalk +https://github-profile-trophy.com/?username=ryo-ma&theme=chalk ```

@@ -308,7 +308,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=chalk ### nord ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=nord +https://github-profile-trophy.com/?username=ryo-ma&theme=nord ```

@@ -318,7 +318,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=nord ### alduin ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=alduin +https://github-profile-trophy.com/?username=ryo-ma&theme=alduin ```

@@ -328,7 +328,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=alduin ### darkhub ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=darkhub +https://github-profile-trophy.com/?username=ryo-ma&theme=darkhub ```

@@ -338,7 +338,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=darkhub ### juicyfresh ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=juicyfresh +https://github-profile-trophy.com/?username=ryo-ma&theme=juicyfresh ```

@@ -348,7 +348,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=juicyfresh ### buddhism ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=buddhism +https://github-profile-trophy.com/?username=ryo-ma&theme=buddhism ```

@@ -358,7 +358,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=buddhism ### oldie ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=oldie +https://github-profile-trophy.com/?username=ryo-ma&theme=oldie ```

@@ -368,7 +368,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=oldie ### radical ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=radical +https://github-profile-trophy.com/?username=ryo-ma&theme=radical ```

@@ -378,7 +378,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=radical ### onestar ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=onestar +https://github-profile-trophy.com/?username=ryo-ma&theme=onestar ```

@@ -388,7 +388,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=onestar ### discord ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=discord +https://github-profile-trophy.com/?username=ryo-ma&theme=discord ```

@@ -398,7 +398,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=discord ### algolia ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=algolia +https://github-profile-trophy.com/?username=ryo-ma&theme=algolia ```

@@ -408,7 +408,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=algolia ### gitdimmed ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=gitdimmed +https://github-profile-trophy.com/?username=ryo-ma&theme=gitdimmed ```

@@ -418,7 +418,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=gitdimmed ### tokyonight ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=tokyonight +https://github-profile-trophy.com/?username=ryo-ma&theme=tokyonight ```

@@ -428,7 +428,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=tokyonight ### matrix ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=matrix +https://github-profile-trophy.com/?username=ryo-ma&theme=matrix ```

@@ -438,7 +438,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=matrix ### apprentice ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=apprentice +https://github-profile-trophy.com/?username=ryo-ma&theme=apprentice ```

@@ -448,7 +448,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=apprentice ### dark_dimmed ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=dark_dimmed +https://github-profile-trophy.com/?username=ryo-ma&theme=dark_dimmed ```

@@ -458,7 +458,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=dark_dimmed ### dark_lover ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=dark_lover +https://github-profile-trophy.com/?username=ryo-ma&theme=dark_lover ```

@@ -468,7 +468,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=dark_lover ### kimbie_dark ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=kimbie_dark +https://github-profile-trophy.com/?username=ryo-ma&theme=kimbie_dark ```

@@ -478,7 +478,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=kimbie_dark ### aura ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&theme=aura +https://github-profile-trophy.com/?username=ryo-ma&theme=aura ```

@@ -492,7 +492,7 @@ You can put a margin in the width between trophies.\ `Default: margin-w=0` ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&margin-w=15 +https://github-profile-trophy.com/?username=ryo-ma&margin-w=15 ```

@@ -506,7 +506,7 @@ You can put a margin in the height between trophies.\ `Default: margin-h=0` ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&margin-h=15 +https://github-profile-trophy.com/?username=ryo-ma&margin-h=15 ```

@@ -516,7 +516,7 @@ https://github-profile-trophy.vercel.app/?username=ryo-ma&margin-h=15 ## Example layout ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&column=3&margin-w=15&margin-h=15 +https://github-profile-trophy.com/?username=ryo-ma&column=3&margin-w=15&margin-h=15 ```

@@ -530,7 +530,7 @@ You can turn the background transparent.\ `Default: no-bg=false` ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&no-bg=true +https://github-profile-trophy.com/?username=ryo-ma&no-bg=true ```

@@ -544,7 +544,7 @@ You can hide the frames around the trophies.\ `Default: no-frame=false` ``` -https://github-profile-trophy.vercel.app/?username=ryo-ma&no-frame=true +https://github-profile-trophy.com/?username=ryo-ma&no-frame=true ```

diff --git a/api/index.ts b/api/index.ts index 6f39b93b..18dca269 100644 --- a/api/index.ts +++ b/api/index.ts @@ -43,7 +43,7 @@ async function app(req: Request): Promise { const column = params.getNumberValue("column", CONSTANTS.DEFAULT_MAX_COLUMN); const themeParam: string = params.getStringValue("theme", "default"); if (username === null) { - const [base] = req.url.split("?"); + const base = 'https://github-profile-trophy.com'; const error = new Error400( `

@@ -59,7 +59,7 @@ async function app(req: Request): Promise {

You can use this form:

Enter your username and click get trophies

-
+ @@ -73,7 +73,7 @@ async function app(req: Request): Promise {