diff --git a/apps/web/app/sitemap.ts b/apps/web/app/sitemap.ts new file mode 100644 index 0000000..d53e1a4 --- /dev/null +++ b/apps/web/app/sitemap.ts @@ -0,0 +1,56 @@ +import { MetadataRoute } from 'next'; +import { blogPosts } from '../src/data/blogPosts'; +import { technologies } from './technologies/[slug]/data'; + +/** + * Sitemap Generator + * + * Standard Next.js 15 App Router sitemap generation. + * This file dynamically generates /sitemap.xml + */ +export default function sitemap(): MetadataRoute.Sitemap { + const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || 'https://mintel.me'; + + // 1. Core Pages + const routes = [ + '', + '/about', + '/blog', + '/case-studies', + '/case-studies/klz-cables', + '/contact', + '/websites', + ].map((route) => ({ + url: `${baseUrl}${route}`, + lastModified: new Date(), + changeFrequency: 'monthly' as const, + priority: route === '' ? 1.0 : 0.8, + })); + + // 2. Dynamic Blog Posts + const blogRoutes = blogPosts.map((post) => ({ + url: `${baseUrl}/blog/${post.slug}`, + lastModified: new Date(post.date), + changeFrequency: 'monthly' as const, + priority: 0.7, + })); + + // 3. Technology Detail Pages + const techRoutes = Object.keys(technologies).map((slug) => ({ + url: `${baseUrl}/technologies/${slug}`, + lastModified: new Date(), + changeFrequency: 'monthly' as const, + priority: 0.6, + })); + + // 4. Tag Pages + const allTags = [...new Set(blogPosts.flatMap((post) => post.tags))]; + const tagRoutes = allTags.map((tag) => ({ + url: `${baseUrl}/tags/${tag}`, + lastModified: new Date(), + changeFrequency: 'weekly' as const, + priority: 0.3, + })); + + return [...routes, ...blogRoutes, ...techRoutes, ...tagRoutes]; +} diff --git a/eslint.config.js b/eslint.config.js index a2806e9..456ee90 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -3,17 +3,9 @@ import tseslint from "typescript-eslint"; import nextPlugin from "@next/eslint-plugin-next"; import reactPlugin from "eslint-plugin-react"; import hooksPlugin from "eslint-plugin-react-hooks"; -import { FlatCompat } from "@eslint/eslintrc"; -import { dirname } from "path"; -import { fileURLToPath } from "url"; - const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); -const compat = new FlatCompat({ - baseDirectory: __dirname, -}); - export default tseslint.config( { ignores: ["**/dist/**", "**/node_modules/**", "**/.next/**", "**/out/**"], @@ -34,15 +26,6 @@ export default tseslint.config( "react/react-in-jsx-scope": "off", "react/no-unescaped-entities": "off", "@next/next/no-img-element": "warn", - }, - settings: { - react: { - version: "detect", - }, - }, - }, - { - rules: { "no-unused-vars": "warn", "@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_", @@ -68,5 +51,10 @@ export default tseslint.config( "no-self-assign": "off", "no-control-regex": "off", }, + settings: { + react: { + version: "detect", + }, + }, }, );