Volksmusik & Schlager TV | FOLX Music Television – Nachrichten, Videos & mehr
-
+ Schlager & Volksmusik News | FOLX TV
+
-
-
+
+
@@ -23,8 +23,8 @@
-
-
+
+
diff --git a/client/src/components/footer.tsx b/client/src/components/footer.tsx
index 68a017b..1b1b322 100644
--- a/client/src/components/footer.tsx
+++ b/client/src/components/footer.tsx
@@ -23,8 +23,8 @@ export default function Footer({ narrow }: { narrow?: boolean }) {
Folx Music Television
- FOLX TV – Ihr Fernsehsender Nr. 1 für Volksmusik und Schlager. Aktuelle Nachrichten,
- Musikvideos, Künstlerporträts, Live-Shows und Interviews aus der Welt der volkstümlichen Musik.
+ FOLX TV – Aktuelle Schlager- und Volksmusik-News, Künstlerporträts und Interviews.
+ Entdecken Sie Nachrichten, Artikel und Videos aus der Musikszene sowie Informationen zu unserem TV-Angebot.
diff --git a/client/src/pages/empfang.tsx b/client/src/pages/empfang.tsx
index 62265ec..cce37bb 100644
--- a/client/src/pages/empfang.tsx
+++ b/client/src/pages/empfang.tsx
@@ -1,3 +1,4 @@
+import { INFO_SEO } from "@shared/seo";
import { Tv, MapPin, PlayCircle, Youtube, Smartphone, Radio, ExternalLink } from "lucide-react";
import Header from "@/components/header";
import Footer from "@/components/footer";
@@ -107,10 +108,7 @@ const APPS = [
];
export default function EmpfangPage() {
- usePageMeta(
- "Empfang FOLX TV - Volksmusik & Schlager Sender empfangen",
- "So empfangen Sie FOLX TV – den Volksmusik & Schlager Sender: kostenloser Livestream auf folx.live, die FOLX TV App für Apple, Android, Samsung und Fire TV sowie Kabel und IPTV in Deutschland, Österreich und der Schweiz.",
- );
+ usePageMeta(INFO_SEO["/empfang-folx-tv"].title, INFO_SEO["/empfang-folx-tv"].description, { siteName: "FOLX TV" });
return (
diff --git a/client/src/pages/home.tsx b/client/src/pages/home.tsx
index 8e2b3cc..704e52c 100644
--- a/client/src/pages/home.tsx
+++ b/client/src/pages/home.tsx
@@ -1,3 +1,4 @@
+import { HOME_TITLE, HOME_DESCRIPTION, homeSchema } from "@shared/seo";
import { useQuery } from "@tanstack/react-query";
import { artistGroup } from "@/lib/artists";
import { objectPositionFor } from "@/lib/focal";
@@ -756,38 +757,10 @@ function BentoSkeleton() {
}
export default function Home() {
- usePageMeta("Volksmusik & Schlager TV", "FOLX TV – Ihr Fernsehsender Nr. 1 für Volksmusik und Schlager. Aktuelle Nachrichten, Musikvideos, Künstlerporträts, Live-Shows und Interviews aus der Welt der volkstümlichen Musik.");
+ usePageMeta(HOME_TITLE, HOME_DESCRIPTION, { siteName: "FOLX TV" });
useEffect(() => {
- const jsonLd = {
- "@context": "https://schema.org",
- "@type": "WebSite",
- "name": "Folx Music Television",
- "alternateName": ["FOLX TV", "Volksmusik TV"],
- "url": "https://folx.tv",
- "description": "FOLX TV – Ihr Fernsehsender Nr. 1 für Volksmusik und Schlager. Aktuelle Nachrichten, Musikvideos, Künstlerporträts, Live-Shows und Interviews aus der Welt der volkstümlichen Musik.",
- "publisher": {
- "@type": "Organization",
- "name": "Folx Music Television",
- "url": "https://folx.tv",
- "logo": {
- "@type": "ImageObject",
- "url": `${window.location.origin}/favicon.png`
- },
- "sameAs": [
- "https://www.facebook.com/folxtvmusic",
- "https://www.instagram.com/folxtv",
- "https://www.youtube.com/@FolxTV",
- "https://www.tiktok.com/@folx.tv"
- ]
- },
- "potentialAction": {
- "@type": "SearchAction",
- "target": "https://folx.tv/search?q={search_term_string}",
- "query-input": "required name=search_term_string"
- },
- "inLanguage": "de"
- };
+ const jsonLd = homeSchema();
const script = document.createElement("script");
script.type = "application/ld+json";
script.id = "home-jsonld";
@@ -1033,7 +1006,7 @@ export default function Home() {
-
FOLX TV – Volksmusik & Schlager Fernsehsender: Nachrichten, Videos und Live-Shows
+
FOLX TV – Schlager & Volksmusik News
{/* Prej lastna kopija pasu s trdo visino 90 px in responsive=false:
Google je vanjo postavil 320x50 in okrog je ostal siv rob.
diff --git a/client/src/pages/impressum.tsx b/client/src/pages/impressum.tsx
index 27c7184..581d838 100644
--- a/client/src/pages/impressum.tsx
+++ b/client/src/pages/impressum.tsx
@@ -1,3 +1,4 @@
+import { INFO_SEO } from "@shared/seo";
import { Scale } from "lucide-react";
import Header from "@/components/header";
import Footer from "@/components/footer";
@@ -5,7 +6,7 @@ import { usePageMeta } from "@/hooks/use-page-meta";
import { PageSideAds } from "@/components/adsense";
export default function ImpressumPage() {
- usePageMeta("Impressum - FOLX TV Volksmusik Sender", "Impressum und rechtliche Informationen zu FOLX TV – Ihrem Volksmusik & Schlager Fernsehsender.");
+ usePageMeta(INFO_SEO["/impressum"].title, INFO_SEO["/impressum"].description, { siteName: "FOLX TV" });
return (
diff --git a/client/src/pages/kontakt.tsx b/client/src/pages/kontakt.tsx
index 0a85b21..d307903 100644
--- a/client/src/pages/kontakt.tsx
+++ b/client/src/pages/kontakt.tsx
@@ -1,3 +1,4 @@
+import { INFO_SEO } from "@shared/seo";
import { useState } from "react";
import { Mail, Phone, Send, CheckCircle, AlertCircle, Smartphone, Printer } from "lucide-react";
import { SiFacebook, SiInstagram, SiYoutube, SiTiktok } from "react-icons/si";
@@ -8,7 +9,7 @@ import { PageSideAds, TopBannerAd } from "@/components/adsense";
import { apiRequest } from "@/lib/queryClient";
export default function KontaktPage() {
- usePageMeta("Kontakt - FOLX TV Volksmusik Sender", "Kontaktieren Sie FOLX TV – Ihren Fernsehsender Nr. 1 für Volksmusik und Schlager. Wir freuen uns auf Ihre Nachricht.");
+ usePageMeta(INFO_SEO["/kontakt"].title, INFO_SEO["/kontakt"].description, { siteName: "FOLX TV" });
const [formData, setFormData] = useState({ name: "", email: "", subject: "", message: "" });
const [status, setStatus] = useState<"idle" | "sending" | "success" | "error">("idle");
diff --git a/script/seo-check.ts b/script/seo-check.ts
new file mode 100644
index 0000000..0c937c7
--- /dev/null
+++ b/script/seo-check.ts
@@ -0,0 +1,20 @@
+import assert from "node:assert/strict";
+import { homeSchema, publisherSchema, articleModifiedTime, articleGenre, INFO_SEO } from "../shared/seo";
+const home = homeSchema();
+assert.equal(home["@graph"].filter(x => x["@type"] === "WebSite").length, 1);
+assert.equal(publisherSchema()["@type"], "NewsMediaOrganization");
+assert.ok(JSON.stringify(home).includes("/search?q="));
+assert.ok(!JSON.stringify(home).includes("/suche"));
+assert.ok(publisherSchema().sameAs.includes("https://www.youtube.com/@folxmtv"));
+const pub = "2026-01-01T12:00:00.000Z";
+assert.equal(articleModifiedTime("", pub), pub);
+assert.equal(articleModifiedTime("", pub), pub);
+assert.equal(articleModifiedTime("", pub), pub);
+assert.equal(articleModifiedTime("", pub), pub);
+assert.equal(articleModifiedTime("", pub), "2026-02-01T00:00:00.000Z");
+assert.equal(articleGenre("").section, "Star News");
+assert.ok(!articleGenre("").words.includes("Schlager"));
+assert.equal(articleGenre("").section, "Musik News");
+assert.equal(INFO_SEO["/ueber-uns"].type, "AboutPage");
+assert.equal(INFO_SEO["/kontakt"].type, "ContactPage");
+console.log("SEO metadata checks passed");
diff --git a/server/static.ts b/server/static.ts
index 69917de..60f24a1 100644
--- a/server/static.ts
+++ b/server/static.ts
@@ -1,3 +1,4 @@
+import { publisherSchema, homeSchema, INFO_SEO, articleModifiedTime, articleGenre } from "../shared/seo";
import express, { type Express } from "express";
import fs from "fs";
import path from "path";
@@ -11,13 +12,7 @@ import sharp from "sharp";
// Brez markerja ostane vse kot prej (glasbeno), da starejsi clanki ne nazadujejo.
// Besedilne zaznave namenoma NI: preizkus na 30 clankih jo je zgresil pri
// Fernsehgartnu in Carpendaleju.
-function folxGenre(article: any): { words: string[]; section: string } {
- const m = //i.exec(String(article?.content || ""));
- const badge = (m ? m[1] : "MUSIC NEWS").toUpperCase();
- return badge === "MUSIC NEWS"
- ? { words: ["Volksmusik", "Schlager", "Musik News"], section: "Musik News" }
- : { words: ["Star News", "Promi News", "Promi"], section: "Star News" };
-}
+const folxGenre = (article: any) => articleGenre(String(article?.content || ""));
function escapeHtml(str: string): string {
@@ -88,15 +83,7 @@ const ARTICLE_SLUG_REDIRECTS: Record = {
// v bazi in v /api/articles ostanejo, ker jih bere sidebar na TV kanalih.
// Izdajatelj: doslej samo ime in logo. Brez registrirane druzbe, naslova in
// profilov Google znamke nima s cim povezati.
-const PUBLISHER = (base: string) => ({
- // 4. 9. 2026: izdajatelj spet samo "Folx Music Television" z logom, kot do
- // 26. 8. - brez registrirane druzbe, naslova in kontaktov.
- "@type": "Organization",
- "@id": `${base}/#organization`,
- "name": "Folx Music Television",
- "url": base,
- "logo": { "@type": "ImageObject", "url": `${base}/og-image.jpg` },
-});
+const PUBLISHER = publisherSchema;
const ONE_RUBRIKEN = new Set(["Politik", "Promis", "Sport", "Musik & Film", "Wetter", "Finanzen", "Aktuelles"]);
@@ -294,28 +281,10 @@ export function serveStatic(app: Express) {
if (url === "/" || url.startsWith("/?")) {
try {
let template = await fs.promises.readFile(indexPath, "utf-8");
- const homeLd = {
- "@context": "https://schema.org",
- "@graph": [
- PUBLISHER(canonicalBase),
- {
- "@type": "WebSite",
- "@id": `${canonicalBase}/#website`,
- "url": `${canonicalBase}/`,
- "name": "FOLX Music Television",
- "inLanguage": "de-DE",
- "publisher": { "@id": `${canonicalBase}/#organization` },
- "potentialAction": {
- "@type": "SearchAction",
- "target": { "@type": "EntryPoint", "urlTemplate": `${canonicalBase}/suche?q={search_term_string}` },
- "query-input": "required name=search_term_string",
- },
- },
- ],
- };
+ const homeLd = homeSchema(canonicalBase);
template = template.replace(
"",
- `\n`);
+ `\n`);
// 31. 8. 2026: naslovnica je React aplikacija, zato je robot dobil samo
// lupino brez ene same povezave na clanek. Clanki se do Googla pridejo
@@ -325,7 +294,8 @@ export function serveStatic(app: Express) {
try {
const vsi = await storage.getArticles();
const zadnji = [...vsi]
- .sort((a: any, b: any) => String(b.publishedAt).localeCompare(String(a.publishedAt)))
+ .filter((a: any) => !a.targetUrl && !ONE_RUBRIKEN.has(a.category || ""))
+ .sort((a: any, b: any) => new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime())
.slice(0, 40);
if (zadnji.length) {
const seznam = zadnji
@@ -503,11 +473,7 @@ export function serveStatic(app: Express) {
: new Date().toISOString();
// dateModified: ce je clanek dopolnjen (enrich), preberi marker
- const modDate = (() => {
- const mm = //.exec(article.content || "");
- if (mm) { try { return new Date(mm[1]).toISOString(); } catch (e) { /* ignore */ } }
- return pubDate;
- })();
+ const modDate = articleModifiedTime(article.content || "", pubDate);
// VideoObject: ce je v clanku vgrajen YouTube video
const videoId = (() => {
@@ -518,6 +484,8 @@ export function serveStatic(app: Express) {
const jsonLd = {
"@context": "https://schema.org",
"@type": "NewsArticle",
+ "@id": `${articleUrl}#article`,
+ "inLanguage": "de-DE",
"headline": article.title,
"description": article.excerpt,
"image": [finalImage],
@@ -536,7 +504,7 @@ export function serveStatic(app: Express) {
"@id": articleUrl,
},
};
- const jsonLdTag = ``;
+ const jsonLdTag = ``;
const videoLd = videoId ? {
"@context": "https://schema.org",
@@ -557,6 +525,8 @@ export function serveStatic(app: Express) {
``,
``,
``,
+ ``,
+ ``,
``,
``,
``,
@@ -575,7 +545,7 @@ export function serveStatic(app: Express) {
``,
``,
``,
- `${escapeHtml(article.title)} - Volksmusik & Schlager | Folx Music Television`,
+ `${escapeHtml(article.title)} | FOLX TV`,
jsonLdTag,
videoLdTag,
].join("\n ");
@@ -765,6 +735,34 @@ export function serveStatic(app: Express) {
return;
}
+ const infoPath = pathOnly.replace(/\/+$/, "");
+ const info = INFO_SEO[infoPath];
+ if (info) {
+ let template = stripExistingMeta(await fs.promises.readFile(indexPath, "utf-8"));
+ const pageUrl = `${canonicalBase}${infoPath}`;
+ const title = `${info.title} | FOLX TV`;
+ const ld = { "@context": "https://schema.org", "@type": info.type,
+ "@id": `${pageUrl}#webpage`, url: pageUrl, name: title, description: info.description,
+ inLanguage: "de-DE", isPartOf: { "@id": `${canonicalBase}/#website` }, publisher: PUBLISHER(canonicalBase) };
+ template = template.replace(/[^<]*<\/title>/, [
+ `${escapeHtml(title)}`,
+ ``,
+ ``,
+ ``,
+ ``,
+ ``,
+ ``,
+ ``,
+ ``,
+ ``,
+ ``,
+ ``,
+ ``,
+ ].join("\n"));
+ res.status(200).type("html").send(template);
+ return;
+ }
+
// Neznana pot mora vrniti PRAVI 404, sicer Google dobi soft 404 (HTTP 200
// z naslovnico). Seznam mora ustrezati potem v client/src/App.tsx.
const KNOWN = [
diff --git a/shared/seo.ts b/shared/seo.ts
new file mode 100644
index 0000000..6346dfa
--- /dev/null
+++ b/shared/seo.ts
@@ -0,0 +1,53 @@
+export const SITE_URL = "https://folx.tv";
+export const HOME_TITLE = "Schlager & Volksmusik News";
+export const HOME_DESCRIPTION = "Aktuelle Schlager- und Volksmusik-News, Künstler-Interviews und Nachrichten aus der Musikszene. Jetzt Artikel und Videos auf FOLX TV entdecken.";
+
+export function publisherSchema(base = SITE_URL) {
+ return {
+ "@type": "NewsMediaOrganization",
+ "@id": `${base}/#organization`,
+ name: "Folx Music Television",
+ alternateName: "FOLX TV",
+ url: base,
+ description: HOME_DESCRIPTION,
+ logo: { "@type": "ImageObject", url: `${base}/og-image.jpg` },
+ sameAs: ["https://www.facebook.com/folxtv", "https://www.instagram.com/folxtv", "https://www.youtube.com/@folxmtv"],
+ };
+}
+
+export function homeSchema(base = SITE_URL) {
+ return { "@context": "https://schema.org", "@graph": [
+ publisherSchema(base),
+ { "@type": "WebSite", "@id": `${base}/#website`, url: `${base}/`,
+ name: "FOLX TV", alternateName: "Folx Music Television", description: HOME_DESCRIPTION,
+ inLanguage: "de-DE", publisher: { "@id": `${base}/#organization` },
+ potentialAction: { "@type": "SearchAction", target: { "@type": "EntryPoint", urlTemplate: `${base}/search?q={search_term_string}` }, "query-input": "required name=search_term_string" } },
+ { "@type": "CollectionPage", "@id": `${base}/#webpage`, url: `${base}/`,
+ name: `${HOME_TITLE} | FOLX TV`, description: HOME_DESCRIPTION, inLanguage: "de-DE",
+ isPartOf: { "@id": `${base}/#website` }, publisher: { "@id": `${base}/#organization` },
+ hasPart: { "@type": "CollectionPage", "@id": `${base}/category/News#webpage`, url: `${base}/category/News`, name: "News" } }
+ ] };
+}
+
+export function articleModifiedTime(content: string, published: string): string {
+ const marker = //.exec(content || "");
+ const time = marker ? new Date(marker[1]).getTime() : NaN;
+ return Number.isFinite(time) && time >= new Date(published).getTime() && time <= Date.now()
+ ? new Date(time).toISOString() : published;
+}
+
+export function articleGenre(content: string) {
+ const marker = //i.exec(content || "");
+ const badge = (marker ? marker[1] : "MUSIC NEWS").toUpperCase();
+ return badge === "MUSIC NEWS"
+ ? { words: ["Volksmusik", "Schlager", "Musik News"], section: "Musik News" }
+ : { words: ["Star News", "Promi News", "Promi"], section: "Star News" };
+}
+
+export const INFO_SEO: Record = {
+ "/ueber-uns": { title: "Über FOLX TV – Musik-News, Interviews und Fernsehen", description: "FOLX TV verbindet aktuelle Schlager- und Volksmusik-News mit Künstler-Interviews, Videos und eigenen TV-Produktionen. Mehr über unser Angebot.", type: "AboutPage" },
+ "/kontakt": { title: "Kontakt", description: "Kontakt zu FOLX TV: Fragen zu Artikeln, Musik-News, Interviews und unserem Programm. Schreiben Sie uns über das Kontaktformular.", type: "ContactPage" },
+ "/impressum": { title: "Impressum", description: "Anbieterangaben und rechtliche Informationen zu FOLX TV und dem Nachrichtenangebot auf folx.tv.", type: "WebPage" },
+ "/datenschutz": { title: "Datenschutz", description: "Informationen zum Datenschutz und zur Verarbeitung personenbezogener Daten auf folx.tv.", type: "WebPage" },
+ "/empfang-folx-tv": { title: "FOLX TV empfangen – Livestream, App, Kabel und IPTV", description: "Informationen zum Empfang des FOLX TV Fernsehprogramms: Livestream, Apps sowie Kabel und IPTV in Deutschland, Österreich und der Schweiz.", type: "WebPage" }
+};