Add automatic Facebook sharing with video previews
Implement server-side Open Graph meta tags for videos and update video sharing functionality. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 401e2ec0-e00d-4f10-9d0e-60f3d479f9a5 Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Event-Id: 3500eb91-6967-423b-a9b5-22b380def61b Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/60d372ff-2c10-46c7-b01b-10c3435136b0/401e2ec0-e00d-4f10-9d0e-60f3d479f9a5/lPVBpdc
This commit is contained in:
parent
4f47d64e64
commit
3cec2d8f2e
16
.replit
16
.replit
@ -15,22 +15,6 @@ run = ["npm", "run", "start"]
|
|||||||
localPort = 5000
|
localPort = 5000
|
||||||
externalPort = 80
|
externalPort = 80
|
||||||
|
|
||||||
[[ports]]
|
|
||||||
localPort = 33967
|
|
||||||
externalPort = 3002
|
|
||||||
|
|
||||||
[[ports]]
|
|
||||||
localPort = 34033
|
|
||||||
externalPort = 3001
|
|
||||||
|
|
||||||
[[ports]]
|
|
||||||
localPort = 35637
|
|
||||||
externalPort = 3000
|
|
||||||
|
|
||||||
[[ports]]
|
|
||||||
localPort = 41219
|
|
||||||
externalPort = 3003
|
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
PORT = "5000"
|
PORT = "5000"
|
||||||
|
|
||||||
|
|||||||
@ -315,6 +315,13 @@ export default function VideoPage() {
|
|||||||
return `${baseUrl}/video/${currentVideo.id}`;
|
return `${baseUrl}/video/${currentVideo.id}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Facebook share URL uses special endpoint with proper OG meta tags
|
||||||
|
const getFacebookShareUrl = () => {
|
||||||
|
if (!currentVideo?.id) return window.location.origin;
|
||||||
|
const baseUrl = 'https://video.folx.tv';
|
||||||
|
return `${baseUrl}/share/video/${currentVideo.id}`;
|
||||||
|
};
|
||||||
|
|
||||||
const copyToClipboard = async () => {
|
const copyToClipboard = async () => {
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(getShareUrl());
|
await navigator.clipboard.writeText(getShareUrl());
|
||||||
@ -732,7 +739,7 @@ export default function VideoPage() {
|
|||||||
|
|
||||||
{showShareMenu && (
|
{showShareMenu && (
|
||||||
<div className="absolute right-0 top-full mt-2 bg-gray-800 rounded-lg shadow-lg py-2 z-50 min-w-[200px]">
|
<div className="absolute right-0 top-full mt-2 bg-gray-800 rounded-lg shadow-lg py-2 z-50 min-w-[200px]">
|
||||||
<FacebookShareButton url={getShareUrl()}>
|
<FacebookShareButton url={getFacebookShareUrl()}>
|
||||||
<div className="w-full px-4 py-2 text-left text-white hover:bg-gray-700 flex items-center gap-2 cursor-pointer">
|
<div className="w-full px-4 py-2 text-left text-white hover:bg-gray-700 flex items-center gap-2 cursor-pointer">
|
||||||
<FacebookIcon size={16} round />
|
<FacebookIcon size={16} round />
|
||||||
Facebook
|
Facebook
|
||||||
|
|||||||
@ -1280,6 +1280,93 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Facebook/Social Media Share Page - Returns HTML with proper OG tags for video sharing
|
||||||
|
app.get('/share/video/:id', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
const video = await findVideoByAnyId(id);
|
||||||
|
|
||||||
|
if (!video) {
|
||||||
|
return res.status(404).send('Video not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseUrl = 'https://video.folx.tv';
|
||||||
|
const videoUrl = `${baseUrl}/video/${video.id}`;
|
||||||
|
|
||||||
|
// Get high-quality thumbnail for sharing (1200x630 is ideal for Facebook)
|
||||||
|
const thumbnailUrl = video.thumbnailUrl
|
||||||
|
? video.thumbnailUrl.replace('width=400&height=225', 'width=1200&height=630').replace('format=webp', 'format=jpg')
|
||||||
|
: `${baseUrl}/api/social-image`;
|
||||||
|
|
||||||
|
// Clean description for meta tags
|
||||||
|
const description = video.description
|
||||||
|
? video.description.substring(0, 200).replace(/[<>"']/g, '')
|
||||||
|
: `Gledajte ${video.title} na video.folx.tv - Najboljša glasba`;
|
||||||
|
|
||||||
|
const title = video.title || 'video.folx.tv';
|
||||||
|
|
||||||
|
// Return HTML page with OG tags that redirects to actual video
|
||||||
|
const html = `<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>${title} - video.folx.tv</title>
|
||||||
|
|
||||||
|
<!-- Open Graph meta tags for Facebook -->
|
||||||
|
<meta property="og:type" content="video.other">
|
||||||
|
<meta property="og:title" content="${title}">
|
||||||
|
<meta property="og:description" content="${description}">
|
||||||
|
<meta property="og:image" content="${thumbnailUrl}">
|
||||||
|
<meta property="og:image:width" content="1200">
|
||||||
|
<meta property="og:image:height" content="630">
|
||||||
|
<meta property="og:image:type" content="image/jpeg">
|
||||||
|
<meta property="og:url" content="${videoUrl}">
|
||||||
|
<meta property="og:site_name" content="video.folx.tv">
|
||||||
|
<meta property="og:locale" content="de_DE">
|
||||||
|
|
||||||
|
<!-- Twitter Card meta tags -->
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<meta name="twitter:title" content="${title}">
|
||||||
|
<meta name="twitter:description" content="${description}">
|
||||||
|
<meta name="twitter:image" content="${thumbnailUrl}">
|
||||||
|
|
||||||
|
<!-- Redirect to actual video page for humans -->
|
||||||
|
<meta http-equiv="refresh" content="0;url=${videoUrl}">
|
||||||
|
<link rel="canonical" href="${videoUrl}">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background: #1a1a2e;
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.container { text-align: center; }
|
||||||
|
a { color: #da234d; text-decoration: none; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Preusmerjanje...</h1>
|
||||||
|
<p>Če se ne preusmeri avtomatično, <a href="${videoUrl}">kliknite tukaj</a>.</p>
|
||||||
|
</div>
|
||||||
|
<script>window.location.href = "${videoUrl}";</script>
|
||||||
|
</body>
|
||||||
|
</html>`;
|
||||||
|
|
||||||
|
res.set('Content-Type', 'text/html');
|
||||||
|
res.send(html);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error generating share page:', error);
|
||||||
|
res.status(500).send('Error generating share page');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// SEO - Sitemap XML with all video pages
|
// SEO - Sitemap XML with all video pages
|
||||||
app.get('/sitemap.xml', async (req, res) => {
|
app.get('/sitemap.xml', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user