diff --git a/server/routes.ts b/server/routes.ts
index 85c7f80..4fc56d3 100644
--- a/server/routes.ts
+++ b/server/routes.ts
@@ -71,6 +71,85 @@ export async function registerRoutes(
);
});
+ // ---- SEO: robots.txt, sitemap.xml, news sitemap, RSS ----
+ const SITE = "https://folx.tv";
+ const xmlEscape = (s: string) =>
+ String(s || "")
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'");
+
+ app.get("/robots.txt", (_req, res) => {
+ res.type("text/plain").send(
+ [
+ "User-agent: *",
+ "Allow: /",
+ "",
+ `Sitemap: ${SITE}/sitemap.xml`,
+ `Sitemap: ${SITE}/news-sitemap.xml`,
+ "",
+ ].join("\n")
+ );
+ });
+
+ app.get("/sitemap.xml", async (_req, res) => {
+ try {
+ const articles = await storage.getArticles();
+ const staticPaths = ["/", "/news", "/video", "/galerie", "/horoskop", "/rezepte", "/kontakt", "/impressum", "/datenschutz"];
+ const urls: string[] = [];
+ for (const p of staticPaths) {
+ urls.push(` \n ${SITE}${p}\n daily\n ${p === "/" ? "1.0" : "0.7"}\n `);
+ }
+ for (const a of articles) {
+ const lastmod = a.publishedAt ? new Date(a.publishedAt as any).toISOString() : new Date().toISOString();
+ urls.push(` \n ${SITE}/article/${xmlEscape(a.slug)}\n ${lastmod}\n weekly\n 0.8\n `);
+ }
+ const xml = `\n\n${urls.join("\n")}\n`;
+ res.type("application/xml").send(xml);
+ } catch (e) {
+ res.status(500).type("application/xml").send('');
+ }
+ });
+
+ app.get("/news-sitemap.xml", async (_req, res) => {
+ try {
+ const articles = await storage.getArticles();
+ const now = Date.now();
+ const twoDays = 48 * 60 * 60 * 1000;
+ const recent = articles.filter((a) => {
+ const t = a.publishedAt ? new Date(a.publishedAt as any).getTime() : now;
+ return now - t <= twoDays;
+ });
+ const urls = recent.map((a) => {
+ const pub = a.publishedAt ? new Date(a.publishedAt as any).toISOString() : new Date().toISOString();
+ return ` \n ${SITE}/article/${xmlEscape(a.slug)}\n \n \n Folx Music Television\n de\n \n ${pub}\n ${xmlEscape(a.title)}\n \n `;
+ });
+ const xml = `\n\n${urls.join("\n")}\n`;
+ res.type("application/xml").send(xml);
+ } catch (e) {
+ res.status(500).type("application/xml").send('');
+ }
+ });
+
+ app.get(["/rss.xml", "/feed", "/feed.xml"], async (_req, res) => {
+ try {
+ const articles = (await storage.getArticles()).slice(0, 30);
+ const items = articles.map((a) => {
+ const pub = a.publishedAt ? new Date(a.publishedAt as any).toUTCString() : new Date().toUTCString();
+ const link = `${SITE}/article/${xmlEscape(a.slug)}`;
+ const img = a.coverImage ? (a.coverImage.startsWith("http") ? a.coverImage : SITE + a.coverImage) : "";
+ const enclosure = img ? `\n ` : "";
+ return ` - \n ${xmlEscape(a.title)}\n ${link}\n ${link}\n ${pub}\n ${xmlEscape(a.category || "News")}\n ${xmlEscape(a.excerpt || "")}${enclosure}\n
`;
+ });
+ const xml = `\n\n \n Folx Music Television – News\n ${SITE}\n \n Aktuelle Nachrichten aus der Welt der Volksmusik und des Schlagers.\n de-DE\n ${new Date().toUTCString()}\n${items.join("\n")}\n \n`;
+ res.type("application/rss+xml").send(xml);
+ } catch (e) {
+ res.status(500).type("application/rss+xml").send('');
+ }
+ });
+
app.get("/api/focal-points", (_req, res) => {
res.json(getCachedFocalPoints());
});
diff --git a/server/static.ts b/server/static.ts
index 30a5e70..0f02bbd 100644
--- a/server/static.ts
+++ b/server/static.ts
@@ -63,6 +63,38 @@ export function serveStatic(app: Express) {
let template = await fs.promises.readFile(indexPath, "utf-8");
template = stripExistingMeta(template);
+ const pubDate = article.publishedAt
+ ? new Date(article.publishedAt as any).toISOString()
+ : new Date().toISOString();
+ const jsonLd = {
+ "@context": "https://schema.org",
+ "@type": "NewsArticle",
+ "headline": article.title,
+ "description": article.excerpt,
+ "image": [finalImage],
+ "datePublished": pubDate,
+ "dateModified": pubDate,
+ "articleSection": article.category || "News",
+ "author": {
+ "@type": "Organization",
+ "name": article.author || "Folx Music Television",
+ "url": canonicalBase,
+ },
+ "publisher": {
+ "@type": "Organization",
+ "name": "Folx Music Television",
+ "logo": {
+ "@type": "ImageObject",
+ "url": `${canonicalBase}/og-image.jpg`,
+ },
+ },
+ "mainEntityOfPage": {
+ "@type": "WebPage",
+ "@id": articleUrl,
+ },
+ };
+ const jsonLdTag = ``;
+
const ogTags = [
``,
``,
@@ -84,6 +116,7 @@ export function serveStatic(app: Express) {
``,
``,
`
${escapeHtml(article.title)} - Volksmusik & Schlager | Folx Music Television`,
+ jsonLdTag,
].join("\n ");
template = template.replace(/[^<]*<\/title>/, ogTags);