93 lines
2.7 KiB
TypeScript
93 lines
2.7 KiB
TypeScript
import { MetadataRoute } from 'next';
|
|
import { getCategories, getProducts, getArticlesResult } from '../lib/cms';
|
|
import { generateProductSlug } from '../lib/slugify';
|
|
import { resolveLocalized } from '../lib/localization';
|
|
|
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000';
|
|
|
|
const languages = ['th', 'en', 'ja', 'zh', 'vi', 'ko'];
|
|
|
|
function createAlternates(path: string) {
|
|
const alternates: Record<string, string> = {};
|
|
for (const lang of languages) {
|
|
alternates[lang] = `${baseUrl}/${lang}${path}`;
|
|
}
|
|
return alternates;
|
|
}
|
|
|
|
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
|
const [categories, products, articlesResult] = await Promise.all([
|
|
getCategories(),
|
|
getProducts('limit=1000'),
|
|
getArticlesResult(),
|
|
]);
|
|
|
|
const staticPages = [
|
|
'',
|
|
'/shop',
|
|
'/scent-guide',
|
|
'/about',
|
|
'/contact',
|
|
'/faq',
|
|
];
|
|
|
|
const routes: MetadataRoute.Sitemap = staticPages.map((route) => ({
|
|
url: `${baseUrl}/th${route}`,
|
|
lastModified: new Date(),
|
|
changeFrequency: 'daily',
|
|
priority: route === '' ? 1 : 0.8,
|
|
alternates: {
|
|
languages: createAlternates(route),
|
|
},
|
|
}));
|
|
|
|
const categoryRoutes: MetadataRoute.Sitemap = categories.map((category) => ({
|
|
url: `${baseUrl}/th/category/${category.id}`,
|
|
lastModified: new Date(),
|
|
changeFrequency: 'weekly',
|
|
priority: 0.7,
|
|
alternates: {
|
|
languages: createAlternates(`/category/${category.id}`),
|
|
},
|
|
}));
|
|
|
|
const productRoutes: MetadataRoute.Sitemap = products.map((product) => {
|
|
const alternates: Record<string, string> = {};
|
|
let thSlug = '';
|
|
|
|
for (const lang of languages) {
|
|
const localizedName = resolveLocalized(product.name, lang) || (product.brand ? product.brand.name : 'product');
|
|
const slug = generateProductSlug(localizedName, product.id);
|
|
alternates[lang] = `${baseUrl}/${lang}/products/${slug}`;
|
|
if (lang === 'th') thSlug = slug;
|
|
}
|
|
|
|
return {
|
|
url: `${baseUrl}/th/products/${thSlug}`,
|
|
lastModified: new Date(),
|
|
changeFrequency: 'daily',
|
|
priority: 0.9,
|
|
alternates: {
|
|
languages: alternates,
|
|
},
|
|
};
|
|
});
|
|
|
|
const articleRoutes: MetadataRoute.Sitemap = [];
|
|
if (articlesResult.ok && articlesResult.data) {
|
|
articlesResult.data.forEach((article) => {
|
|
articleRoutes.push({
|
|
url: `${baseUrl}/th/article/${article.slug}`,
|
|
lastModified: new Date(article.updatedAt || article.createdAt),
|
|
changeFrequency: 'monthly',
|
|
priority: 0.6,
|
|
alternates: {
|
|
languages: createAlternates(`/article/${article.slug}`),
|
|
},
|
|
});
|
|
});
|
|
}
|
|
|
|
return [...routes, ...categoryRoutes, ...productRoutes, ...articleRoutes];
|
|
}
|