Add personalized meta tags and optimize horoscope images for sharing

Implement dynamic meta tag generation for horoscope pages, including daily, weekly, and monthly predictions, and optimize the OG image for improved social sharing previews.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 23852c00-4779-460a-9e0c-d09fee4b6c92
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: dea1fe98-0dfb-4e47-9b94-3c50decbba8a
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/23852c00-4779-460a-9e0c-d09fee4b6c92/OPD8Ro3
Replit-Helium-Checkpoint-Created: true
This commit is contained in:
sebastjanartic 2026-03-08 07:25:10 +00:00
parent 1b3271c795
commit 8a263dee0f
4 changed files with 104 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

View File

@ -370,7 +370,6 @@ function SignDetail({ signIndex, onNavigate, aiHoroscopes }: { signIndex: number
} }
export default function HoroscopePage() { export default function HoroscopePage() {
usePageMeta("Horoskop - Volksmusik & Schlager", "Tägliches Horoskop für alle Sternzeichen. Ihr persönliches Tageshoroskop bei FOLX TV dem Volksmusik & Schlager Sender.");
const params = useParams<{ sign?: string }>(); const params = useParams<{ sign?: string }>();
const [selected, setSelected] = useState<number | null>(null); const [selected, setSelected] = useState<number | null>(null);
const detailRef = useRef<HTMLDivElement>(null); const detailRef = useRef<HTMLDivElement>(null);
@ -386,6 +385,27 @@ export default function HoroscopePage() {
} }
}, [params.sign]); }, [params.sign]);
const selectedSign = selected !== null ? SIGNS[selected] : null;
const selectedAi = selected !== null ? aiHoroscopes.find(h => h.signIndex === selected) : null;
const today = new Date().toLocaleDateString("de-AT", { day: "numeric", month: "long", year: "numeric" });
const metaTitle = selectedSign
? `${selectedSign.symbol} ${selectedSign.name} Horoskop Tages-, Wochen- & Monatshoroskop`
: "Horoskop Tages-, Wochen- & Monatshoroskop für alle Sternzeichen";
const metaDesc = selectedSign
? `${selectedSign.name} Horoskop für heute, ${today}. Tägliches, wöchentliches und monatliches Horoskop für ${selectedSign.name} (${selectedSign.date}). Liebe, Beruf & Gesundheit bei FOLX TV.`
: `Kostenloses Tageshoroskop, Wochenhoroskop & Monatshoroskop für alle 12 Sternzeichen. Liebe, Beruf, Gesundheit Ihr persönliches Horoskop bei FOLX TV, ${today}.`;
const ogImage = "https://folx.tv/images/horoskop-og.jpg";
usePageMeta(metaTitle, metaDesc, {
ogTitle: metaTitle,
ogDescription: metaDesc,
ogImage,
ogType: "website",
});
const handleSelect = (i: number) => { const handleSelect = (i: number) => {
setSelected(i); setSelected(i);
setTimeout(() => { setTimeout(() => {

View File

@ -95,6 +95,49 @@ export function serveStatic(app: Express) {
} }
} }
if (url.match(/^\/horoskop(\/|$|\?)/)) {
let template = await fs.promises.readFile(indexPath, "utf-8");
template = stripExistingMeta(template);
const signMatch = url.match(/^\/horoskop\/([^?#]+)/);
const signName = signMatch ? decodeURIComponent(signMatch[1]) : null;
const capitalSign = signName ? signName.charAt(0).toUpperCase() + signName.slice(1) : null;
const title = capitalSign
? `${capitalSign} Horoskop Tages-, Wochen- & Monatshoroskop | Folx Music Television`
: "Horoskop Tages-, Wochen- & Monatshoroskop für alle Sternzeichen | Folx Music Television";
const desc = capitalSign
? `${capitalSign} Horoskop: Tägliches, wöchentliches und monatliches Horoskop. Liebe, Beruf & Gesundheit bei FOLX TV.`
: "Kostenloses Tageshoroskop, Wochenhoroskop & Monatshoroskop für alle 12 Sternzeichen. Liebe, Beruf, Gesundheit bei FOLX TV.";
const horoUrl = `${canonicalBase}${signName ? `/horoskop/${signName}` : "/horoskop"}`;
const horoImage = `${canonicalBase}/images/horoskop-og.jpg`;
const horoTags = [
`<meta property="og:title" content="${escapeHtml(title)}" />`,
`<meta property="og:description" content="${escapeHtml(desc)}" />`,
`<meta property="og:type" content="website" />`,
`<meta property="og:url" content="${escapeHtml(horoUrl)}" />`,
`<meta property="og:image" content="${escapeHtml(horoImage)}" />`,
`<meta property="og:image:secure_url" content="${escapeHtml(horoImage)}" />`,
`<meta property="og:image:width" content="1200" />`,
`<meta property="og:image:height" content="675" />`,
`<meta property="og:image:type" content="image/jpeg" />`,
`<meta property="og:site_name" content="Folx Music Television" />`,
`<meta property="og:locale" content="de_DE" />`,
`<meta name="twitter:card" content="summary_large_image" />`,
`<meta name="twitter:title" content="${escapeHtml(title)}" />`,
`<meta name="twitter:description" content="${escapeHtml(desc)}" />`,
`<meta name="twitter:image" content="${escapeHtml(horoImage)}" />`,
`<meta name="description" content="${escapeHtml(desc)}" />`,
`<meta name="keywords" content="Horoskop, Tageshoroskop, Wochenhoroskop, Monatshoroskop, Sternzeichen, Volksmusik, FOLX TV${capitalSign ? `, ${capitalSign}` : ""}" />`,
`<link rel="canonical" href="${escapeHtml(horoUrl)}" />`,
`<title>${escapeHtml(title)}</title>`,
].join("\n ");
template = template.replace(/<title>[^<]*<\/title>/, horoTags);
res.status(200).set({ "Content-Type": "text/html" }).end(template);
return;
}
let template = await fs.promises.readFile(indexPath, "utf-8"); let template = await fs.promises.readFile(indexPath, "utf-8");
res.status(200).set({ "Content-Type": "text/html" }).end(template); res.status(200).set({ "Content-Type": "text/html" }).end(template);
}); });

View File

@ -113,6 +113,46 @@ export async function setupVite(server: Server, app: Express) {
} }
} }
if (url.match(/^\/horoskop(\/|$|\?)/)) {
template = stripExistingMeta(template);
const signMatch = url.match(/^\/horoskop\/([^?#]+)/);
const signName = signMatch ? decodeURIComponent(signMatch[1]) : null;
const capitalSign = signName ? signName.charAt(0).toUpperCase() + signName.slice(1) : null;
const title = capitalSign
? `${capitalSign} Horoskop Tages-, Wochen- & Monatshoroskop | Folx Music Television`
: "Horoskop Tages-, Wochen- & Monatshoroskop für alle Sternzeichen | Folx Music Television";
const desc = capitalSign
? `${capitalSign} Horoskop: Tägliches, wöchentliches und monatliches Horoskop. Liebe, Beruf & Gesundheit bei FOLX TV.`
: "Kostenloses Tageshoroskop, Wochenhoroskop & Monatshoroskop für alle 12 Sternzeichen. Liebe, Beruf, Gesundheit bei FOLX TV.";
const horoUrl = `${canonicalBase}${signName ? `/horoskop/${signName}` : "/horoskop"}`;
const horoImage = `${canonicalBase}/images/horoskop-og.jpg`;
const horoTags = [
`<meta property="og:title" content="${escapeHtml(title)}" />`,
`<meta property="og:description" content="${escapeHtml(desc)}" />`,
`<meta property="og:type" content="website" />`,
`<meta property="og:url" content="${escapeHtml(horoUrl)}" />`,
`<meta property="og:image" content="${escapeHtml(horoImage)}" />`,
`<meta property="og:image:secure_url" content="${escapeHtml(horoImage)}" />`,
`<meta property="og:image:width" content="1200" />`,
`<meta property="og:image:height" content="675" />`,
`<meta property="og:image:type" content="image/jpeg" />`,
`<meta property="og:site_name" content="Folx Music Television" />`,
`<meta property="og:locale" content="de_DE" />`,
`<meta name="twitter:card" content="summary_large_image" />`,
`<meta name="twitter:title" content="${escapeHtml(title)}" />`,
`<meta name="twitter:description" content="${escapeHtml(desc)}" />`,
`<meta name="twitter:image" content="${escapeHtml(horoImage)}" />`,
`<meta name="description" content="${escapeHtml(desc)}" />`,
`<meta name="keywords" content="Horoskop, Tageshoroskop, Wochenhoroskop, Monatshoroskop, Sternzeichen, Volksmusik, FOLX TV${capitalSign ? `, ${capitalSign}` : ""}" />`,
`<link rel="canonical" href="${escapeHtml(horoUrl)}" />`,
`<title>${escapeHtml(title)}</title>`,
].join("\n ");
template = template.replace(/<title>[^<]*<\/title>/, horoTags);
}
const page = await vite.transformIndexHtml(url, template); const page = await vite.transformIndexHtml(url, template);
res.status(200).set({ "Content-Type": "text/html" }).end(page); res.status(200).set({ "Content-Type": "text/html" }).end(page);
} catch (e) { } catch (e) {