Vitron-Front/app/routes/sitemap[.]xml.tsx
2026-04-29 01:44:16 +03:30

105 lines
2.8 KiB
TypeScript

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<ExploreProduct[]> {
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) => ` <url>
<loc>${baseUrl}${page.path}</loc>
<lastmod>${today}</lastmod>
<changefreq>${page.changefreq}</changefreq>
<priority>${page.priority}</priority>
</url>`,
)
.join("\n");
const productUrls = products
.map((product) => {
const lastmod = product.updatedAt
? new Date(product.updatedAt).toISOString().split("T")[0]
: today;
return ` <url>
<loc>${baseUrl}/product/${product.id}</loc>
<lastmod>${lastmod}</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>`;
})
.join("\n");
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${staticUrls}
${productUrls}
</urlset>`;
return new Response(sitemap, {
status: 200,
headers: {
"Content-Type": "application/xml",
"Cache-Control": "public, max-age=3600", // Cache for 1 hour
},
});
}