Files
arsam 2bea3214b7 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.
2026-09-18 23:27:09 +03:30

97 lines
3.7 KiB
JavaScript

#!/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`);