Merge pull request #16 from Denshooter/d-branch-3

feat(sitemap): enhance sitemap generation and error handling
This commit is contained in:
Denshooter
2025-02-12 18:32:09 +01:00
committed by GitHub
3 changed files with 70 additions and 48 deletions

View File

@@ -13,15 +13,9 @@ RUN npm install
# Copy the application code # Copy the application code
COPY . . COPY . .
# Set IS_BUILD environment variable for build process
ENV IS_BUILD=true
# Build the Next.js application # Build the Next.js application
RUN npm run build RUN npm run build
# Unset IS_BUILD environment variable for runtime
ENV IS_BUILD=false
# Set environmental variable for production mode # Set environmental variable for production mode
ENV NODE_ENV=production ENV NODE_ENV=production

View File

@@ -1,8 +1,8 @@
// portfolio/app/api/sitemap/route.tsx
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
interface Project { interface Project {
slug: string; slug: string;
updated_at?: string; // Optional timestamp for last modification
} }
interface ProjectsData { interface ProjectsData {
@@ -14,7 +14,7 @@ interface SitemapRoute {
lastModified: string; lastModified: string;
} }
const baseUrl = "https://dki.one"; const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || "https://dki.one";
const generateSitemap = async (): Promise<SitemapRoute[]> => { const generateSitemap = async (): Promise<SitemapRoute[]> => {
try { try {
@@ -33,7 +33,7 @@ const generateSitemap = async (): Promise<SitemapRoute[]> => {
// Check if running in build environment // Check if running in build environment
if (process.env.IS_BUILD) { if (process.env.IS_BUILD) {
// Use mock data during build console.log("Running in build mode - using mock data");
const mockProjectsData: ProjectsData = { const mockProjectsData: ProjectsData = {
posts: [ posts: [
{ slug: "project-1" }, { slug: "project-1" },
@@ -50,36 +50,42 @@ const generateSitemap = async (): Promise<SitemapRoute[]> => {
return [...staticRoutes, ...projectRoutes]; return [...staticRoutes, ...projectRoutes];
} }
// Fetch project data from your API // Fetch project data from API
console.log("Fetching project data from API..."); console.log("Fetching project data from API...");
const response = await fetch(`${baseUrl}/api/fetchAllProjects`); const response = await fetch(`${baseUrl}/api/fetchAllProjects`, {
headers: { "Cache-Control": "no-cache" },
});
if (!response.ok) { if (!response.ok) {
throw new Error( console.error(`Failed to fetch projects: ${response.statusText}`);
`Failed to fetch projects from Ghost: ${response.statusText}`, return staticRoutes; // Return static pages instead of throwing an error
);
} }
const projectsData = (await response.json()) as ProjectsData; const projectsData = (await response.json()) as ProjectsData;
console.log("Fetched project data:", projectsData); console.log("Fetched project data:", projectsData);
// Generate dynamic routes for projects // Generate dynamic routes for projects
const projectRoutes: SitemapRoute[] = projectsData.posts.map((project) => ({ const projectRoutes: SitemapRoute[] = projectsData.posts.map((project) => ({
url: `${baseUrl}/projects/${project.slug}`, url: `${baseUrl}/projects/${project.slug}`,
lastModified: new Date().toISOString(), lastModified: project.updated_at
? new Date(project.updated_at).toISOString()
: new Date().toISOString(),
})); }));
return [...staticRoutes, ...projectRoutes]; return [...staticRoutes, ...projectRoutes];
} catch (error) { } catch (error) {
console.error("Error generating sitemap:", error); console.error("Error generating sitemap:", error);
throw error; return staticRoutes; // Return static pages in case of failure
} }
}; };
export async function GET() { export async function GET() {
try { try {
const sitemap = await generateSitemap(); const sitemap = await generateSitemap();
return NextResponse.json(sitemap); return NextResponse.json(sitemap, {
headers: { "Cache-Control": "no-cache" },
});
} catch (error) { } catch (error) {
console.error("Failed to generate sitemap:", error);
return NextResponse.json( return NextResponse.json(
{ error: "Failed to generate sitemap" }, { error: "Failed to generate sitemap" },
{ status: 500 }, { status: 500 },

View File

@@ -17,36 +17,58 @@ interface SitemapRoute {
export default async function sitemap(): Promise<MetadataRoute.Sitemap> { export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseUrl = "https://dki.one"; const baseUrl = "https://dki.one";
// Fetch the sitemap data from the dynamic API routes try {
const response = await fetch(`${baseUrl}/api/sitemap`); const response = await fetch(`${baseUrl}/api/sitemap`);
if (!response.ok) { if (!response.ok) {
throw new Error(`Failed to fetch sitemap: ${response.statusText}`); throw new Error(`Failed to fetch sitemap: ${response.statusText}`);
}
const sitemapData = (await response.json()) as SitemapRoute[];
return sitemapData.map((route) => {
let changeFrequency: SitemapRoute["changeFrequency"];
let priority: number;
if (route.url === `${baseUrl}/`) {
changeFrequency = "weekly";
priority = 1.0;
} else if (route.url.startsWith(`${baseUrl}/projects`)) {
changeFrequency = "monthly";
priority = 0.8;
} else if (route.url.startsWith(`${baseUrl}/Blog`)) {
changeFrequency = "weekly";
priority = 0.6;
} else {
changeFrequency = "monthly";
priority = 0.5;
} }
return { const sitemapData = (await response.json()) as SitemapRoute[];
url: route.url,
lastModified: route.lastModified, return sitemapData.map((route) => {
changeFrequency, const config: Record<
priority, string,
}; { changeFrequency: SitemapRoute["changeFrequency"]; priority: number }
}); > = {
[`${baseUrl}/`]: { changeFrequency: "weekly", priority: 1.0 },
};
if (route.url.startsWith(`${baseUrl}/projects`)) {
config[route.url] = { changeFrequency: "monthly", priority: 0.8 };
} else if (route.url.startsWith(`${baseUrl}/blog`)) {
config[route.url] = { changeFrequency: "weekly", priority: 0.6 };
} else {
config[route.url] = { changeFrequency: "monthly", priority: 0.5 };
}
return {
url: route.url,
lastModified: route.lastModified,
...config[route.url],
};
});
} catch (error) {
console.error("Failed to fetch dynamic sitemap, using fallback:", error);
return [
{
url: `${baseUrl}/`,
lastModified: new Date().toISOString(),
changeFrequency: "weekly",
priority: 1.0,
},
{
url: `${baseUrl}/privacy-policy`,
lastModified: new Date().toISOString(),
changeFrequency: "yearly",
priority: 0.3,
},
{
url: `${baseUrl}/legal-notice`,
lastModified: new Date().toISOString(),
changeFrequency: "yearly",
priority: 0.3,
},
];
}
} }