diff --git a/FrontEnd/my-app/app/robots.ts b/FrontEnd/my-app/app/robots.ts new file mode 100644 index 000000000..c8d0a4465 --- /dev/null +++ b/FrontEnd/my-app/app/robots.ts @@ -0,0 +1,17 @@ +import type { MetadataRoute } from 'next'; + +const SITE_URL = + process.env.NEXT_PUBLIC_SITE_URL?.replace(/\/$/, '') ?? 'https://stellarearn.app'; + +export default function robots(): MetadataRoute.Robots { + return { + rules: [ + { + userAgent: '*', + allow: '/', + disallow: ['/api/', '/admin', '/*/admin', '/settings', '/*/settings'], + }, + ], + sitemap: `${SITE_URL}/sitemap.xml`, + }; +} \ No newline at end of file diff --git a/FrontEnd/my-app/app/sitemap.ts b/FrontEnd/my-app/app/sitemap.ts new file mode 100644 index 000000000..272fae216 --- /dev/null +++ b/FrontEnd/my-app/app/sitemap.ts @@ -0,0 +1,58 @@ +import type { MetadataRoute } from 'next'; +import { getQuests } from '@/lib/api/quests'; +import { locales } from '@/lib/i18n/config'; + +const SITE_URL = + process.env.NEXT_PUBLIC_SITE_URL?.replace(/\/$/, '') ?? 'https://stellarearn.app'; + +// Static, locale-independent-content routes worth indexing. +const STATIC_ROUTES = ['', '/quests', '/rewards']; + +const QUEST_PAGE_SIZE = 100; +const MAX_QUEST_PAGES = 50; // safety cap (~5,000 quests) so a runaway API can't hang the build + +async function getActiveQuestIds(): Promise { + const ids: string[] = []; + + try { + let page = 1; + let totalPages = 1; + + do { + const result = await getQuests({ status: 'Active', page, limit: QUEST_PAGE_SIZE }); + ids.push(...result.quests.map((quest) => quest.id)); + totalPages = result.totalPages || 1; + page += 1; + } while (page <= totalPages && page <= MAX_QUEST_PAGES); + } catch { + // If the API is unreachable at build/request time, fall back to the + // static routes only rather than failing the whole sitemap. + } + + return ids; +} + +export default async function sitemap(): Promise { + const questIds = await getActiveQuestIds(); + const now = new Date(); + + const staticEntries: MetadataRoute.Sitemap = locales.flatMap((locale) => + STATIC_ROUTES.map((route) => ({ + url: `${SITE_URL}/${locale}${route}`, + lastModified: now, + changeFrequency: route === '' ? 'daily' : 'hourly', + priority: route === '' ? 1 : 0.8, + })), + ); + + const questEntries: MetadataRoute.Sitemap = locales.flatMap((locale) => + questIds.map((id) => ({ + url: `${SITE_URL}/${locale}/quests/${id}`, + lastModified: now, + changeFrequency: 'daily', + priority: 0.6, + })), + ); + + return [...staticEntries, ...questEntries]; +} \ No newline at end of file