Files
mashinify/scripts/generate-sitemap-config.mjs
Alireza HassaniandCursor 5a6ef9e0e0 Route user products as /user-products/{id}/{slug}.
Load details via by-id, build links from pathSlug/title, redirect legacy slug URLs, and update the sitemap template.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 15:41:31 +03:30

112 lines
3.0 KiB
JavaScript

/**
* Scans app page routes and writes src/lib/sitemap-config.generated.json
* for GET /meshkee/sitemap-config.json (Meshkee sitemap sync).
*/
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const appDir = path.join(root, "src", "app");
const outFile = path.join(root, "src", "lib", "sitemap-config.generated.json");
const EXCLUDE_SEGMENTS = new Set([
"api",
"meshkee",
"admin",
"auth",
"login",
"checkout",
"cart",
"account",
]);
const PRIORITY = {
"/": { changefreq: "daily", priority: 1.0 },
"/user-products": { changefreq: "daily", priority: 0.9 },
"/categories": { changefreq: "weekly", priority: 0.8 },
"/blog": { changefreq: "weekly", priority: 0.8 },
"/about": { changefreq: "monthly", priority: 0.6 },
"/contact": { changefreq: "monthly", priority: 0.5 },
};
function websiteDomain() {
return (
process.env.NEXT_PUBLIC_SITE_DOMAIN ||
process.env.NEXT_PUBLIC_WEBSITE_DOMAIN ||
process.env.WEBSITE_DOMAIN ||
"www.mashinify.com"
);
}
function walkPages(dir, segments = []) {
/** @type {string[]} */
const pages = [];
if (!fs.existsSync(dir)) return pages;
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
const full = path.join(dir, entry.name);
if (entry.isDirectory()) {
if (EXCLUDE_SEGMENTS.has(entry.name)) continue;
if (/^\[.+\]$/.test(entry.name) || /^\(.+\)$/.test(entry.name)) {
if (/^\(.+\)$/.test(entry.name)) {
pages.push(...walkPages(full, segments));
}
continue;
}
pages.push(...walkPages(full, [...segments, entry.name]));
continue;
}
if (
entry.name === "page.tsx" ||
entry.name === "page.ts" ||
entry.name === "page.jsx" ||
entry.name === "page.js"
) {
const routePath = segments.length ? `/${segments.join("/")}` : "/";
pages.push(routePath);
}
}
return pages;
}
function main() {
const paths = [...new Set(walkPages(appDir))].sort((a, b) => {
if (a === "/") return -1;
if (b === "/") return 1;
return a.localeCompare(b);
});
const staticPages = paths.map((routePath) => {
const meta = PRIORITY[routePath] ?? {
changefreq: "monthly",
priority: 0.5,
};
return { path: routePath, ...meta };
});
const domain = websiteDomain().replace(/^https?:\/\//, "").replace(/\/+$/, "");
const config = {
baseUrl: `https://${domain}`,
staticPages,
// Mashinify public paths differ from Meshkee catalog defaults.
templates: {
userProduct: "/user-products/{id}/{slug}",
blog: "/blog/{slug}",
},
};
fs.mkdirSync(path.dirname(outFile), { recursive: true });
fs.writeFileSync(outFile, `${JSON.stringify(config, null, 2)}\n`, "utf8");
console.log(
`Wrote ${path.relative(root, outFile)} (${staticPages.length} static pages)`,
);
}
main();