diff --git a/.env.example b/.env.example
index d4343c2..3dcca8f 100644
--- a/.env.example
+++ b/.env.example
@@ -12,6 +12,7 @@ GITHUB_DISCUSSION_COUNT=10
# Leaderboard source data
LEADERBOARD_SOURCE_URL_TEMPLATE=https://raw.githubusercontent.com/ashkulz/committers.top/gh-pages/_data/locations/{country}.yml
+DISABLE_CALCULATE_LEADERBOARD_ENDPOINT=false
# Redis caching (optional — strongly recommended for leaderboard performance)
# Use either redis://localhost:6379 or include password if enabled: redis://:password@localhost:6379
@@ -24,4 +25,4 @@ REDIS_CONNECT_TIMEOUT_MS=1500
# ── PostgreSQL (local development) ─────────────────
DATABASE_URL=postgresql://devimpact:devimpact@localhost:5432/devimpact?sslmode=disable
-POSTGRES_PASSWORD=CHANGE_THIS_TO_A_LONG_RANDOM_PASSWORD
\ No newline at end of file
+POSTGRES_PASSWORD=CHANGE_THIS_TO_A_LONG_RANDOM_PASSWORD
diff --git a/app/api/calculate-leaderboard/route.ts b/app/api/calculate-leaderboard/route.ts
index 02ae782..5a9c83b 100644
--- a/app/api/calculate-leaderboard/route.ts
+++ b/app/api/calculate-leaderboard/route.ts
@@ -3,7 +3,20 @@ import { calculateLeaderboard } from "@/lib/calculate-leaderboard";
export const runtime = "nodejs";
+function isCalculateLeaderboardDisabled(): boolean {
+ const raw =
+ process.env.DISABLE_CALCULATE_LEADERBOARD_ENDPOINT?.trim().toLowerCase();
+ return raw === "true" || raw === "1" || raw === "yes";
+}
+
export async function POST(request: Request) {
+ if (isCalculateLeaderboardDisabled()) {
+ return NextResponse.json(
+ { success: false, error: "Not found" },
+ { status: 404 },
+ );
+ }
+
const { searchParams } = new URL(request.url);
const country = searchParams.get("country")?.trim();
@@ -26,4 +39,4 @@ export async function POST(request: Request) {
{ status: 502 },
);
}
-}
\ No newline at end of file
+}
diff --git a/components/avatar.tsx b/components/avatar.tsx
new file mode 100644
index 0000000..95ade3b
--- /dev/null
+++ b/components/avatar.tsx
@@ -0,0 +1,33 @@
+import Image from "next/image";
+import { cn } from "@/lib/utils";
+
+type AvatarProps = {
+ src: string;
+ alt: string;
+ size?: number;
+ unoptimized?: boolean;
+ className?: string;
+};
+
+/**
+ * Reusable avatar image component.
+ *
+ */
+export function Avatar({
+ src,
+ alt,
+ size = 32,
+ unoptimized = true,
+ className,
+}: AvatarProps) {
+ return (
+