From a8f10c8e37aa161a963d9c1c0dfd8b55828a4411 Mon Sep 17 00:00:00 2001 From: Denshooter Date: Thu, 13 Feb 2025 16:10:14 +0100 Subject: [PATCH] refactor(sitemap): improve sitemap generation and error handling; rename sitemap file --- README.md | 18 ++-- app/api/sitemap/route.tsx | 95 +++++++++------------- app/{sitemap.tsx => sitemap.xml/route.tsx} | 47 ++++------- public/robots.txt | 2 +- 4 files changed, 69 insertions(+), 93 deletions(-) rename app/{sitemap.tsx => sitemap.xml/route.tsx} (65%) diff --git a/README.md b/README.md index e215bc4..1da47b3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +This is a [Next.js](https://nextjs.org) project bootstrapped with [ +`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). ## Getting Started @@ -16,9 +17,10 @@ bun dev Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +You can start editing the page by modifying `app/route.tsx`. The page auto-updates as you edit the file. -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically +optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. ## Learn More @@ -27,10 +29,14 @@ To learn more about Next.js, take a look at the following resources: - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions +are welcome! ## Deploy on Vercel -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +The easiest way to deploy your Next.js app is to use +the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) +from the creators of Next.js. -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for +more details. diff --git a/app/api/sitemap/route.tsx b/app/api/sitemap/route.tsx index 3c45630..374dbc4 100644 --- a/app/api/sitemap/route.tsx +++ b/app/api/sitemap/route.tsx @@ -1,75 +1,60 @@ -import { NextResponse } from "next/server"; +import {NextResponse} from "next/server"; interface Project { - slug: string; - updated_at?: string; // Optional timestamp for last modification + slug: string; + updated_at?: string; // Optional timestamp for last modification } interface ProjectsData { - posts: Project[]; + posts: Project[]; } interface SitemapRoute { - url: string; - lastModified: string; + url: string; + lastModified: string; } const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || "https://dki.one"; const generateSitemap = async (): Promise => { - // Static pages - const staticRoutes: SitemapRoute[] = [ - { url: `${baseUrl}/`, lastModified: new Date().toISOString() }, - { - url: `${baseUrl}/privacy-policy`, - lastModified: new Date().toISOString(), - }, - { - url: `${baseUrl}/legal-notice`, - lastModified: new Date().toISOString(), - }, - ]; + try { + const response = await fetch(`${baseUrl}/api/fetchAllProjects`, { + headers: {"Cache-Control": "no-cache"}, + }); - try { - console.log("Fetching project data from API..."); - const response = await fetch(`${baseUrl}/api/fetchAllProjects`, { - headers: { "Cache-Control": "no-cache" }, - }); + if (!response.ok) { + console.error(`Failed to fetch projects: ${response.statusText}`); + return []; + } - if (!response.ok) { - console.error(`Failed to fetch projects: ${response.statusText}`); - return staticRoutes; // Fallback auf statische Seiten + const projectsData = (await response.json()) as ProjectsData; + + // Dynamische Projekt-Routen generieren + const projectRoutes: SitemapRoute[] = projectsData.posts.map((project) => ({ + url: `${baseUrl}/projects/${project.slug}`, + lastModified: project.updated_at + ? new Date(project.updated_at).toISOString() + : new Date().toISOString(), + })); + + return [...projectRoutes]; + } catch (error) { + console.error("Failed to generate sitemap:", error); + return []; } - - const projectsData = (await response.json()) as ProjectsData; - console.log("Fetched project data:", projectsData); - - // Dynamische Projekt-Routen generieren - const projectRoutes: SitemapRoute[] = projectsData.posts.map((project) => ({ - url: `${baseUrl}/projects/${project.slug}`, - lastModified: project.updated_at - ? new Date(project.updated_at).toISOString() - : new Date().toISOString(), - })); - - return [...staticRoutes, ...projectRoutes]; - } catch (error) { - console.error("Failed to generate sitemap:", error); - return staticRoutes; // Fallback nur auf statische Seiten - } }; export async function GET() { - try { - const sitemap = await generateSitemap(); - return NextResponse.json(sitemap, { - headers: { "Cache-Control": "no-cache" }, - }); - } catch (error) { - console.error("Failed to generate sitemap:", error); - return NextResponse.json( - { error: "Failed to generate sitemap" }, - { status: 500 }, - ); - } + try { + const sitemap = await generateSitemap(); + return NextResponse.json(sitemap, { + headers: {"Cache-Control": "no-cache"}, + }); + } catch (error) { + console.error("Failed to generate sitemap:", error); + return NextResponse.json( + {error: "Failed to generate sitemap"}, + {status: 500}, + ); + } } diff --git a/app/sitemap.tsx b/app/sitemap.xml/route.tsx similarity index 65% rename from app/sitemap.tsx rename to app/sitemap.xml/route.tsx index d4615f5..2dcf4c5 100644 --- a/app/sitemap.tsx +++ b/app/sitemap.xml/route.tsx @@ -1,4 +1,4 @@ -import type {GetServerSideProps} from "next"; +import {NextResponse} from "next/server"; interface SitemapRoute { url: string; @@ -16,7 +16,9 @@ interface SitemapRoute { const baseUrl = "https://dki.one"; -export const getServerSideProps: GetServerSideProps = async () => { +export async function GET() { + console.log("Generating sitemap..."); + const staticRoutes: SitemapRoute[] = [ {url: `${baseUrl}/`, lastModified: new Date().toISOString(), changeFrequency: "weekly", priority: 1.0}, { @@ -36,28 +38,24 @@ export const getServerSideProps: GetServerSideProps = async () => { try { const response = await fetch(`${baseUrl}/api/sitemap`); if (!response.ok) { - console.error(`Failed to fetch dynamic sitemap: ${response.statusText}`); + console.error(`Failed to fetch dynamic routes: ${response.statusText}`); } const dynamicRoutes = (await response.json()) as SitemapRoute[]; + const sitemap = [...staticRoutes, ...dynamicRoutes]; - return { - props: { - sitemap: [...staticRoutes, ...dynamicRoutes], - }, - }; + return new NextResponse(generateXml(sitemap), { + headers: {"Content-Type": "application/xml"}, + }); } catch (error) { - console.error("Failed to fetch dynamic sitemap, using fallback:", error); - - return { - props: { - sitemap: staticRoutes, - }, - }; + console.error("Error fetching dynamic routes, using fallback:", error); + return new NextResponse(generateXml(staticRoutes), { + headers: {"Content-Type": "application/xml"}, + }); } -}; +} -const generateXml = (routes: SitemapRoute[]): string => { +function generateXml(routes: SitemapRoute[]): string { const xmlHeader = ''; const urlsetOpen = ''; const urlsetClose = ''; @@ -75,17 +73,4 @@ const generateXml = (routes: SitemapRoute[]): string => { .join(""); return `${xmlHeader}${urlsetOpen}${urlEntries}${urlsetClose}`; -}; - -const Sitemap = ({sitemap}: { sitemap: SitemapRoute[] }) => { - const xmlSitemap = generateXml(sitemap); - - return new Response(xmlSitemap, { - headers: { - "Content-Type": "application/xml", - "Cache-Control": "no-cache", - }, - }); -}; - -export default Sitemap; \ No newline at end of file +} diff --git a/public/robots.txt b/public/robots.txt index 5cd4fbf..a672edc 100644 --- a/public/robots.txt +++ b/public/robots.txt @@ -1,4 +1,4 @@ User-agent: * Allow: / Disallow: ['/legal-notice', '/privacy-policy'] -Sitemap: https://dki.one/sitemap.xml +Page: https://dki.one/sitemap.xml