spb/market-atlas
Public
TypeScript 96.7%
SQL 1.6%
CSS 0.8%
JavaScript 0.5%
1import type { MetadataRoute } from "next";2import { API_URL } from "@/lib/api";3import { SITE_URL } from "@/lib/site";45/**6 * Segmented sitemap: static pages, exchanges, countries, then quoted instruments per asset class7 * (thin pages without a canonical quote are not listed).8 */9export async function generateSitemaps() {10 return [{ id: "static" }, { id: "exchanges" }, { id: "countries" }, { id: "stocks" }, { id: "etfs" }, { id: "indices" }, { id: "crypto" }, { id: "forex" }, { id: "rates" }, { id: "commodities" }];11}1213const CLASS: Record<string, string[]> = { stocks: ["EQUITY"], etfs: ["ETF", "ETN"], indices: ["INDEX"], crypto: ["CRYPTO"], forex: ["FOREX"], rates: ["TREASURY", "BOND", "INTEREST_RATE"], commodities: ["COMMODITY", "FUTURE"] };1415async function get<T>(path: string): Promise<T | null> {16 try {17 const r = await fetch(`${API_URL}${path}`, { cache: "no-store" });18 if (!r.ok) return null;19 return ((await r.json()) as { data: T }).data;20 } catch {21 return null;22 }23}2425export default async function sitemap({ id: rawId }: { id: string | Promise<string> }): Promise<MetadataRoute.Sitemap> {26 const id = String(await rawId); // Next 16 passes the segment param as a promise27 const now = new Date();28 if (id === "static") {29 return ["", "/markets", "/live", "/stocks", "/etfs", "/indices", "/crypto", "/forex", "/rates", "/commodities", "/exchanges", "/countries", "/events", "/halts", "/filings", "/sources", "/coverage", "/connectors", "/data-health", "/status", "/compare", "/methodology", "/developers", "/licensing"].map((p) => ({ url: `${SITE_URL}${p}`, lastModified: now, changeFrequency: p === "" || p === "/live" ? "always" : "hourly", priority: p === "" ? 1 : 0.7 }));30 }31 if (id === "exchanges") {32 const xs = (await get<Array<{ id: string }>>("/v1/exchanges")) ?? [];33 return xs.map((x) => ({ url: `${SITE_URL}/exchanges/${x.id}`, lastModified: now, changeFrequency: "hourly", priority: 0.6 }));34 }35 if (id === "countries") {36 const cs = (await get<Array<{ code: string }>>("/v1/countries")) ?? [];37 return cs.map((c) => ({ url: `${SITE_URL}/countries/${c.code}`, lastModified: now, changeFrequency: "daily", priority: 0.5 }));38 }39 const classes = CLASS[id] ?? [];40 const out: MetadataRoute.Sitemap = [];41 for (const c of classes) {42 const rows = (await get<Array<{ id: string }>>(`/v1/instruments?asset_class=${c}"ed=1&limit=500`)) ?? [];43 out.push(...rows.map((r) => ({ url: `${SITE_URL}/instruments/${encodeURIComponent(r.id)}`, lastModified: now, changeFrequency: "hourly" as const, priority: 0.6 })));44 }45 return out;46}47