feat: add SteamGridDB proxy API for non-Steam game images

This commit is contained in:
2026-04-28 23:36:00 +08:00
parent cc34fd17ef
commit 74fe0447ee
5 changed files with 95 additions and 1 deletions
+7 -1
View File
@@ -80,4 +80,10 @@ EMAIL_FROM="DeckyVault <noreply@deckyvault.xyz>"
# CONTACT FORM # CONTACT FORM
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Discord webhook URL for contact/report submissions # Discord webhook URL for contact/report submissions
DISCORD_WEBHOOK_URL="" DISCORD_WEBHOOK_URL=""
# -----------------------------------------------------------------------------
# STEAMGRIDDB
# -----------------------------------------------------------------------------
# API key for SteamGridDB image search proxy (optional — non-Steam game wizard will show no images without it)
STEAMGRIDDB_API_KEY=""
+3
View File
@@ -24,6 +24,7 @@ import { searchUnifiedRoutes } from "@/lib/api/search-unified"
import { gameStubRoutes } from "@/lib/api/game-stub" import { gameStubRoutes } from "@/lib/api/game-stub"
import { gameStatsRoutes } from "@/lib/api/game-stats" import { gameStatsRoutes } from "@/lib/api/game-stats"
import { gamesListingRoutes } from "@/lib/api/games-listing" import { gamesListingRoutes } from "@/lib/api/games-listing"
import { steamgridProxyRoutes } from "@/lib/api/steamgrid-proxy"
const betterAuth = new Elysia({ name: "better-auth" }) const betterAuth = new Elysia({ name: "better-auth" })
.mount(auth.handler) .mount(auth.handler)
@@ -84,6 +85,8 @@ export const app = new Elysia({ prefix: "/api" })
.use(searchUnifiedRoutes) .use(searchUnifiedRoutes)
// Game stub creation // Game stub creation
.use(gameStubRoutes) .use(gameStubRoutes)
// SteamGridDB proxy
.use(steamgridProxyRoutes)
// Game stats aggregation // Game stats aggregation
.use(gameStatsRoutes) .use(gameStatsRoutes)
// Saved games // Saved games
+1
View File
@@ -14,3 +14,4 @@ export { contactRoutes } from "./contact"
export { adminReportRoutes } from "./admin-reports" export { adminReportRoutes } from "./admin-reports"
export { adminPerformanceRoutes } from "./admin-performance" export { adminPerformanceRoutes } from "./admin-performance"
export { adminCommentRoutes } from "./admin-comments" export { adminCommentRoutes } from "./admin-comments"
export { steamgridProxyRoutes } from "./steamgrid-proxy"
+80
View File
@@ -0,0 +1,80 @@
import { Elysia, t } from "elysia"
const STEAMGRIDDB_BASE = "https://www.steamgriddb.com/api/v2"
export const steamgridProxyRoutes = new Elysia({ prefix: "/steamgrid" })
.get(
"/search",
async ({ query, set }) => {
const apiKey = process.env.STEAMGRIDDB_API_KEY
if (!apiKey) {
set.status = 503
return { error: "SteamGridDB API key not configured" }
}
try {
const res = await fetch(
`${STEAMGRIDDB_BASE}/search/autocomplete/${encodeURIComponent(query.q)}`,
{
headers: { Authorization: `Bearer ${apiKey}` },
}
)
if (!res.ok) {
set.status = res.status
return { error: "SteamGridDB search failed" }
}
const data = await res.json()
return data
} catch (err) {
console.error("SteamGridDB search error:", err)
set.status = 500
return { error: "SteamGridDB search failed" }
}
},
{
query: t.Object({ q: t.String({ minLength: 2 }) }),
}
)
.get(
"/grids/:gameId",
async ({ params, query, set }) => {
const apiKey = process.env.STEAMGRIDDB_API_KEY
if (!apiKey) {
set.status = 503
return { error: "SteamGridDB API key not configured" }
}
try {
const url = new URL(`${STEAMGRIDDB_BASE}/grids/game/${params.gameId}`)
// Add dimensions filter for capsule-style images
url.searchParams.set("dimensions", "600x900,342x482")
if (query.styles) {
url.searchParams.set("styles", query.styles)
}
const res = await fetch(url.toString(), {
headers: { Authorization: `Bearer ${apiKey}` },
})
if (!res.ok) {
set.status = res.status
return { error: "SteamGridDB grids fetch failed" }
}
const data = await res.json()
return data
} catch (err) {
console.error("SteamGridDB grids fetch error:", err)
set.status = 500
return { error: "SteamGridDB grids fetch failed" }
}
},
{
params: t.Object({ gameId: t.String() }),
query: t.Object({
styles: t.Optional(t.String()),
}),
}
)
+4
View File
@@ -17,6 +17,10 @@ const nextConfig: NextConfig = {
port: "", port: "",
pathname: "/store_item_assets/**", pathname: "/store_item_assets/**",
}, },
{
protocol: "https",
hostname: "cdn.steamgriddb.com",
},
], ],
}, },
}; };