Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 94 additions & 8 deletions apps/web-roo-code/next-sitemap.config.cjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,68 @@
const path = require('path');
const fs = require('fs');
const matter = require('gray-matter');

/**
* Get published blog posts for sitemap
* Note: This runs at build time, so recently-scheduled posts may lag
*/
function getPublishedBlogPosts() {
const BLOG_DIR = path.join(process.cwd(), 'src/content/blog');

if (!fs.existsSync(BLOG_DIR)) {
return [];
}

const files = fs.readdirSync(BLOG_DIR).filter(f => f.endsWith('.md'));
const posts = [];

// Get current time in PT for publish check
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'America/Los_Angeles',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false,
});

const parts = formatter.formatToParts(new Date());
const get = (type) => parts.find(p => p.type === type)?.value ?? '';
const nowDate = `${get('year')}-${get('month')}-${get('day')}`;
const nowMinutes = parseInt(get('hour')) * 60 + parseInt(get('minute'));

for (const file of files) {
const filepath = path.join(BLOG_DIR, file);
const raw = fs.readFileSync(filepath, 'utf8');
const { data } = matter(raw);

// Check if post is published
if (data.status !== 'published') continue;

// Parse publish time
const timeMatch = data.publish_time_pt?.match(/^(1[0-2]|[1-9]):([0-5][0-9])(am|pm)$/i);
if (!timeMatch) continue;

let hours = parseInt(timeMatch[1]);
const mins = parseInt(timeMatch[2]);
const isPm = timeMatch[3].toLowerCase() === 'pm';
if (hours === 12) hours = isPm ? 12 : 0;
else if (isPm) hours += 12;
const postMinutes = hours * 60 + mins;

// Check if post is past publish date/time
const isPublished = nowDate > data.publish_date ||
(nowDate === data.publish_date && nowMinutes >= postMinutes);

if (isPublished && data.slug) {
posts.push(data.slug);
}
}

return posts;
}

/** @type {import('next-sitemap').IConfig} */
module.exports = {
siteUrl: process.env.NEXT_PUBLIC_SITE_URL || 'https://roocode.com',
Expand Down Expand Up @@ -39,6 +104,12 @@ module.exports = {
} else if (path === '/privacy' || path === '/terms') {
priority = 0.5;
changefreq = 'yearly';
} else if (path === '/blog') {
priority = 0.8;
changefreq = 'weekly';
} else if (path.startsWith('/blog/')) {
priority = 0.7;
changefreq = 'monthly';
}

return {
Expand All @@ -50,24 +121,39 @@ module.exports = {
};
},
additionalPaths: async (config) => {
// Add any additional paths that might not be automatically discovered
// This is useful for dynamic routes or API-generated pages
const result = [];

// Add the /evals page since it's a dynamic route
return [{
result.push({
loc: '/evals',
changefreq: 'monthly',
priority: 0.8,
lastmod: new Date().toISOString(),
}];
});

// Add the /evals page since it's a dynamic route
// Add /blog index
result.push({
loc: '/evals',
changefreq: 'monthly',
loc: '/blog',
changefreq: 'weekly',
priority: 0.8,
lastmod: new Date().toISOString(),
});

// Add published blog posts
try {
const slugs = getPublishedBlogPosts();
for (const slug of slugs) {
result.push({
loc: `/blog/${slug}`,
changefreq: 'monthly',
priority: 0.7,
lastmod: new Date().toISOString(),
});
}
} catch (e) {
console.warn('Could not load blog posts for sitemap:', e.message);
}

return result;
},
};
};
8 changes: 6 additions & 2 deletions apps/web-roo-code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
"build": "next build",
"postbuild": "next-sitemap --config next-sitemap.config.cjs",
"start": "next start",
"clean": "rimraf .next .turbo"
"clean": "rimraf .next .turbo",
"test": "vitest run",
"test:watch": "vitest"
},
"dependencies": {
"@radix-ui/react-dialog": "^1.1.15",
Expand All @@ -25,6 +27,7 @@
"embla-carousel-autoplay": "^8.6.0",
"embla-carousel-react": "^8.6.0",
"framer-motion": "^12.29.2",
"gray-matter": "^4.0.3",
"lucide-react": "^0.563.0",
"next": "^16.1.6",
"next-themes": "^0.4.6",
Expand Down Expand Up @@ -52,6 +55,7 @@
"autoprefixer": "^10.4.23",
"next-sitemap": "^4.2.3",
"postcss": "^8.5.6",
"tailwindcss": "^3.4.17"
"tailwindcss": "^3.4.17",
"vitest": "^4.0.18"
}
}
Loading
Loading