Import source: global/scripts/generate-seo.mjs
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
@@ -0,0 +1,96 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
// Generates sitemap.xml, robots.txt, and feed.xml for teknavglobal.com
|
||||||
|
import { writeFileSync, mkdirSync } from 'fs';
|
||||||
|
import { createRequire } from 'module';
|
||||||
|
|
||||||
|
const SITE = 'https://www.teknavglobal.com';
|
||||||
|
|
||||||
|
// Load article data (CommonJS-compatible workaround for ES module data)
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
|
|
||||||
|
// Dynamic import of global-data.js
|
||||||
|
const { articles, authors, siteConfig } = await import('../global-data.js');
|
||||||
|
|
||||||
|
function capDate(d) {
|
||||||
|
const now = new Date().toISOString().split('T')[0];
|
||||||
|
return d > now ? now : d;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── sitemap.xml ─────────────────────────────────────────────────────
|
||||||
|
const staticPages = [
|
||||||
|
{ url: '/', priority: '1.0', freq: 'daily' },
|
||||||
|
{ url: '/articles', priority: '0.9', freq: 'daily' },
|
||||||
|
{ url: '/about', priority: '0.7', freq: 'monthly' },
|
||||||
|
{ url: '/privacy', priority: '0.4', freq: 'yearly' },
|
||||||
|
{ url: '/terms', priority: '0.4', freq: 'yearly' },
|
||||||
|
{ url: '/editorial-policy', priority: '0.5', freq: 'monthly' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const articleEntries = articles.map(a => ({
|
||||||
|
url: `/article/${a.slug}`,
|
||||||
|
lastmod: capDate(a.dateEn),
|
||||||
|
priority: '0.8',
|
||||||
|
freq: 'weekly',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const allEntries = [...staticPages, ...articleEntries];
|
||||||
|
|
||||||
|
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||||
|
xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
||||||
|
${allEntries.map(e => ` <url>
|
||||||
|
<loc>${SITE}${e.url}</loc>
|
||||||
|
${e.lastmod ? `<lastmod>${e.lastmod}</lastmod>` : ''}
|
||||||
|
<changefreq>${e.freq}</changefreq>
|
||||||
|
<priority>${e.priority}</priority>
|
||||||
|
</url>`).join('\n')}
|
||||||
|
</urlset>`;
|
||||||
|
|
||||||
|
// ── robots.txt ──────────────────────────────────────────────────────
|
||||||
|
const robots = `User-agent: *
|
||||||
|
Allow: /
|
||||||
|
Disallow: /api/
|
||||||
|
Disallow: /profile/
|
||||||
|
Disallow: /admin/
|
||||||
|
|
||||||
|
Sitemap: ${SITE}/sitemap.xml
|
||||||
|
`;
|
||||||
|
|
||||||
|
// ── feed.xml (RSS) ──────────────────────────────────────────────────
|
||||||
|
const feed = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
|
||||||
|
<channel>
|
||||||
|
<title>Teknav — Deep Technology Analysis for Builders</title>
|
||||||
|
<link>${SITE}</link>
|
||||||
|
<description>Technical analysis on AI engineering, security, software architecture, and emerging compute.</description>
|
||||||
|
<language>en</language>
|
||||||
|
<lastBuildDate>${new Date().toUTCString()}</lastBuildDate>
|
||||||
|
<atom:link href="${SITE}/feed.xml" rel="self" type="application/rss+xml"/>
|
||||||
|
<image>
|
||||||
|
<url>${SITE}/images/og/default.jpg</url>
|
||||||
|
<title>Teknav</title>
|
||||||
|
<link>${SITE}</link>
|
||||||
|
</image>
|
||||||
|
${articles
|
||||||
|
.sort((a, b) => new Date(b.dateEn) - new Date(a.dateEn))
|
||||||
|
.map(a => {
|
||||||
|
const author = authors.find(au => au.id === a.author);
|
||||||
|
return ` <item>
|
||||||
|
<title><![CDATA[${a.title}]]></title>
|
||||||
|
<link>${SITE}/article/${a.slug}</link>
|
||||||
|
<guid isPermaLink="true">${SITE}/article/${a.slug}</guid>
|
||||||
|
<pubDate>${new Date(a.dateEn).toUTCString()}</pubDate>
|
||||||
|
<description><![CDATA[${a.subtitle || a.metaDescription || ''}]]></description>
|
||||||
|
${author ? `<author>${author.name}</author>` : ''}
|
||||||
|
<category>${a.category}</category>
|
||||||
|
</item>`;
|
||||||
|
}).join('\n')}
|
||||||
|
</channel>
|
||||||
|
</rss>`;
|
||||||
|
|
||||||
|
mkdirSync('public', { recursive: true });
|
||||||
|
writeFileSync('public/sitemap.xml', sitemap);
|
||||||
|
writeFileSync('public/robots.txt', robots);
|
||||||
|
writeFileSync('public/feed.xml', feed);
|
||||||
|
|
||||||
|
console.log(`[seo] sitemap: ${allEntries.length} URLs | feed: ${articles.length} items`);
|
||||||
Reference in New Issue
Block a user