import { LoaderFunctionArgs } from "@remix-run/node"; import { getInternalApiUrl } from "~/utils/api-config"; interface ExploreProduct { id: string; updatedAt?: string; } interface PaginatedResponse { results: ExploreProduct[]; next: string | null; } // Fetch all products with pagination async function fetchAllProducts(apiBaseUrl: string): Promise { const allProducts: ExploreProduct[] = []; let cursor: string | undefined = undefined; const maxPages = 50; // Safety limit to prevent infinite loops let pageCount = 0; try { while (pageCount < maxPages) { const url = cursor ? `${apiBaseUrl}/api/explore/v1/?cursor=${cursor}` : `${apiBaseUrl}/api/explore/v1/`; const response = await fetch(url); if (!response.ok) break; const data: PaginatedResponse = await response.json(); allProducts.push(...data.results); if (!data.next) break; // Extract cursor from next URL const nextUrl = new URL(data.next); cursor = nextUrl.searchParams.get("cursor") || undefined; if (!cursor) break; pageCount++; } } catch (error) { console.error("Error fetching products for sitemap:", error); } return allProducts; } export async function loader({ request }: LoaderFunctionArgs) { const baseUrl = new URL(request.url).origin; const apiBaseUrl = getInternalApiUrl(); const staticPages = [ { path: "/", priority: "1.0", changefreq: "daily" }, { path: "/explore", priority: "0.9", changefreq: "daily" }, { path: "/login", priority: "0.5", changefreq: "monthly" }, { path: "/profile", priority: "0.7", changefreq: "weekly" }, { path: "/cart", priority: "0.6", changefreq: "daily" }, ]; // Fetch products from API const products = await fetchAllProducts(apiBaseUrl); const today = new Date().toISOString().split("T")[0]; const staticUrls = staticPages .map( (page) => ` ${baseUrl}${page.path} ${today} ${page.changefreq} ${page.priority} `, ) .join("\n"); const productUrls = products .map((product) => { const lastmod = product.updatedAt ? new Date(product.updatedAt).toISOString().split("T")[0] : today; return ` ${baseUrl}/product/${product.id} ${lastmod} weekly 0.8 `; }) .join("\n"); const sitemap = ` ${staticUrls} ${productUrls} `; return new Response(sitemap, { status: 200, headers: { "Content-Type": "application/xml", "Cache-Control": "public, max-age=3600", // Cache for 1 hour }, }); }