From 23ed51f27cb53a4eb2c723db1ae84fe60ef22452 Mon Sep 17 00:00:00 2001 From: Rifaldo-dev Date: Fri, 3 Jul 2026 00:02:58 +0700 Subject: [PATCH] feat: add .svg embed endpoint Add a new route (app/api/card-svg/[username]/route.ts) that returns a minimal SVG wrapping the existing PNG card via an element. This lets users embed their card in GitHub profile READMEs and other contexts that prefer SVG over PNG from external sources. - gitfut.com/.svg serves the SVG wrapper - ?country=XX override is forwarded to the PNG route - No rendering or extra dependencies - the SVG is a lightweight wrapper - Cache-Control matches the PNG route (public, max-age=300) Also adds a rewrite rule in next.config.ts for the .svg pretty URL, and updates README.md to document both .png and .svg embed formats. --- README.md | 6 ++++ app/api/card-svg/[username]/route.ts | 42 ++++++++++++++++++++++++++++ next.config.ts | 3 ++ 3 files changed, 51 insertions(+) create mode 100644 app/api/card-svg/[username]/route.ts diff --git a/README.md b/README.md index f80f7cb..c8b157a 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,15 @@ Your card lives at a URL. Drop it in your profile README, your portfolio, anywhe [![My GitFut card](https://gitfut.com/YOUR_USERNAME.png)](https://gitfut.com/YOUR_USERNAME) ``` +> **Tip:** some platforms (like GitHub profile READMEs) render SVG more reliably than PNG from external sources. Use `.svg` instead: +> ```md +> [![My GitFut card](https://gitfut.com/YOUR_USERNAME.svg)](https://gitfut.com/YOUR_USERNAME) +> ``` + | | | |---|---| | **`gitfut.com/.png`** | your card, as a live image | +| **`gitfut.com/.svg`** | same card, SVG format (better for GitHub READMEs) | | **`gitfut.com/`** | the full scout report | | **`?country=XX`** | override the flag (e.g. `?country=DZ`) | diff --git a/app/api/card-svg/[username]/route.ts b/app/api/card-svg/[username]/route.ts new file mode 100644 index 0000000..f1fc45c --- /dev/null +++ b/app/api/card-svg/[username]/route.ts @@ -0,0 +1,42 @@ +// SVG wrapper for the embeddable card image. +// gitfut.com/.svg → here (via next.config rewrite). +// +// Returns a minimal SVG that embeds the existing PNG card via an element. +// This lets users embed their card in contexts that only accept SVG (e.g. GitHub +// profile READMEs that block from external domains). The SVG +// itself is tiny - the PNG is still served by the card-image route and cached at +// the CDN; this route just wraps it. No rendering, no fonts, no sharp. +// +// Usage: ![card](https://gitfut.com/username.svg) +// ![card](https://gitfut.com/username.svg?country=id) + +const W = 810; +const H = 1230; + +export async function GET(req: Request, { params }: { params: Promise<{ username: string }> }) { + const { username } = await params; + + // Forward the ?country= override to the PNG route so the flag matches. + const { searchParams } = new URL(req.url); + const country = searchParams.get("country"); + const pngUrl = country + ? `/api/card-image/${username}?country=${encodeURIComponent(country)}` + : `/api/card-image/${username}`; + + // Build an absolute URL from the incoming request origin so the + // works from any host (local dev, preview deployments, production). + const origin = new URL(req.url).origin; + const pngAbsolute = `${origin}${pngUrl}`; + + const svg = ` + +`; + + return new Response(svg, { + headers: { + "Content-Type": "image/svg+xml", + // Match the PNG cache duration so they stay in sync. + "Cache-Control": "public, max-age=300", + }, + }); +} diff --git a/next.config.ts b/next.config.ts index 3da90b6..1d8e16f 100644 --- a/next.config.ts +++ b/next.config.ts @@ -14,6 +14,9 @@ const nextConfig: NextConfig = { // files still win over it regardless. return [ { source: "/:username([a-zA-Z0-9-]+).png", destination: "/api/card-image/:username" }, + // SVG embed: gitfut.com/.svg → SVG wrapper around the PNG card. + // Useful for GitHub profile READMEs and other contexts that prefer SVG. + { source: "/:username([a-zA-Z0-9-]+).svg", destination: "/api/card-svg/:username" }, ]; }, };