From 41d2634280305d18a0934077e876e42453665c04 Mon Sep 17 00:00:00 2001 From: abumalick Date: Fri, 25 Jul 2025 11:52:51 +0300 Subject: [PATCH 1/8] feat: implement sitemap generation in TypeScript and remove XML file --- apps/web-roo-code/src/app/sitemap.ts | 38 +++++++++++++++++++++++++++ apps/web-roo-code/src/app/sitemap.xml | 9 ------- 2 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 apps/web-roo-code/src/app/sitemap.ts delete mode 100644 apps/web-roo-code/src/app/sitemap.xml diff --git a/apps/web-roo-code/src/app/sitemap.ts b/apps/web-roo-code/src/app/sitemap.ts new file mode 100644 index 0000000000..fcb5a0f452 --- /dev/null +++ b/apps/web-roo-code/src/app/sitemap.ts @@ -0,0 +1,38 @@ +import { MetadataRoute } from "next" + +export default function sitemap(): MetadataRoute.Sitemap { + const baseUrl = "https://roocode.com" + + return [ + { + url: `${baseUrl}/`, + lastModified: new Date(), + changeFrequency: "yearly", + priority: 1, + }, + { + url: `${baseUrl}/enterprise`, + lastModified: new Date(), + changeFrequency: "monthly", + priority: 0.8, + }, + { + url: `${baseUrl}/evals`, + lastModified: new Date(), + changeFrequency: "monthly", + priority: 0.8, + }, + { + url: `${baseUrl}/privacy`, + lastModified: new Date(), + changeFrequency: "yearly", + priority: 0.5, + }, + { + url: `${baseUrl}/terms`, + lastModified: new Date(), + changeFrequency: "yearly", + priority: 0.5, + }, + ] +} diff --git a/apps/web-roo-code/src/app/sitemap.xml b/apps/web-roo-code/src/app/sitemap.xml deleted file mode 100644 index 43ac973306..0000000000 --- a/apps/web-roo-code/src/app/sitemap.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - https://roocode.com/ - 2025-03-13T22:26:09Z - yearly - 1.0 - - From e25cfdf2407df8ba26390a9b61d21a10db453368 Mon Sep 17 00:00:00 2001 From: abumalick Date: Thu, 7 Aug 2025 19:40:04 +0300 Subject: [PATCH 2/8] fix: use environment variable for base URL in sitemap generation --- apps/web-roo-code/.env.example | 4 ++++ apps/web-roo-code/src/app/sitemap.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/web-roo-code/.env.example b/apps/web-roo-code/.env.example index 734a9a2a08..01258bc500 100644 --- a/apps/web-roo-code/.env.example +++ b/apps/web-roo-code/.env.example @@ -6,3 +6,7 @@ NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com # Basin Form Endpoint for Static Form Submissions # Replace this with your actual Basin form endpoint (e.g., https://usebasin.com/f/your-form-id) NEXT_PUBLIC_BASIN_ENDPOINT=https://usebasin.com/f/your-form-id-here + +# Site URL Configuration +# Used for generating absolute URLs in sitemap and other contexts +NEXT_PUBLIC_SITE_URL=https://roocode.com diff --git a/apps/web-roo-code/src/app/sitemap.ts b/apps/web-roo-code/src/app/sitemap.ts index fcb5a0f452..579c27252c 100644 --- a/apps/web-roo-code/src/app/sitemap.ts +++ b/apps/web-roo-code/src/app/sitemap.ts @@ -1,7 +1,7 @@ import { MetadataRoute } from "next" export default function sitemap(): MetadataRoute.Sitemap { - const baseUrl = "https://roocode.com" + const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://roocode.com" return [ { From 0e4344012f226cffcc131e75ff73bea44959c2fd Mon Sep 17 00:00:00 2001 From: abumalick Date: Thu, 7 Aug 2025 19:48:08 +0300 Subject: [PATCH 3/8] fix: update lastModified dates in sitemap entries --- apps/web-roo-code/src/app/sitemap.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/web-roo-code/src/app/sitemap.ts b/apps/web-roo-code/src/app/sitemap.ts index 579c27252c..ce3fc6547c 100644 --- a/apps/web-roo-code/src/app/sitemap.ts +++ b/apps/web-roo-code/src/app/sitemap.ts @@ -6,31 +6,31 @@ export default function sitemap(): MetadataRoute.Sitemap { return [ { url: `${baseUrl}/`, - lastModified: new Date(), + lastModified: new Date("2025-06-03T21:03:19.000Z"), changeFrequency: "yearly", priority: 1, }, { url: `${baseUrl}/enterprise`, - lastModified: new Date(), + lastModified: new Date("2025-07-02T20:39:02.000Z"), changeFrequency: "monthly", priority: 0.8, }, { url: `${baseUrl}/evals`, - lastModified: new Date(), + lastModified: new Date("2025-06-11T21:17:53.000Z"), changeFrequency: "monthly", priority: 0.8, }, { url: `${baseUrl}/privacy`, - lastModified: new Date(), + lastModified: new Date("2025-06-20T03:00:11.000Z"), changeFrequency: "yearly", priority: 0.5, }, { url: `${baseUrl}/terms`, - lastModified: new Date(), + lastModified: new Date("2025-06-20T04:56:14.000Z"), changeFrequency: "yearly", priority: 0.5, }, From d4ca4b3e6bb31a3321b8a7e1acbd7381ab064377 Mon Sep 17 00:00:00 2001 From: abumalick Date: Thu, 7 Aug 2025 19:54:49 +0300 Subject: [PATCH 4/8] feat: add script to update sitemap with git modification dates --- package.json | 1 + scripts/update-sitemap-dates.js | 102 ++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 scripts/update-sitemap-dates.js diff --git a/package.json b/package.json index c1ddc68223..50d4129da5 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "changeset:version": "cp CHANGELOG.md src/CHANGELOG.md && changeset version && cp -vf src/CHANGELOG.md .", "knip": "knip --include files", "update-contributors": "node scripts/update-contributors.js", + "update-sitemap": "node scripts/update-sitemap-dates.js", "evals": "dotenvx run -f packages/evals/.env.development packages/evals/.env.local -- docker compose -f packages/evals/docker-compose.yml --profile server --profile runner up --build --scale runner=0", "link-workspace-packages": "node scripts/link-packages.js", "unlink-workspace-packages": "node scripts/link-packages.js --unlink" diff --git a/scripts/update-sitemap-dates.js b/scripts/update-sitemap-dates.js new file mode 100644 index 0000000000..dbdc665dde --- /dev/null +++ b/scripts/update-sitemap-dates.js @@ -0,0 +1,102 @@ +#!/usr/bin/env node + +const fs = require("fs") +const path = require("path") +const { execSync } = require("child_process") + +/** + * Script to update sitemap.ts with actual git modification dates + * Run this script whenever you want to update the sitemap with current git history + */ + +const SITEMAP_PATH = path.join(__dirname, "../apps/web-roo-code/src/app/sitemap.ts") + +// Map of sitemap URLs to their corresponding page files +const URL_TO_FILE_MAP = { + "/": "apps/web-roo-code/src/app/page.tsx", + "/enterprise": "apps/web-roo-code/src/app/enterprise/page.tsx", + "/evals": "apps/web-roo-code/src/app/evals/page.tsx", + "/privacy": "apps/web-roo-code/src/app/privacy/page.tsx", + "/terms": "apps/web-roo-code/src/app/terms/page.tsx", +} + +/** + * Get the last modification date of a file from git history + * @param {string} filePath - Path to the file relative to repo root + * @returns {string} ISO date string + */ +function getLastModifiedDate(filePath) { + try { + // Get the last commit date for the file + const gitCommand = `git log -1 --format="%ai" -- "${filePath}"` + const result = execSync(gitCommand, { + cwd: path.join(__dirname, "../"), // Go to repo root + encoding: "utf8", + }).trim() + + if (!result) { + console.warn(`No git history found for ${filePath}, using current date`) + return new Date().toISOString() + } + + // Convert git date to ISO string + return new Date(result).toISOString() + } catch (error) { + console.error(`Error getting git date for ${filePath}:`, error.message) + return new Date().toISOString() + } +} + +/** + * Update the sitemap.ts file with new dates + */ +function updateSitemap() { + console.log("šŸ” Reading current sitemap...") + + // Read the current sitemap file + const sitemapContent = fs.readFileSync(SITEMAP_PATH, "utf8") + + console.log("šŸ“… Getting git modification dates...") + + // Get modification dates for each URL + const urlDates = {} + for (const [url, filePath] of Object.entries(URL_TO_FILE_MAP)) { + const lastModified = getLastModifiedDate(filePath) + urlDates[url] = lastModified + console.log(` ${url}: ${lastModified}`) + } + + console.log("āœļø Updating sitemap content...") + + // Update the sitemap content + let updatedContent = sitemapContent + + // Replace each lastModified: new Date() with the actual git date + for (const [url, isoDate] of Object.entries(urlDates)) { + // Create a regex to match the specific URL entry and its lastModified line + const urlPattern = new RegExp( + `(\\{[^}]*url:\\s*\`\\$\\{baseUrl\\}${url.replace("/", "\\/")}\`[^}]*lastModified:\\s*)new Date\\([^)]*\\)`, + "g", + ) + + updatedContent = updatedContent.replace(urlPattern, `$1new Date("${isoDate}")`) + } + + // Write the updated content back to the file + fs.writeFileSync(SITEMAP_PATH, updatedContent, "utf8") + + console.log("āœ… Sitemap updated successfully!") + console.log(`šŸ“ Updated file: ${SITEMAP_PATH}`) +} + +// Run the script +if (require.main === module) { + try { + updateSitemap() + } catch (error) { + console.error("āŒ Error updating sitemap:", error.message) + process.exit(1) + } +} + +module.exports = { updateSitemap, getLastModifiedDate } From d6a4f993d0238422da11becfaa2ce0d3414f2819 Mon Sep 17 00:00:00 2001 From: abumalick Date: Thu, 7 Aug 2025 20:14:21 +0300 Subject: [PATCH 5/8] feat: enhance sitemap update script to dynamically discover page files and handle missing entries --- scripts/update-sitemap-dates.js | 88 +++++++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 10 deletions(-) diff --git a/scripts/update-sitemap-dates.js b/scripts/update-sitemap-dates.js index dbdc665dde..4e4d858140 100644 --- a/scripts/update-sitemap-dates.js +++ b/scripts/update-sitemap-dates.js @@ -10,14 +10,58 @@ const { execSync } = require("child_process") */ const SITEMAP_PATH = path.join(__dirname, "../apps/web-roo-code/src/app/sitemap.ts") +const APP_DIR = path.join(__dirname, "../apps/web-roo-code/src/app") -// Map of sitemap URLs to their corresponding page files -const URL_TO_FILE_MAP = { - "/": "apps/web-roo-code/src/app/page.tsx", - "/enterprise": "apps/web-roo-code/src/app/enterprise/page.tsx", - "/evals": "apps/web-roo-code/src/app/evals/page.tsx", - "/privacy": "apps/web-roo-code/src/app/privacy/page.tsx", - "/terms": "apps/web-roo-code/src/app/terms/page.tsx", +/** + * Recursively find all page.tsx files in the app directory + * @param {string} dir - Directory to search + * @param {string} basePath - Base path for building relative paths + * @returns {Array<{url: string, filePath: string}>} Array of URL to file mappings + */ +function findPageFiles(dir, basePath = "") { + const pages = [] + const entries = fs.readdirSync(dir, { withFileTypes: true }) + + for (const entry of entries) { + const fullPath = path.join(dir, entry.name) + + if (entry.isDirectory()) { + // Skip certain directories that shouldn't contain pages + if (entry.name.startsWith(".") || entry.name === "api") { + continue + } + + // Recursively search subdirectories + const subPages = findPageFiles(fullPath, path.join(basePath, entry.name)) + pages.push(...subPages) + } else if (entry.name === "page.tsx") { + // Convert file path to URL following Next.js app router conventions + const url = basePath === "" ? "/" : `/${basePath}` + const relativeFilePath = path.relative(path.join(__dirname, "../"), fullPath) + + pages.push({ + url, + filePath: relativeFilePath, + }) + } + } + + return pages +} + +/** + * Get URL to file mapping by scanning the app directory + * @returns {Object} Map of URLs to their corresponding page files + */ +function getUrlToFileMap() { + const pages = findPageFiles(APP_DIR) + const urlToFileMap = {} + + for (const page of pages) { + urlToFileMap[page.url] = page.filePath + } + + return urlToFileMap } /** @@ -51,7 +95,16 @@ function getLastModifiedDate(filePath) { * Update the sitemap.ts file with new dates */ function updateSitemap() { - console.log("šŸ” Reading current sitemap...") + console.log("šŸ” Discovering page files...") + + // Dynamically discover page files + const urlToFileMap = getUrlToFileMap() + console.log(`Found ${Object.keys(urlToFileMap).length} page files:`) + for (const [url, filePath] of Object.entries(urlToFileMap)) { + console.log(` ${url} → ${filePath}`) + } + + console.log("\nšŸ” Reading current sitemap...") // Read the current sitemap file const sitemapContent = fs.readFileSync(SITEMAP_PATH, "utf8") @@ -60,7 +113,7 @@ function updateSitemap() { // Get modification dates for each URL const urlDates = {} - for (const [url, filePath] of Object.entries(URL_TO_FILE_MAP)) { + for (const [url, filePath] of Object.entries(urlToFileMap)) { const lastModified = getLastModifiedDate(filePath) urlDates[url] = lastModified console.log(` ${url}: ${lastModified}`) @@ -78,6 +131,21 @@ function updateSitemap() { `(\\{[^}]*url:\\s*\`\\$\\{baseUrl\\}${url.replace("/", "\\/")}\`[^}]*lastModified:\\s*)new Date\\([^)]*\\)`, "g", ) + const isFound = updatedContent.match(urlPattern) + + if (!isFound) { + console.error(`\nāš ļø No matching entry found for ${url}, skipping update`) + console.log( + `šŸ“ To add this missing entry to the sitemap, add the following to apps/web-roo-code/src/app/sitemap.ts:`, + ) + console.log(`\n{`) + console.log(`\turl: \`\${baseUrl}${url}\`,`) + console.log(`\tlastModified: new Date("${isoDate}"),`) + console.log(`\tchangeFrequency: "monthly",`) + console.log(`\tpriority: 0.8,`) + console.log(`},\n`) + continue + } updatedContent = updatedContent.replace(urlPattern, `$1new Date("${isoDate}")`) } @@ -99,4 +167,4 @@ if (require.main === module) { } } -module.exports = { updateSitemap, getLastModifiedDate } +module.exports = { updateSitemap, getLastModifiedDate, findPageFiles, getUrlToFileMap } From ab341fbb380f717fab0a77955696a5bb41a9a65d Mon Sep 17 00:00:00 2001 From: abumalick Date: Thu, 7 Aug 2025 20:26:40 +0300 Subject: [PATCH 6/8] fix: use execFileSync for safer git command execution in lastModified date retrieval --- scripts/update-sitemap-dates.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/update-sitemap-dates.js b/scripts/update-sitemap-dates.js index 4e4d858140..88c7e98f46 100644 --- a/scripts/update-sitemap-dates.js +++ b/scripts/update-sitemap-dates.js @@ -72,8 +72,8 @@ function getUrlToFileMap() { function getLastModifiedDate(filePath) { try { // Get the last commit date for the file - const gitCommand = `git log -1 --format="%ai" -- "${filePath}"` - const result = execSync(gitCommand, { + // Use execFileSync to prevent command injection by separating command from arguments + const result = execFileSync("git", ["log", "-1", "--format=%ai", "--", filePath], { cwd: path.join(__dirname, "../"), // Go to repo root encoding: "utf8", }).trim() From a7bfef2e965629bc219c4b636c53a465781c264e Mon Sep 17 00:00:00 2001 From: daniel-lxs Date: Thu, 14 Aug 2025 10:10:22 -0500 Subject: [PATCH 7/8] feat: replace custom sitemap with next-sitemap package - Install next-sitemap as dev dependency - Add next-sitemap.config.cjs with proper configuration - Configure postbuild script to generate sitemap automatically - Add robots.txt generation - Remove custom sitemap.ts and update-sitemap-dates.js script - Add generated files to .gitignore - Add .npmrc to enable pre/post scripts for pnpm This provides better future-proofing with automatic page discovery, robots.txt generation, and more configuration options as suggested by @mrubens. --- apps/web-roo-code/.gitignore | 4 + apps/web-roo-code/.npmrc | 1 + apps/web-roo-code/next-sitemap.config.cjs | 57 ++++++++ apps/web-roo-code/package.json | 2 + apps/web-roo-code/src/app/sitemap.ts | 38 ----- package.json | 1 - pnpm-lock.yaml | 31 +++- scripts/update-sitemap-dates.js | 170 ---------------------- 8 files changed, 94 insertions(+), 210 deletions(-) create mode 100644 apps/web-roo-code/.npmrc create mode 100644 apps/web-roo-code/next-sitemap.config.cjs delete mode 100644 apps/web-roo-code/src/app/sitemap.ts delete mode 100644 scripts/update-sitemap-dates.js diff --git a/apps/web-roo-code/.gitignore b/apps/web-roo-code/.gitignore index 7b8da95f5e..6f31e99c00 100644 --- a/apps/web-roo-code/.gitignore +++ b/apps/web-roo-code/.gitignore @@ -40,3 +40,7 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# generated files +/public/sitemap*.xml +/public/robots.txt diff --git a/apps/web-roo-code/.npmrc b/apps/web-roo-code/.npmrc new file mode 100644 index 0000000000..b7425b9ee8 --- /dev/null +++ b/apps/web-roo-code/.npmrc @@ -0,0 +1 @@ +enable-pre-post-scripts=true \ No newline at end of file diff --git a/apps/web-roo-code/next-sitemap.config.cjs b/apps/web-roo-code/next-sitemap.config.cjs new file mode 100644 index 0000000000..ae9b4b55ba --- /dev/null +++ b/apps/web-roo-code/next-sitemap.config.cjs @@ -0,0 +1,57 @@ +/** @type {import('next-sitemap').IConfig} */ +module.exports = { + siteUrl: process.env.NEXT_PUBLIC_SITE_URL || 'https://roocode.com', + generateRobotsTxt: true, + generateIndexSitemap: false, // We don't need index sitemap for a small site + changefreq: 'monthly', + priority: 0.7, + sitemapSize: 5000, + exclude: [ + '/api/*', + '/server-sitemap-index.xml', + '/404', + '/500', + '/_not-found', + ], + robotsTxtOptions: { + policies: [ + { + userAgent: '*', + allow: '/', + }, + ], + additionalSitemaps: [ + // Add any additional sitemaps here if needed in the future + ], + }, + // Custom transform function to set specific priorities and change frequencies + transform: async (config, path) => { + // Set custom priority for specific pages + let priority = config.priority; + let changefreq = config.changefreq; + + if (path === '/') { + priority = 1.0; + changefreq = 'yearly'; + } else if (path === '/enterprise' || path === '/evals') { + priority = 0.8; + changefreq = 'monthly'; + } else if (path === '/privacy' || path === '/terms') { + priority = 0.5; + changefreq = 'yearly'; + } + + return { + loc: path, + changefreq, + priority, + lastmod: config.autoLastmod ? new Date().toISOString() : undefined, + alternateRefs: config.alternateRefs ?? [], + }; + }, + additionalPaths: async (config) => { + // Add any additional paths that might not be automatically discovered + // This is useful for dynamic routes or API-generated pages + return []; + }, +}; \ No newline at end of file diff --git a/apps/web-roo-code/package.json b/apps/web-roo-code/package.json index 8495dd961a..fa59cacccb 100644 --- a/apps/web-roo-code/package.json +++ b/apps/web-roo-code/package.json @@ -7,6 +7,7 @@ "check-types": "tsc --noEmit", "dev": "next dev", "build": "next build", + "postbuild": "next-sitemap --config next-sitemap.config.cjs", "start": "next start", "clean": "rimraf .next .turbo" }, @@ -42,6 +43,7 @@ "@types/react": "^18.3.23", "@types/react-dom": "^18.3.7", "autoprefixer": "^10.4.21", + "next-sitemap": "^4.2.3", "postcss": "^8.5.4", "tailwindcss": "^3.4.17" } diff --git a/apps/web-roo-code/src/app/sitemap.ts b/apps/web-roo-code/src/app/sitemap.ts deleted file mode 100644 index ce3fc6547c..0000000000 --- a/apps/web-roo-code/src/app/sitemap.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { MetadataRoute } from "next" - -export default function sitemap(): MetadataRoute.Sitemap { - const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://roocode.com" - - return [ - { - url: `${baseUrl}/`, - lastModified: new Date("2025-06-03T21:03:19.000Z"), - changeFrequency: "yearly", - priority: 1, - }, - { - url: `${baseUrl}/enterprise`, - lastModified: new Date("2025-07-02T20:39:02.000Z"), - changeFrequency: "monthly", - priority: 0.8, - }, - { - url: `${baseUrl}/evals`, - lastModified: new Date("2025-06-11T21:17:53.000Z"), - changeFrequency: "monthly", - priority: 0.8, - }, - { - url: `${baseUrl}/privacy`, - lastModified: new Date("2025-06-20T03:00:11.000Z"), - changeFrequency: "yearly", - priority: 0.5, - }, - { - url: `${baseUrl}/terms`, - lastModified: new Date("2025-06-20T04:56:14.000Z"), - changeFrequency: "yearly", - priority: 0.5, - }, - ] -} diff --git a/package.json b/package.json index 50d4129da5..c1ddc68223 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,6 @@ "changeset:version": "cp CHANGELOG.md src/CHANGELOG.md && changeset version && cp -vf src/CHANGELOG.md .", "knip": "knip --include files", "update-contributors": "node scripts/update-contributors.js", - "update-sitemap": "node scripts/update-sitemap-dates.js", "evals": "dotenvx run -f packages/evals/.env.development packages/evals/.env.local -- docker compose -f packages/evals/docker-compose.yml --profile server --profile runner up --build --scale runner=0", "link-workspace-packages": "node scripts/link-packages.js", "unlink-workspace-packages": "node scripts/link-packages.js --unlink" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8a0cb09263..6724732a50 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -327,6 +327,9 @@ importers: autoprefixer: specifier: ^10.4.21 version: 10.4.21(postcss@8.5.4) + next-sitemap: + specifier: ^4.2.3 + version: 4.2.3(next@15.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) postcss: specifier: ^8.5.4 version: 8.5.4 @@ -1511,6 +1514,9 @@ packages: '@chevrotain/utils@11.0.3': resolution: {integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==} + '@corex/deepmerge@4.0.43': + resolution: {integrity: sha512-N8uEMrMPL0cu/bdboEWpQYb/0i2K5Qn8eCsxzOmxSggJbbQte7ljMRoXm917AbntqTGOzdTu+vP3KOOzoC70HQ==} + '@csstools/color-helpers@5.0.2': resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==} engines: {node: '>=18'} @@ -2103,6 +2109,9 @@ packages: '@neon-rs/load@0.0.4': resolution: {integrity: sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==} + '@next/env@13.5.11': + resolution: {integrity: sha512-fbb2C7HChgM7CemdCY+y3N1n8pcTKdqtQLbC7/EQtPdLvlMUT9JX/dBYl8MMZAtYG4uVMyPFHXckb68q/NRwqg==} + '@next/env@15.2.5': resolution: {integrity: sha512-uWkCf9C8wKTyQjqrNk+BA7eL3LOQdhL+xlmJUf2O85RM4lbzwBwot3Sqv2QGe/RGnc3zysIf1oJdtq9S00pkmQ==} @@ -7422,6 +7431,13 @@ packages: resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} engines: {node: '>= 0.4.0'} + next-sitemap@4.2.3: + resolution: {integrity: sha512-vjdCxeDuWDzldhCnyFCQipw5bfpl4HmZA7uoo3GAaYGjGgfL4Cxb1CiztPuWGmS+auYs7/8OekRS8C2cjdAsjQ==} + engines: {node: '>=14.18'} + hasBin: true + peerDependencies: + next: '*' + next-themes@0.4.6: resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==} peerDependencies: @@ -8648,6 +8664,7 @@ packages: source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} + deprecated: The work that was done in this beta branch won't be included in future versions space-separated-tokens@1.1.5: resolution: {integrity: sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==} @@ -10733,6 +10750,8 @@ snapshots: '@chevrotain/utils@11.0.3': {} + '@corex/deepmerge@4.0.43': {} + '@csstools/color-helpers@5.0.2': {} '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': @@ -11324,6 +11343,8 @@ snapshots: '@neon-rs/load@0.0.4': optional: true + '@next/env@13.5.11': {} + '@next/env@15.2.5': {} '@next/eslint-plugin-next@15.3.2': @@ -13432,7 +13453,7 @@ snapshots: sirv: 3.0.1 tinyglobby: 0.2.14 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.15.29)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@20.17.57)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) '@vitest/utils@3.2.4': dependencies: @@ -17371,6 +17392,14 @@ snapshots: netmask@2.0.2: {} + next-sitemap@4.2.3(next@15.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)): + dependencies: + '@corex/deepmerge': 4.0.43 + '@next/env': 13.5.11 + fast-glob: 3.3.3 + minimist: 1.2.8 + next: 15.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next-themes@0.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 diff --git a/scripts/update-sitemap-dates.js b/scripts/update-sitemap-dates.js deleted file mode 100644 index 88c7e98f46..0000000000 --- a/scripts/update-sitemap-dates.js +++ /dev/null @@ -1,170 +0,0 @@ -#!/usr/bin/env node - -const fs = require("fs") -const path = require("path") -const { execSync } = require("child_process") - -/** - * Script to update sitemap.ts with actual git modification dates - * Run this script whenever you want to update the sitemap with current git history - */ - -const SITEMAP_PATH = path.join(__dirname, "../apps/web-roo-code/src/app/sitemap.ts") -const APP_DIR = path.join(__dirname, "../apps/web-roo-code/src/app") - -/** - * Recursively find all page.tsx files in the app directory - * @param {string} dir - Directory to search - * @param {string} basePath - Base path for building relative paths - * @returns {Array<{url: string, filePath: string}>} Array of URL to file mappings - */ -function findPageFiles(dir, basePath = "") { - const pages = [] - const entries = fs.readdirSync(dir, { withFileTypes: true }) - - for (const entry of entries) { - const fullPath = path.join(dir, entry.name) - - if (entry.isDirectory()) { - // Skip certain directories that shouldn't contain pages - if (entry.name.startsWith(".") || entry.name === "api") { - continue - } - - // Recursively search subdirectories - const subPages = findPageFiles(fullPath, path.join(basePath, entry.name)) - pages.push(...subPages) - } else if (entry.name === "page.tsx") { - // Convert file path to URL following Next.js app router conventions - const url = basePath === "" ? "/" : `/${basePath}` - const relativeFilePath = path.relative(path.join(__dirname, "../"), fullPath) - - pages.push({ - url, - filePath: relativeFilePath, - }) - } - } - - return pages -} - -/** - * Get URL to file mapping by scanning the app directory - * @returns {Object} Map of URLs to their corresponding page files - */ -function getUrlToFileMap() { - const pages = findPageFiles(APP_DIR) - const urlToFileMap = {} - - for (const page of pages) { - urlToFileMap[page.url] = page.filePath - } - - return urlToFileMap -} - -/** - * Get the last modification date of a file from git history - * @param {string} filePath - Path to the file relative to repo root - * @returns {string} ISO date string - */ -function getLastModifiedDate(filePath) { - try { - // Get the last commit date for the file - // Use execFileSync to prevent command injection by separating command from arguments - const result = execFileSync("git", ["log", "-1", "--format=%ai", "--", filePath], { - cwd: path.join(__dirname, "../"), // Go to repo root - encoding: "utf8", - }).trim() - - if (!result) { - console.warn(`No git history found for ${filePath}, using current date`) - return new Date().toISOString() - } - - // Convert git date to ISO string - return new Date(result).toISOString() - } catch (error) { - console.error(`Error getting git date for ${filePath}:`, error.message) - return new Date().toISOString() - } -} - -/** - * Update the sitemap.ts file with new dates - */ -function updateSitemap() { - console.log("šŸ” Discovering page files...") - - // Dynamically discover page files - const urlToFileMap = getUrlToFileMap() - console.log(`Found ${Object.keys(urlToFileMap).length} page files:`) - for (const [url, filePath] of Object.entries(urlToFileMap)) { - console.log(` ${url} → ${filePath}`) - } - - console.log("\nšŸ” Reading current sitemap...") - - // Read the current sitemap file - const sitemapContent = fs.readFileSync(SITEMAP_PATH, "utf8") - - console.log("šŸ“… Getting git modification dates...") - - // Get modification dates for each URL - const urlDates = {} - for (const [url, filePath] of Object.entries(urlToFileMap)) { - const lastModified = getLastModifiedDate(filePath) - urlDates[url] = lastModified - console.log(` ${url}: ${lastModified}`) - } - - console.log("āœļø Updating sitemap content...") - - // Update the sitemap content - let updatedContent = sitemapContent - - // Replace each lastModified: new Date() with the actual git date - for (const [url, isoDate] of Object.entries(urlDates)) { - // Create a regex to match the specific URL entry and its lastModified line - const urlPattern = new RegExp( - `(\\{[^}]*url:\\s*\`\\$\\{baseUrl\\}${url.replace("/", "\\/")}\`[^}]*lastModified:\\s*)new Date\\([^)]*\\)`, - "g", - ) - const isFound = updatedContent.match(urlPattern) - - if (!isFound) { - console.error(`\nāš ļø No matching entry found for ${url}, skipping update`) - console.log( - `šŸ“ To add this missing entry to the sitemap, add the following to apps/web-roo-code/src/app/sitemap.ts:`, - ) - console.log(`\n{`) - console.log(`\turl: \`\${baseUrl}${url}\`,`) - console.log(`\tlastModified: new Date("${isoDate}"),`) - console.log(`\tchangeFrequency: "monthly",`) - console.log(`\tpriority: 0.8,`) - console.log(`},\n`) - continue - } - - updatedContent = updatedContent.replace(urlPattern, `$1new Date("${isoDate}")`) - } - - // Write the updated content back to the file - fs.writeFileSync(SITEMAP_PATH, updatedContent, "utf8") - - console.log("āœ… Sitemap updated successfully!") - console.log(`šŸ“ Updated file: ${SITEMAP_PATH}`) -} - -// Run the script -if (require.main === module) { - try { - updateSitemap() - } catch (error) { - console.error("āŒ Error updating sitemap:", error.message) - process.exit(1) - } -} - -module.exports = { updateSitemap, getLastModifiedDate, findPageFiles, getUrlToFileMap } From 1c303817c4eddc0cbccaf19b92c4b799c555e61a Mon Sep 17 00:00:00 2001 From: daniel-lxs Date: Thu, 14 Aug 2025 10:24:12 -0500 Subject: [PATCH 8/8] fix: add next-sitemap.config.cjs to knip ignore list --- knip.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/knip.json b/knip.json index 7ca8cfad7b..46626af32b 100644 --- a/knip.json +++ b/knip.json @@ -7,7 +7,8 @@ "src/activate/**", "src/workers/countTokens.ts", "src/extension.ts", - "scripts/**" + "scripts/**", + "apps/web-roo-code/next-sitemap.config.cjs" ], "workspaces": { "src": {