Files
negin-dental-clinic/app/meshkee/sitemap-config.json/route.js
T
alireza-hassaniandClaude Sonnet 5 f16b47966b Initial commit: Negin Dental Clinic website
Next.js (App Router) clone of negindentalclinic.ir, wired to the
Meshkee Website API (blog, contact form, favicon), with on-page SEO
and a scroll-reveal animation sequence on the homepage.

See context.md for full project context.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 18:28:54 +03:30

80 lines
2.8 KiB
JavaScript

import fs from "node:fs";
import path from "node:path";
import { NextResponse } from "next/server";
import { WEBSITE_DOMAIN } from "@/lib/meshkee";
// Published for the Meshkee business dashboard's "Refresh" sitemap button —
// see AI_PROMPT.md ("What the website must publish"). Meshkee's own nginx
// proxy serves the actual /sitemap.xml (and the CMS-driven child sitemaps
// like /sitemap-blogs.xml) from the API; this route only lists this app's
// *static* public pages so the dashboard can fold them into the sitemap
// index. Do not add app/sitemap.ts / app/robots.ts — those paths are owned
// by the Meshkee proxy once this site is live on a Meshkee-managed domain.
export const dynamic = "force-static";
// Route segments that never map to a crawlable public page: dynamic detail
// pages (CMS-managed — Meshkee generates their own sitemap entries), and
// this "meshkee/*" integration namespace itself.
const EXCLUDE_SEGMENT = (segment) =>
segment.startsWith("[") || segment === "meshkee" || segment.startsWith("_");
// Per-path SEO weight. Anything not listed falls back to a sane default.
const PAGE_META = {
"/": { changefreq: "daily", priority: 1.0 },
"/services": { changefreq: "weekly", priority: 0.8 },
"/about-us": { changefreq: "monthly", priority: 0.6 },
"/blog": { changefreq: "daily", priority: 0.7 },
"/contact-us": { changefreq: "monthly", priority: 0.5 },
"/virtual-tour": { changefreq: "yearly", priority: 0.4 },
};
/** Scan app/ for `page.js` files and turn each into a public URL path. */
function scanStaticPages(dir, baseSegments = []) {
const pages = [];
let entries;
try {
entries = fs.readdirSync(dir, { withFileTypes: true });
} catch {
return pages;
}
const hasPage = entries.some(
(e) => e.isFile() && /^page\.(js|jsx|ts|tsx)$/.test(e.name)
);
if (hasPage && !baseSegments.some(EXCLUDE_SEGMENT)) {
const urlPath = "/" + baseSegments.join("/");
pages.push(urlPath === "/" ? "/" : urlPath.replace(/\/$/, ""));
}
for (const entry of entries) {
if (!entry.isDirectory()) continue;
// route groups "(name)" don't appear in the URL
const isGroup = entry.name.startsWith("(") && entry.name.endsWith(")");
const nextSegments = isGroup
? baseSegments
: [...baseSegments, entry.name];
if (EXCLUDE_SEGMENT(entry.name)) continue;
pages.push(...scanStaticPages(path.join(dir, entry.name), nextSegments));
}
return pages;
}
export async function GET() {
const appDir = path.join(process.cwd(), "app");
const paths = scanStaticPages(appDir).sort(
(a, b) => a.split("/").length - b.split("/").length || a.localeCompare(b)
);
const staticPages = paths.map((p) => ({
path: p,
...(PAGE_META[p] || { changefreq: "monthly", priority: 0.5 }),
}));
return NextResponse.json({
baseUrl: `https://${WEBSITE_DOMAIN}`,
staticPages,
});
}