folx-tv/server/vite.ts
sebastjanartic a55d69614f Update website links to use the correct domain for image sharing
Replace all instances of "www.folx.tv" with "folx.tv" in the client and server configurations to resolve SSL issues preventing image sharing on social media platforms.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 1f7e7e89-a520-4970-9645-37daadc466dc
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 20f43e40-d815-42d5-9bb6-37729939c10e
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/1f7e7e89-a520-4970-9645-37daadc466dc/mwtHL8H
Replit-Helium-Checkpoint-Created: true
2026-03-05 15:43:13 +00:00

120 lines
4.3 KiB
TypeScript

import { type Express } from "express";
import { createServer as createViteServer, createLogger } from "vite";
import { type Server } from "http";
import viteConfig from "../vite.config";
import fs from "fs";
import path from "path";
import { nanoid } from "nanoid";
import { storage } from "./storage";
const viteLogger = createLogger();
function escapeHtml(str: string): string {
return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}
function ogImageUrl(coverImage: string, baseUrl: string): string {
if (!coverImage) return "";
let imgPath = coverImage;
if (imgPath.endsWith(".webp")) {
imgPath = imgPath.replace(/\.webp$/, ".jpg");
}
return imgPath.startsWith("http") ? imgPath : `${baseUrl}${imgPath}`;
}
function stripExistingMeta(html: string): string {
html = html.replace(/<meta\s+property="og:[^"]*"[^>]*>\s*/gi, "");
html = html.replace(/<meta\s+name="twitter:[^"]*"[^>]*>\s*/gi, "");
html = html.replace(/<meta\s+name="description"[^>]*>\s*/gi, "");
html = html.replace(/<meta\s+name="keywords"[^>]*>\s*/gi, "");
return html;
}
export async function setupVite(server: Server, app: Express) {
const serverOptions = {
middlewareMode: true,
hmr: { server, path: "/vite-hmr" },
allowedHosts: true as const,
};
const vite = await createViteServer({
...viteConfig,
configFile: false,
customLogger: {
...viteLogger,
error: (msg, options) => {
viteLogger.error(msg, options);
process.exit(1);
},
},
server: serverOptions,
appType: "custom",
});
app.use(vite.middlewares);
app.use("/{*path}", async (req, res, next) => {
const url = req.originalUrl;
const canonicalBase = "https://folx.tv";
try {
const clientTemplate = path.resolve(
import.meta.dirname,
"..",
"client",
"index.html",
);
let template = await fs.promises.readFile(clientTemplate, "utf-8");
template = template.replace(
`src="/src/main.tsx"`,
`src="/src/main.tsx?v=${nanoid()}"`,
);
const articleMatch = url.match(/^\/article\/([^?#]+)/);
if (articleMatch) {
try {
const slug = decodeURIComponent(articleMatch[1]);
const article = await storage.getArticleBySlug(slug);
if (article) {
const articleUrl = `${canonicalBase}/article/${article.slug}`;
const imageUrl = ogImageUrl(article.coverImage || "", canonicalBase);
const finalImage = imageUrl || `${canonicalBase}/og-image.jpg`;
template = stripExistingMeta(template);
const ogTags = [
`<meta property="og:title" content="${escapeHtml(article.title)}" />`,
`<meta property="og:description" content="${escapeHtml(article.excerpt)}" />`,
`<meta property="og:type" content="article" />`,
`<meta property="og:url" content="${escapeHtml(articleUrl)}" />`,
`<meta property="og:image" content="${escapeHtml(finalImage)}" />`,
`<meta property="og:image:secure_url" content="${escapeHtml(finalImage)}" />`,
`<meta property="og:image:width" content="800" />`,
`<meta property="og:image:height" content="450" />`,
`<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(article.title)}" />`,
`<meta name="twitter:description" content="${escapeHtml(article.excerpt)}" />`,
`<meta name="twitter:image" content="${escapeHtml(finalImage)}" />`,
`<meta name="description" content="${escapeHtml(article.excerpt)}" />`,
`<title>${escapeHtml(article.title)} - Folx Music Television</title>`,
].join("\n ");
template = template.replace(/<title>[^<]*<\/title>/, ogTags);
}
} catch (e) {
}
}
const page = await vite.transformIndexHtml(url, template);
res.status(200).set({ "Content-Type": "text/html" }).end(page);
} catch (e) {
vite.ssrFixStacktrace(e as Error);
next(e);
}
});
}