From f41fc04964449276756c12fb4f6b1debecc20ebf Mon Sep 17 00:00:00 2001 From: Ryan Lewis Date: Fri, 21 Jun 2024 16:28:43 -0700 Subject: [PATCH 1/6] add sitemap --- app/src/app/[locale]/health/page.tsx | 9 +++++- app/src/app/sitemap.ts | 16 +++++++++++ app/src/middleware.ts | 2 +- app/src/utils/getRoutes.ts | 41 ++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 app/src/app/sitemap.ts create mode 100644 app/src/utils/getRoutes.ts diff --git a/app/src/app/[locale]/health/page.tsx b/app/src/app/[locale]/health/page.tsx index adbd9f30..0a3f6167 100644 --- a/app/src/app/[locale]/health/page.tsx +++ b/app/src/app/[locale]/health/page.tsx @@ -1,3 +1,10 @@ export default function Page() { - return <>healthy; + return ( + <> + + Health Check + +
healthy
+ + ); } diff --git a/app/src/app/sitemap.ts b/app/src/app/sitemap.ts new file mode 100644 index 00000000..50323888 --- /dev/null +++ b/app/src/app/sitemap.ts @@ -0,0 +1,16 @@ +import { MetadataRoute } from "next"; +import { getNextRoutes } from "../utils/getRoutes"; + +export default function sitemap(): MetadataRoute.Sitemap { + const routes = getNextRoutes("./src/app"); + + const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000"; + const sitemap: MetadataRoute.Sitemap = routes.map((route) => ({ + url: `${baseUrl}${route || ""}`, + lastModified: new Date().toISOString(), + changeFrequency: "weekly", + priority: 0.5, + })); + + return sitemap; +} diff --git a/app/src/middleware.ts b/app/src/middleware.ts index 18d43c06..6f0ea8a6 100644 --- a/app/src/middleware.ts +++ b/app/src/middleware.ts @@ -11,7 +11,7 @@ import { defaultLocale, locales } from "./i18n/config"; // Don't run middleware on API routes or Next.js build output export const config = { - matcher: ["/((?!api|_next|.*\\..*).*)"], + matcher: ["/((?!api|_next|sitemap|.*\\..*).*)"], }; /** diff --git a/app/src/utils/getRoutes.ts b/app/src/utils/getRoutes.ts new file mode 100644 index 00000000..5c863583 --- /dev/null +++ b/app/src/utils/getRoutes.ts @@ -0,0 +1,41 @@ +import fs from "node:fs"; +import path from "node:path"; + +// Helper function to list all paths in a directory recursively +export function listPaths(dir: string): string[] { + let fileList: string[] = []; + const files = fs.readdirSync(dir); + files.forEach((file) => { + const filePath = path.join(dir, file); + if (fs.statSync(filePath).isDirectory()) { + fileList = fileList.concat(listPaths(filePath)); + } else { + fileList.push(filePath); + } + }); + return fileList; +} + +// Function to get the Next.js routes +export function getNextRoutes(src: string): string[] { + // Get all paths from the `app` directory + const appPaths = listPaths(src).filter((file) => file.endsWith("page.tsx")); + + // Extract the route name for each `page.tsx` file + // Basically anything between [locale] and /page.tsx is extracted, + // which lets us get nested routes such as /newsletter/unsubscribe + const appRoutes = appPaths.map((filePath) => { + const relativePath = path.relative(src, filePath); + const route = relativePath + ? "/" + + relativePath + .replace("/page.tsx", "") + .replace(/\[locale\]/g, "") + .replace(/\\/g, "/") + : // for any additional overrides add more replace here... + "/"; + return route.replace(/\/\//g, "/"); + }); + + return appRoutes; +} From c6195b21cd9f189ee3f07a565115f82700e336c0 Mon Sep 17 00:00:00 2001 From: Ryan Lewis Date: Fri, 21 Jun 2024 16:36:18 -0700 Subject: [PATCH 2/6] format --- app/src/app/sitemap.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/app/sitemap.ts b/app/src/app/sitemap.ts index 50323888..f689992a 100644 --- a/app/src/app/sitemap.ts +++ b/app/src/app/sitemap.ts @@ -1,4 +1,5 @@ import { MetadataRoute } from "next"; + import { getNextRoutes } from "../utils/getRoutes"; export default function sitemap(): MetadataRoute.Sitemap { From 26b212561a30b91166dfc45319ab9a4391b4326f Mon Sep 17 00:00:00 2001 From: Ryan Lewis Date: Fri, 21 Jun 2024 16:43:55 -0700 Subject: [PATCH 3/6] add readme --- app/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/README.md b/app/README.md index a8260cd4..2c52d31b 100644 --- a/app/README.md +++ b/app/README.md @@ -178,6 +178,10 @@ Optionally, configure your code editor to auto run these tools on file save. Mos +## Sitemap + +A dynamically generated sitemap is available for the application at http://localhost:3001/sitemap.xml. The sitemap helps search engines index the content of your site more efficiently and can also be used for tools such as accessibility scans. This sitemap is automatically updated to reflect the current application routes. + ## Other topics - [Internationalization](../docs/app/internationalization.md) From 7762d08637528c650cf970bfa9f070b1f893930e Mon Sep 17 00:00:00 2001 From: Ryan Lewis Date: Fri, 21 Jun 2024 16:59:19 -0700 Subject: [PATCH 4/6] move comment --- app/src/utils/getRoutes.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/utils/getRoutes.ts b/app/src/utils/getRoutes.ts index 5c863583..eba82551 100644 --- a/app/src/utils/getRoutes.ts +++ b/app/src/utils/getRoutes.ts @@ -29,11 +29,11 @@ export function getNextRoutes(src: string): string[] { const route = relativePath ? "/" + relativePath + // for any additional overrides add more replace here... .replace("/page.tsx", "") .replace(/\[locale\]/g, "") .replace(/\\/g, "/") - : // for any additional overrides add more replace here... - "/"; + : "/"; return route.replace(/\/\//g, "/"); }); From 17feb258d6b8b0fb5ae0b701a84a38a0c52241aa Mon Sep 17 00:00:00 2001 From: Ryan Lewis Date: Mon, 24 Jun 2024 10:23:32 -0700 Subject: [PATCH 5/6] use next-intl for health check page --- app/src/app/[locale]/health/page.tsx | 7 +++++-- app/src/i18n/messages/en-US/index.ts | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/app/[locale]/health/page.tsx b/app/src/app/[locale]/health/page.tsx index 0a3f6167..32840f27 100644 --- a/app/src/app/[locale]/health/page.tsx +++ b/app/src/app/[locale]/health/page.tsx @@ -1,10 +1,13 @@ +import { useTranslations } from "next-intl"; + export default function Page() { + const t = useTranslations("health"); return ( <> - Health Check + {t("title")} -
healthy
+
{t("healthy")}
); } diff --git a/app/src/i18n/messages/en-US/index.ts b/app/src/i18n/messages/en-US/index.ts index 5e856e07..c092b9c3 100644 --- a/app/src/i18n/messages/en-US/index.ts +++ b/app/src/i18n/messages/en-US/index.ts @@ -26,4 +26,8 @@ export const messages = { formatting: "The template includes an internationalization library with basic formatters built-in. Such as numbers: { amount, number, currency }, and dates: { isoDate, date, long}.", }, + health: { + title: "Health Check", + healthy: "healthy" + } }; From 623accba1811787b5b0eb205e5f659df008d3477 Mon Sep 17 00:00:00 2001 From: Ryan Lewis Date: Mon, 24 Jun 2024 10:24:59 -0700 Subject: [PATCH 6/6] format --- app/src/i18n/messages/en-US/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/i18n/messages/en-US/index.ts b/app/src/i18n/messages/en-US/index.ts index c092b9c3..9d9bcac1 100644 --- a/app/src/i18n/messages/en-US/index.ts +++ b/app/src/i18n/messages/en-US/index.ts @@ -28,6 +28,6 @@ export const messages = { }, health: { title: "Health Check", - healthy: "healthy" - } + healthy: "healthy", + }, };