diff --git a/src/app/(frontend)/map/page.tsx b/src/app/(frontend)/map/page.tsx index 30176f1..18387a0 100644 --- a/src/app/(frontend)/map/page.tsx +++ b/src/app/(frontend)/map/page.tsx @@ -23,6 +23,21 @@ function basemapUrl(map: MapDoc): string | null { return null; } +/** + * Static preview for tile-mode maps: a 2x2 mosaic of the map's own zoom-1 + * tiles covering the whole world square, center-cropped by the card frame. + */ +function tilePreviewUrls(template: string): string[] | null { + if (!template.includes("{z}") || !template.includes("{x}") || !template.includes("{y}")) { + return null; + } + return [0, 1].flatMap((y) => + [0, 1].map((x) => + template.replace("{z}", "1").replace("{x}", String(x)).replace("{y}", String(y)), + ), + ); +} + export default async function MapPickerPage() { const payload = await getPayload({ config: await config }); @@ -70,6 +85,10 @@ export default async function MapPickerPage() { ? (map.factionControl as Faction) : null; const url = basemapUrl(map); + const tileUrls = + map.basemapMode === "tiles" && map.tileUrlTemplate + ? tilePreviewUrls(map.tileUrlTemplate) + : null; const stats = [ map.weather ? { @@ -101,6 +120,18 @@ export default async function MapPickerPage() { alt={map.name} className="size-full object-cover opacity-80 transition-opacity group-hover:opacity-100" /> + ) : tileUrls ? ( + ) : (