diff --git a/website/alternatives/index.html b/website/alternatives/index.html new file mode 100644 index 0000000..3b7b2da --- /dev/null +++ b/website/alternatives/index.html @@ -0,0 +1,189 @@ + + + + + + {{ALT_INDEX_TITLE}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + + +
+ +
+ + + + + + diff --git a/website/alternatives/screen-sharing.html b/website/alternatives/screen-sharing.html new file mode 100644 index 0000000..5ded34c --- /dev/null +++ b/website/alternatives/screen-sharing.html @@ -0,0 +1,199 @@ + + + + + + {{ALT_SCREEN_TITLE}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + + +
+ +
+ + + + + + diff --git a/website/alternatives/teleparty.html b/website/alternatives/teleparty.html new file mode 100644 index 0000000..51ef580 --- /dev/null +++ b/website/alternatives/teleparty.html @@ -0,0 +1,199 @@ + + + + + + {{ALT_TELEPARTY_TITLE}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + + +
+ +
+ + + + + + diff --git a/website/app.js b/website/app.js index 3a1a83d..a6b5054 100644 --- a/website/app.js +++ b/website/app.js @@ -488,6 +488,14 @@ document.addEventListener('DOMContentLoaded', () => { homeLinks.forEach(link => { link.href = (activeLang === 'en') ? './' : `${activeLang}/`; }); + + const altLinks = document.querySelectorAll('a[href*="alternatives"]'); + altLinks.forEach(link => { + const attr = link.getAttribute('href'); + if (attr === 'alternatives' || attr === 'alternatives/teleparty' || attr.endsWith('/alternatives')) { + link.href = (activeLang === 'en') ? 'alternatives' : `${activeLang}/alternatives`; + } + }); } }; @@ -529,6 +537,29 @@ document.addEventListener('DOMContentLoaded', () => { return; } + const pathSegments = path.split('/'); + const isAlternative = pathSegments.includes('alternatives'); + if (isAlternative) { + let target; + const firstSeg = pathSegments[1]; + const isLangSubdir = ['de', 'fr', 'es', 'it', 'nl', 'pl', 'pt', 'pt-BR', 'tr', 'ru', 'ja', 'ko', 'zh', 'uk'].includes(firstSeg); + + if (newLang === 'en') { + if (isLangSubdir) { + pathSegments.splice(1, 1); + } + } else { + if (isLangSubdir) { + pathSegments[1] = newLang; + } else { + pathSegments.splice(1, 0, newLang); + } + } + target = pathSegments.join('/'); + window.location.href = target + window.location.hash; + return; + } + // Determine if we are on a static landing page versus a dynamic utility page const isIndex = !path.includes('join'); diff --git a/website/build.cjs b/website/build.cjs index f178971..e6b04ad 100644 --- a/website/build.cjs +++ b/website/build.cjs @@ -174,6 +174,8 @@ async function compile() { let compiled = templateContent; compiled = compiled.replace(/\{\{ASSET_PATH\}\}/g, assetPath); compiled = compiled.replace(/\{\{VERSION\}\}/g, buildVersion); + const langPrefix = lang === 'en' ? '' : `${lang}/`; + compiled = compiled.replace(/\{\{LANG_PREFIX\}\}/g, langPrefix); languages.forEach(l => { compiled = compiled.replace(new RegExp(`\\{\\{SELECTED_${l.toUpperCase()}\\}\\}`, 'g'), l === lang ? 'selected' : ''); }); @@ -183,6 +185,44 @@ async function compile() { return compiled; } + // Read alternative page templates + const telepartyTemplatePath = path.join(websiteDir, 'alternatives/teleparty.html'); + const screenSharingTemplatePath = path.join(websiteDir, 'alternatives/screen-sharing.html'); + const overviewTemplatePath = path.join(websiteDir, 'alternatives/index.html'); + const hasTelepartyTemplate = fs.existsSync(telepartyTemplatePath); + const hasScreenSharingTemplate = fs.existsSync(screenSharingTemplatePath); + const hasOverviewTemplate = fs.existsSync(overviewTemplatePath); + const telepartyTemplate = hasTelepartyTemplate ? fs.readFileSync(telepartyTemplatePath, 'utf8') : ''; + const screenSharingTemplate = hasScreenSharingTemplate ? fs.readFileSync(screenSharingTemplatePath, 'utf8') : ''; + const overviewTemplate = hasOverviewTemplate ? fs.readFileSync(overviewTemplatePath, 'utf8') : ''; + + // Preload English locale for fallback + const englishLocalePath = path.join(localesDir, 'en.json'); + const englishLocale = JSON.parse(fs.readFileSync(englishLocalePath, 'utf8')); + + function compileAlternativePage(templateContent, locale, lang, assetPath, langPrefix) { + let compiled = templateContent; + compiled = compiled.replace(/\{\{LANG_CODE\}\}/g, lang); + compiled = compiled.replace(/\{\{ASSET_PATH\}\}/g, assetPath); + compiled = compiled.replace(/\{\{LANG_PREFIX\}\}/g, langPrefix); + compiled = compiled.replace(/\{\{VERSION\}\}/g, buildVersion); + + const indexTitle = lang === 'de' ? 'KoalaSync - Vergleiche & Anleitungen' : 'KoalaSync - Alternatives & Comparisons'; + const indexDesc = lang === 'de' + ? 'Entdecke ehrliche Vergleiche und detaillierte Leitfäden zwischen KoalaSync und anderen Watch-Party-Erweiterungen.' + : 'Explore honest comparisons and detailed guides comparing KoalaSync with other watch party extensions and streaming solutions.'; + + compiled = compiled.replace(/\{\{ALT_INDEX_TITLE\}\}/g, indexTitle); + compiled = compiled.replace(/\{\{ALT_INDEX_META_DESC\}\}/g, indexDesc); + + // Merge locale with English fallback for keys not present in current locale + const mergedLocale = { ...englishLocale, ...locale }; + for (const [key, value] of Object.entries(mergedLocale)) { + compiled = compiled.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), value); + } + return compiled; + } + for (const lang of languages) { const localePath = path.join(localesDir, `${lang}.json`); if (!fs.existsSync(localePath)) { console.warn(`Warning: Locale ${lang} not found.`); continue; } @@ -193,6 +233,26 @@ async function compile() { const html = compilePage(locale, '', lang); fs.writeFileSync(path.join(wwwDir, 'index.html'), html); englishHtml[''] = html; + + // Compile alternatives for English (assets resolved using '../' prefix) + if (hasTelepartyTemplate) { + const altDir = path.join(wwwDir, 'alternatives'); + fs.mkdirSync(altDir, { recursive: true }); + const tpCompiled = compileAlternativePage(telepartyTemplate, locale, lang, '../', ''); + fs.writeFileSync(path.join(altDir, 'teleparty.html'), tpCompiled); + } + if (hasScreenSharingTemplate) { + const altDir = path.join(wwwDir, 'alternatives'); + fs.mkdirSync(altDir, { recursive: true }); + const ssCompiled = compileAlternativePage(screenSharingTemplate, locale, lang, '../', ''); + fs.writeFileSync(path.join(altDir, 'screen-sharing.html'), ssCompiled); + } + if (hasOverviewTemplate) { + const altDir = path.join(wwwDir, 'alternatives'); + fs.mkdirSync(altDir, { recursive: true }); + const ovCompiled = compileAlternativePage(overviewTemplate, locale, lang, '../', ''); + fs.writeFileSync(path.join(altDir, 'index.html'), ovCompiled); + } } else { console.log(`Compiling ${lang.toUpperCase()} (${lang}/index.html)...`); const langDir = path.join(wwwDir, lang); @@ -200,6 +260,26 @@ async function compile() { const html = compilePage(locale, '../', lang); fs.writeFileSync(path.join(langDir, 'index.html'), html); englishHtml[lang] = html; + + // Compile alternatives for other languages (assets resolved using '../../' prefix) + if (hasTelepartyTemplate) { + const langAltDir = path.join(langDir, 'alternatives'); + fs.mkdirSync(langAltDir, { recursive: true }); + const tpCompiled = compileAlternativePage(telepartyTemplate, locale, lang, '../../', lang + '/'); + fs.writeFileSync(path.join(langAltDir, 'teleparty.html'), tpCompiled); + } + if (hasScreenSharingTemplate) { + const langAltDir = path.join(langDir, 'alternatives'); + fs.mkdirSync(langAltDir, { recursive: true }); + const ssCompiled = compileAlternativePage(screenSharingTemplate, locale, lang, '../../', lang + '/'); + fs.writeFileSync(path.join(langAltDir, 'screen-sharing.html'), ssCompiled); + } + if (hasOverviewTemplate) { + const langAltDir = path.join(langDir, 'alternatives'); + fs.mkdirSync(langAltDir, { recursive: true }); + const ovCompiled = compileAlternativePage(overviewTemplate, locale, lang, '../../', lang + '/'); + fs.writeFileSync(path.join(langAltDir, 'index.html'), ovCompiled); + } } } @@ -219,6 +299,7 @@ async function compile() { const src = path.join(websiteDir, mapping.src); const dest = path.join(wwwDir, mapping.dest); if (fs.existsSync(src)) { + fs.mkdirSync(path.dirname(dest), { recursive: true }); fs.copyFileSync(src, dest); console.log(` Copied: ${mapping.src} → ${mapping.dest}`); } @@ -278,23 +359,15 @@ async function compile() { let html = fs.readFileSync(filePath, 'utf8'); // 8a. Replace hashed asset refs - html = html.replace(/href="(?:\.\.\/)?style\.min\.css"/g, (m) => { - const prefix = m.includes('../') ? '../' : ''; + html = html.replace(/href="((?:\.\.\/)*)style\.min\.css"/g, (m, prefix) => { return `href="${prefix}${styleName}"`; }); - html = html.replace(/src="(?:\.\.\/)?app\.min\.js"/g, (m) => { - const prefix = m.includes('../') ? '../' : ''; + html = html.replace(/src="((?:\.\.\/)*)app\.min\.js"/g, (m, prefix) => { return `src="${prefix}${appName}"`; }); - html = html.replace(/src="(?:\.\.\/)?lang-init\.min\.js"/g, (m) => { - const prefix = m.includes('../') ? '../' : ''; + html = html.replace(/src="((?:\.\.\/)*)lang-init\.min\.js"/g, (m, prefix) => { return `src="${prefix}${langName}"`; }); - // Also update preload directives - html = html.replace(/href="(?:\.\.\/)?style\.min\.css"/g, (m) => { - const prefix = m.includes('../') ? '../' : ''; - return `href="${prefix}${styleName}"`; - }); // 8b. Inject AVIF wrappers html = injectAvifPictures(html); diff --git a/website/datenschutz-de.html b/website/datenschutz-de.html index 29dfaad..6cd7f39 100644 --- a/website/datenschutz-de.html +++ b/website/datenschutz-de.html @@ -160,6 +160,7 @@
Impressum Datenschutz + Vergleiche & Anleitungen Mastodon diff --git a/website/impressum-de.html b/website/impressum-de.html index e5aa2c5..17c82a9 100644 --- a/website/impressum-de.html +++ b/website/impressum-de.html @@ -147,6 +147,7 @@
Impressum Datenschutz + Vergleiche & Anleitungen Mastodon diff --git a/website/imprint.html b/website/imprint.html index 94dc2ab..45c31d9 100644 --- a/website/imprint.html +++ b/website/imprint.html @@ -145,6 +145,7 @@
Legal Notice Privacy Policy + Guides & comparisons Mastodon diff --git a/website/join.html b/website/join.html index de2bece..74cd796 100644 --- a/website/join.html +++ b/website/join.html @@ -119,6 +119,7 @@
Legal NoticeImpressum Privacy PolicyDatenschutz + Guides & comparisonsVergleiche & Anleitungen Mastodon diff --git a/website/locales/de.json b/website/locales/de.json index 5ca7a2a..25be927 100644 --- a/website/locales/de.json +++ b/website/locales/de.json @@ -176,5 +176,32 @@ "FOOTER_LEGAL_LINK": "de/impressum", "FOOTER_PRIVACY_LINK": "de/datenschutz", "FOOTER_DISCLAIMER": "KoalaSync ist nicht mit Netflix, Disney+, Amazon, YouTube, Twitch oder anderen Streaming-Plattformen verbunden, wird von diesen nicht unterstützt oder steht in keiner Beziehung zu diesen. Alle Markenrechte liegen bei ihren jeweiligen Inhabern.", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TELEPARTY_TITLE": "KoalaSync vs Teleparty: Welche Watch-Party-Lösung passt besser?", + "ALT_TELEPARTY_META_DESC": "Ein ehrlicher Vergleich von KoalaSync und Teleparty für Watch-Partys, eingebauten Chat, Mobile-Support, Browser-Video-Sync, selbst gehostete Medienserver und Open Source.", + "ALT_TELEPARTY_INTRO": "KoalaSync und Teleparty lösen beide dasselbe nervige Problem: Du willst mit anderen Leuten online etwas schauen, ohne ständig „3, 2, 1, Play“ sagen zu müssen. Beide synchronisieren Videowiedergabe, aber sie gehen ziemlich unterschiedlich an die Sache ran.

Teleparty ist sinnvoll, wenn du einen eingebauten Chat möchtest oder am Handy schauen willst. KoalaSync ist eher für Desktop-Browser-Watch-Partys gedacht, bei denen du sowieso schon mit Freunden in Discord, Teamspeak oder einem anderen Voice-Call bist und einfach nur die Wiedergabe synchron halten möchtest.

Der Hauptgrund, warum ich KoalaSync gebaut habe, war Flexibilität. Es soll mit fast jeder Website funktionieren, die einen normalen Browser-Videoplayer nutzt, nicht nur mit einer festen Liste an Plattformen. Dazu gehören auch selbst gehostete Setups wie Emby, Jellyfin und Plex, lokale oder private Domains und viele normale Videoseiten im Browser.", + "ALT_TELEPARTY_WHEN_TELE_TITLE": "Wann Teleparty trotzdem sinnvoller sein kann", + "ALT_TELEPARTY_WHEN_TELE_BODY": "Teleparty kann trotzdem die bessere Wahl sein, wenn du den Chat direkt im Watch-Party-Tool haben möchtest. KoalaSync hat aktuell keinen eingebauten Chat. Es geht eher davon aus, dass du sowieso schon woanders mit deinen Freunden redest, zum Beispiel in Discord, Teamspeak, WhatsApp, Signal oder einem normalen Anruf.

Mobile ist der zweite große Unterschied. Teleparty hat eine App, während KoalaSync aktuell nur auf Desktop-Browsern läuft. Wenn du Netflix oder andere Inhalte am Handy oder Tablet synchron schauen möchtest, ist KoalaSync im Moment nicht das richtige Tool dafür.

Wenn dir also vor allem eingebauter Chat und Mobile-Support wichtig sind, passt Teleparty wahrscheinlich besser zu deinem Setup.", + "ALT_TELEPARTY_WHEN_KOALA_TITLE": "Wann KoalaSync besser passt", + "ALT_TELEPARTY_WHEN_KOALA_BODY": "KoalaSync passt besser, wenn du ein flexibles Sync-Tool für den Desktop-Browser suchst und nicht auf eine kurze Plattformliste beschränkt sein möchtest.

Es funktioniert mit fast jeder Website, die einen normalen Browser-Videoplayer nutzt. Das ist besonders nützlich für Emby, Jellyfin, Plex, private Medienserver, lokale Domains oder kleinere Videoseiten, die klassische Watch-Party-Tools meistens gar nicht beachten.

Außerdem ist KoalaSync kostenlos, Open Source, braucht keine Accounts und kann bei Bedarf selbst gehostet werden. Ich habe es gebaut, weil ich etwas Privacy-freundliches wollte, das mit meinem eigenen Emby-Setup funktioniert, nicht noch eine geschlossene Plattform nur für ein paar große Streaming-Seiten.", + "ALT_TELEPARTY_MAIN_DIFF_TITLE": "Der wichtigste Unterschied", + "ALT_TELEPARTY_MAIN_DIFF_BODY": "Teleparty ist eher ein Watch-Party-Produkt mit Chat und Mobile-Unterstützung. KoalaSync ist eher eine flexible Sync-Schicht für Browser-Video.

Das klingt erstmal nach einem kleinen Unterschied, ändert aber den Use Case ziemlich stark. Wenn du eine Watch-Party-App mit eingebautem Chat brauchst, ergibt Teleparty Sinn. Wenn du schon einen Voice-Call hast und nur möchtest, dass Play, Pause und Seek zwischen mehreren Browsern synchron bleiben, passt KoalaSync besser.", + "ALT_TELEPARTY_LIMITS_TITLE": "Ehrliche Grenzen", + "ALT_TELEPARTY_LIMITS_BODY": "KoalaSync ist nicht magisch und versucht auch nicht, seine Grenzen zu verstecken. Es funktioniert aktuell nur auf Desktop-Browsern. Es gibt keinen eingebauten Chat und keine Mobile-App.

Die Kompatibilität hängt außerdem vom Browser und vom jeweiligen Videoplayer ab. KoalaSync sollte mit fast jedem normalen Browser-Videoplayer funktionieren, aber Websites können ihre Player, DRM-Logik oder Browser-Einschränkungen jederzeit ändern.

KoalaSync ist nicht mit Netflix, Disney+, Prime Video, YouTube, Teleparty, Emby, Jellyfin, Plex oder anderen hier genannten Marken verbunden. Die Namen werden nur verwendet, um typische Anwendungsfälle verständlich zu beschreiben.", + "ALT_TELEPARTY_SUMMARY_TITLE": "Kurz gesagt", + "ALT_TELEPARTY_SUMMARY_BODY": "Wenn du eingebauten Chat oder Mobile-Support brauchst, passt Teleparty wahrscheinlich besser. Wenn du kostenlose, Open-Source-Desktop-Browser-Synchronisierung möchtest, die mit fast jedem normalen Videoplayer funktioniert, inklusive selbst gehosteter Medienserver wie Emby, Jellyfin und Plex, ist KoalaSync wahrscheinlich die passendere Wahl.", + "ALT_SCREEN_TITLE": "KoalaSync vs Bildschirmübertragung: Wann ist Video-Sync besser?", + "ALT_SCREEN_META_DESC": "Ein ehrlicher Vergleich von KoalaSync und Bildschirmübertragung für Filmabende, Wiedergabekontrolle, Videoqualität, Privatsphäre, Untertitel und gemeinsames Schauen im Browser.", + "ALT_SCREEN_INTRO": "Bildschirmübertragung funktioniert, und manchmal reicht das auch völlig. Eine Person teilt den Bildschirm, alle anderen schauen zu, fertig.

Bei längeren Filmabenden oder Serien kann das aber schnell nervig werden. Die Qualität hängt vom Upload, der CPU, dem Browser und der Komprimierung durch Discord, Teamspeak, Zoom oder andere Call-Apps ab. Außerdem kontrolliert nur eine Person wirklich die Wiedergabe.", + "ALT_SCREEN_WHEN_ENOUGH_TITLE": "Wann Bildschirmübertragung reicht", + "ALT_SCREEN_WHEN_ENOUGH_BODY": "Screen Sharing ist sinnvoll, wenn es möglichst schnell gehen soll. Wenn nur eine Person Zugriff auf das Video hat oder alle damit okay sind, dass eine Person Play, Pause und Spulen kontrolliert, ist es wahrscheinlich die einfachste Lösung.

Es reicht auch oft, wenn die Qualität nicht so wichtig ist, niemand eigene Untertitel oder Audio-Einstellungen braucht und die Person, die teilt, kein Problem damit hat, genau dieses Fenster oder diesen Bildschirm zu zeigen.", + "ALT_SCREEN_WHEN_ANNOYING_TITLE": "Wo Bildschirmübertragung nervig wird", + "ALT_SCREEN_WHEN_ANNOYING_BODY": "Der größte Nachteil ist, dass nicht jeder im eigenen Player schaut. Eine Person streamt den Bildschirm, alle anderen sehen nur diesen Stream.

Das kann schlechtere Bildqualität, komprimierten Ton, Verzögerung und weniger Kontrolle für alle anderen bedeuten. Untertitel und Audiospur sind außerdem genau das, was die teilende Person eingestellt hat.

Dazu kommt der Privacy-Aspekt. Wenn du Fenster oder Tabs wechselst, können andere kurz deine Browser-Tabs, Mails, Reddit, Chats oder andere private Dinge sehen. Man kann das mit einem separaten Fenster umgehen, aber man muss trotzdem daran denken.", + "ALT_SCREEN_WHY_CLEANER_TITLE": "Warum KoalaSync sauberer sein kann", + "ALT_SCREEN_WHY_CLEANER_BODY": "KoalaSync überträgt nicht deinen Bildschirm. Jeder schaut das Video lokal im eigenen Browser, und KoalaSync hält nur Aktionen wie Play, Pause und Spulen zwischen allen Teilnehmern synchron.

Dadurch kann jeder lokal Vollbild nutzen, eigene Untertitel oder Audio-Einstellungen verwenden, sofern der Player das unterstützt, und der Voice-Call bleibt separat in Discord, Teamspeak oder einer anderen App.

Für Filmabende fühlt sich das oft deutlich sauberer an, als wenn eine Person den ganzen Bildschirm streamt. Besonders praktisch ist das bei browserbasierten Setups wie Emby, Jellyfin, Plex, lokalen Dateien im Browser, privaten Domains oder anderen Websites mit normalen Browser-Videoplayern.", + "ALT_SCREEN_LIMITS_TITLE": "Ehrliche Grenzen", + "ALT_SCREEN_LIMITS_BODY": "KoalaSync ersetzt keinen Voice-Call. Wenn ihr beim Schauen reden wollt, nutzt ihr weiterhin Discord, Teamspeak, Signal, WhatsApp oder was auch immer ihr normalerweise verwendet.

Außerdem braucht jede Person selbst Zugriff auf das Video oder die jeweilige Seite. KoalaSync umgeht keine Abos, Logins, DRM, regionale Einschränkungen oder Plattformregeln.

KoalaSync ist aktuell Desktop-Browser-only, hat keinen eingebauten Chat oder Voice-Chat und die Funktion hängt immer vom jeweiligen Browser und Videoplayer ab.", + "ALT_SCREEN_SUMMARY_TITLE": "Kurz gesagt", + "ALT_SCREEN_SUMMARY_BODY": "Bildschirmübertragung ist die einfachste Lösung, wenn es schnell gehen soll und Qualität, Privatsphäre oder individuelle Kontrolle nicht so wichtig sind. KoalaSync passt besser, wenn jeder lokal im eigenen Browser schauen soll und sich der Filmabend mehr wie wirklich gemeinsames Schauen anfühlen soll.", + "ALT_TRY_KOALASYNC": "KoalaSync ausprobieren" } diff --git a/website/locales/en.json b/website/locales/en.json index 0cf5b22..fb1724a 100644 --- a/website/locales/en.json +++ b/website/locales/en.json @@ -176,5 +176,32 @@ "FOOTER_LEGAL_LINK": "imprint", "FOOTER_PRIVACY_LINK": "privacy", "FOOTER_DISCLAIMER": "KoalaSync is not affiliated with, endorsed by, or associated with Netflix, Disney+, Amazon, YouTube, Twitch, or any other streaming platform. All trademarks are property of their respective owners.", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TELEPARTY_TITLE": "KoalaSync vs Teleparty: which watch party tool should you use?", + "ALT_TELEPARTY_META_DESC": "A practical comparison of KoalaSync and Teleparty for watch parties, built-in chat, mobile support, browser video sync, self-hosted media servers and open-source use.", + "ALT_TELEPARTY_INTRO": "KoalaSync and Teleparty both help with the same annoying problem: watching something together without doing the whole \"3, 2, 1, play\" routine. They just take a different approach.

Teleparty makes the most sense if you want a built-in chat or if you want to watch on mobile. KoalaSync is more for desktop browser watch parties where you are already talking on Discord, Teamspeak or another voice call and just want playback to stay in sync.

The main reason I built KoalaSync was flexibility. It is meant to work with almost any website that uses a normal browser video player, not just a fixed list of platforms. That includes self-hosted setups like Emby, Jellyfin and Plex, local/private domains, and a lot of normal video pages in the browser.", + "ALT_TELEPARTY_WHEN_TELE_TITLE": "When Teleparty may still make sense", + "ALT_TELEPARTY_WHEN_TELE_BODY": "Teleparty can still be the better choice if you want the chat to be part of the watch party tool itself. KoalaSync does not currently have a built-in chat. It assumes you are already talking somewhere else, like Discord, Teamspeak, WhatsApp, Signal or a normal call.

Mobile is the other big reason. Teleparty has an app, while KoalaSync currently only works on desktop browsers. If you want to sync Netflix on a phone or tablet, KoalaSync is not the right tool for that right now.

So if chat and mobile support are the things you care about most, Teleparty may simply fit your setup better.", + "ALT_TELEPARTY_WHEN_KOALA_TITLE": "When KoalaSync may fit better", + "ALT_TELEPARTY_WHEN_KOALA_BODY": "KoalaSync fits better if you want a flexible desktop browser sync tool instead of something tied to a short platform list.

It works with almost any website that uses a normal browser video player. That is especially useful for Emby, Jellyfin, Plex, private media servers, local domains, or smaller video sites that classic watch party tools usually ignore.

It is also free, open source, does not require accounts, and can be self-hosted if you want to run your own relay. I built it because I wanted something privacy-friendly that worked with my own Emby setup, not another closed platform just for a few big streaming sites.", + "ALT_TELEPARTY_MAIN_DIFF_TITLE": "The main difference", + "ALT_TELEPARTY_MAIN_DIFF_BODY": "Teleparty is more of a watch party product with chat and mobile support. KoalaSync is more of a flexible sync layer for browser video.

That sounds like a small difference, but it changes the use case a lot. If you need a full watch party app with chat inside it, Teleparty makes sense. If you already have voice chat and just want the video controls to stay synced across browsers, KoalaSync is the simpler fit.", + "ALT_TELEPARTY_LIMITS_TITLE": "Honest limitations", + "ALT_TELEPARTY_LIMITS_BODY": "KoalaSync is not magic and it is not trying to hide its limits. It currently works only on desktop browsers. It has no built-in chat and no mobile app.

Compatibility also depends on the browser and the video player. KoalaSync should work with almost any normal browser video player, but websites can change their players, DRM behavior or browser restrictions at any time.

KoalaSync is not affiliated with Netflix, Disney+, Prime Video, YouTube, Teleparty, Emby, Jellyfin, Plex or any other brand mentioned here. The names are only used to explain typical use cases.", + "ALT_TELEPARTY_SUMMARY_TITLE": "Summary", + "ALT_TELEPARTY_SUMMARY_BODY": "If you want built-in chat or mobile support, Teleparty may be the better fit. If you want free, open-source desktop browser sync that works with almost any normal video player, including self-hosted media servers like Emby, Jellyfin and Plex, KoalaSync is probably the better match.", + "ALT_SCREEN_TITLE": "KoalaSync vs screen sharing: when is video sync better?", + "ALT_SCREEN_META_DESC": "A practical comparison of KoalaSync and screen sharing for remote movie nights, playback control, video quality, privacy, subtitles and browser-based watching.", + "ALT_SCREEN_INTRO": "Screen sharing works, and sometimes it is honestly enough. One person shares their screen, everyone else watches, and you are done.

But for longer movie nights or watching episodes together, it can get annoying. The video quality depends on the sharer\u2019s upload, CPU, browser, and whatever compression Discord, Teamspeak, Zoom or another call app applies. Also, only one person really controls the playback.", + "ALT_SCREEN_WHEN_ENOUGH_TITLE": "When screen sharing is enough", + "ALT_SCREEN_WHEN_ENOUGH_BODY": "Screen sharing is fine when you want the fastest possible setup. If only one person has access to the video, or everyone is okay with one person controlling play, pause and seeking, it may be the simplest option.

It also makes sense when quality is not a big deal, when nobody needs their own subtitles or audio settings, and when the person sharing is comfortable showing that browser window or screen.", + "ALT_SCREEN_WHEN_ANNOYING_TITLE": "Where screen sharing gets annoying", + "ALT_SCREEN_WHEN_ANNOYING_BODY": "The biggest downside is that not everyone is watching in their own player. One person streams their screen, and everyone else only sees that stream.

That can mean worse video quality, compressed audio, delayed playback, and less control for everyone else. Subtitles and audio tracks are also whatever the sharer picked.

There is also the privacy side. If you switch windows or tabs, people may briefly see your browser tabs, email, Reddit, chats or other private stuff. You can work around that with a separate window, but it is still something you have to think about.", + "ALT_SCREEN_WHY_CLEANER_TITLE": "Why KoalaSync can feel cleaner", + "ALT_SCREEN_WHY_CLEANER_BODY": "KoalaSync does not stream your screen. Everyone watches the video locally in their own browser, and KoalaSync only keeps playback actions like play, pause and seeking in sync.

That means everyone can use fullscreen on their own device, use their own subtitle or audio settings if the player supports it, and keep the voice chat separate in Discord, Teamspeak or another call.

For movie nights, that can feel a lot cleaner than one person broadcasting their screen. It is especially useful for browser-based setups like Emby, Jellyfin, Plex, local files opened in the browser, private domains, or other websites with normal browser video players.", + "ALT_SCREEN_LIMITS_TITLE": "Honest limitations", + "ALT_SCREEN_LIMITS_BODY": "KoalaSync is not a replacement for a voice call. If you want to talk while watching, you still use Discord, Teamspeak, Signal, WhatsApp or whatever you normally use.

Everyone also needs access to the video or page on their own device. KoalaSync does not bypass subscriptions, logins, DRM, regional restrictions or platform rules.

It is currently desktop-browser only, has no built-in chat or voice feature, and compatibility always depends on the browser and the video player.", + "ALT_SCREEN_SUMMARY_TITLE": "Summary", + "ALT_SCREEN_SUMMARY_BODY": "Screen sharing is the simplest option when you just want something quick and do not care much about quality, privacy or individual control. KoalaSync is a better fit when everyone should watch locally in their own browser and the session should feel more like actually watching together.", + "ALT_TRY_KOALASYNC": "Try KoalaSync" } diff --git a/website/locales/es.json b/website/locales/es.json index 46821eb..751d4d3 100644 --- a/website/locales/es.json +++ b/website/locales/es.json @@ -176,5 +176,6 @@ "FOOTER_LEGAL_LINK": "imprint", "FOOTER_PRIVACY_LINK": "privacy", "FOOTER_DISCLAIMER": "KoalaSync no está afiliado, respaldado ni asociado con Netflix, Disney+, Amazon, YouTube, Twitch ni ninguna otra plataforma de streaming. Todas las marcas comerciales pertenecen a sus respectivos dueños.", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TRY_KOALASYNC": "Try KoalaSync" } diff --git a/website/locales/fr.json b/website/locales/fr.json index 79aa87b..fedf324 100644 --- a/website/locales/fr.json +++ b/website/locales/fr.json @@ -176,5 +176,6 @@ "FOOTER_LEGAL_LINK": "imprint", "FOOTER_PRIVACY_LINK": "privacy", "FOOTER_DISCLAIMER": "KoalaSync n'est pas affilié à Netflix, Disney+, Amazon, YouTube, Twitch ou toute autre plateforme de streaming. Toutes les marques déposées appartiennent à leurs détenteurs respectifs.", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TRY_KOALASYNC": "Try KoalaSync" } diff --git a/website/locales/it.json b/website/locales/it.json index 3b0d699..ff16b81 100644 --- a/website/locales/it.json +++ b/website/locales/it.json @@ -176,5 +176,6 @@ "FOOTER_LEGAL_LINK": "imprint", "FOOTER_PRIVACY_LINK": "privacy", "FOOTER_DISCLAIMER": "KoalaSync non è affiliato a Netflix, YouTube o altre piattaforme. I marchi appartengono ai rispettivi proprietari.", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TRY_KOALASYNC": "Try KoalaSync" } diff --git a/website/locales/ja.json b/website/locales/ja.json index cb949ec..6678f89 100644 --- a/website/locales/ja.json +++ b/website/locales/ja.json @@ -176,5 +176,6 @@ "FOOTER_LEGAL_LINK": "imprint", "FOOTER_PRIVACY_LINK": "privacy", "FOOTER_DISCLAIMER": "KoalaSyncは、Netflix、Disney+、Amazon、YouTube、Twitch、またはその他のストリーミングプラットフォームと提携、承認、または関連付けられているものではありません。すべての商標はそれぞれの所有者に帰属します。", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TRY_KOALASYNC": "Try KoalaSync" } diff --git a/website/locales/ko.json b/website/locales/ko.json index c0a9be7..4c48a62 100644 --- a/website/locales/ko.json +++ b/website/locales/ko.json @@ -176,5 +176,6 @@ "FOOTER_LEGAL_LINK": "imprint", "FOOTER_PRIVACY_LINK": "privacy", "FOOTER_DISCLAIMER": "KoalaSync는 Netflix, Disney+, Amazon, YouTube, Twitch 또는 기타 스트리밍 플랫폼과 제휴, 보증 또는 연관되어 있지 않습니다. 모든 상표는 해당 소유자의 재산입니다.", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TRY_KOALASYNC": "Try KoalaSync" } diff --git a/website/locales/nl.json b/website/locales/nl.json index 74c9596..d8f719e 100644 --- a/website/locales/nl.json +++ b/website/locales/nl.json @@ -176,5 +176,6 @@ "FOOTER_LEGAL_LINK": "imprint", "FOOTER_PRIVACY_LINK": "privacy", "FOOTER_DISCLAIMER": "KoalaSync is niet verbonden aan, goedgekeurd door of geassocieerd met Netflix, Disney+, Amazon, YouTube, Twitch of enig ander streamingplatform. Alle handelsmerken zijn eigendom van hun respectieve eigenaren.", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TRY_KOALASYNC": "Try KoalaSync" } diff --git a/website/locales/pl.json b/website/locales/pl.json index be17924..dbc839a 100644 --- a/website/locales/pl.json +++ b/website/locales/pl.json @@ -176,5 +176,6 @@ "FOOTER_LEGAL_LINK": "imprint", "FOOTER_PRIVACY_LINK": "privacy", "FOOTER_DISCLAIMER": "KoalaSync nie jest powiązany, wspierany ani stowarzyszony z Netflix, Disney+, Amazon, YouTube, Twitch ani żadną inną platformą streamingową. Wszystkie znaki towarowe są własnością ich odpowiednich właścicieli.", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TRY_KOALASYNC": "Try KoalaSync" } diff --git a/website/locales/pt-BR.json b/website/locales/pt-BR.json index adf1d4e..107f693 100644 --- a/website/locales/pt-BR.json +++ b/website/locales/pt-BR.json @@ -176,5 +176,6 @@ "FOOTER_LEGAL_LINK": "imprint", "FOOTER_PRIVACY_LINK": "privacy", "FOOTER_DISCLAIMER": "KoalaSync não é afiliado à Netflix, Disney+, YouTube, Twitch, etc. Todas as marcas registradas são de propriedade de seus respectivos donos.", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TRY_KOALASYNC": "Try KoalaSync" } diff --git a/website/locales/pt.json b/website/locales/pt.json index 8390172..cd0b7a7 100644 --- a/website/locales/pt.json +++ b/website/locales/pt.json @@ -176,5 +176,6 @@ "FOOTER_LEGAL_LINK": "imprint", "FOOTER_PRIVACY_LINK": "privacy", "FOOTER_DISCLAIMER": "KoalaSync não é afiliado à Netflix, Disney+, YouTube, Twitch, etc. Todas as marcas são propriedade dos seus titulares.", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TRY_KOALASYNC": "Try KoalaSync" } diff --git a/website/locales/ru.json b/website/locales/ru.json index 5dd6a93..a8ea01e 100644 --- a/website/locales/ru.json +++ b/website/locales/ru.json @@ -176,5 +176,6 @@ "FOOTER_LEGAL_LINK": "imprint", "FOOTER_PRIVACY_LINK": "privacy", "FOOTER_DISCLAIMER": "KoalaSync не связан, не спонсируется и не аффилирован с Netflix, Disney+, Amazon, YouTube, Twitch или любой другой стриминговой платформой. Все товарные знаки являются собственностью их соответствующих владельцев.", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TRY_KOALASYNC": "Try KoalaSync" } diff --git a/website/locales/tr.json b/website/locales/tr.json index 742f095..0a29918 100644 --- a/website/locales/tr.json +++ b/website/locales/tr.json @@ -176,5 +176,6 @@ "FOOTER_LEGAL_LINK": "imprint", "FOOTER_PRIVACY_LINK": "privacy", "FOOTER_DISCLAIMER": "KoalaSync; Netflix, Disney+, Amazon, YouTube, Twitch veya başka herhangi bir yayın platformuna bağlı değildir, bunlar tarafından desteklenmemektedir ve bunlarla ilişkili değildir. Tüm ticari markalar ilgili sahiplerinin mülkiyetindedir.", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TRY_KOALASYNC": "Try KoalaSync" } diff --git a/website/locales/uk.json b/website/locales/uk.json index 4fae431..4b43e61 100644 --- a/website/locales/uk.json +++ b/website/locales/uk.json @@ -176,5 +176,6 @@ "FOOTER_LEGAL_LINK": "imprint", "FOOTER_PRIVACY_LINK": "privacy", "FOOTER_DISCLAIMER": "KoalaSync не пов’язаний із Netflix, Disney+, Amazon, YouTube, Twitch або будь-якою іншою потоковою платформою, не схвалений і не пов’язаний з ними. Усі торгові марки є власністю відповідних власників.", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TRY_KOALASYNC": "Try KoalaSync" } diff --git a/website/locales/zh.json b/website/locales/zh.json index 02ed7b3..511d783 100644 --- a/website/locales/zh.json +++ b/website/locales/zh.json @@ -176,5 +176,6 @@ "FOOTER_LEGAL_LINK": "imprint", "FOOTER_PRIVACY_LINK": "privacy", "FOOTER_DISCLAIMER": "KoalaSync 不隶属于 Netflix、Disney+、Amazon、YouTube、Twitch 或任何其他流媒体平台,也不受其认可或关联。所有商标均为其各自所有者的财产。", - "FOOTER_SUPPORT": "Support KoalaSync" + "FOOTER_SUPPORT": "Support KoalaSync", + "ALT_TRY_KOALASYNC": "Try KoalaSync" } diff --git a/website/privacy.html b/website/privacy.html index d5b15fa..84b1226 100644 --- a/website/privacy.html +++ b/website/privacy.html @@ -163,6 +163,7 @@
Legal Notice Privacy Policy + Guides & comparisons Mastodon diff --git a/website/sitemap.xml b/website/sitemap.xml index 86f2d0f..1cb3f8b 100644 --- a/website/sitemap.xml +++ b/website/sitemap.xml @@ -25,6 +25,138 @@ monthly 0.3 + + https://sync.koalastuff.net/alternatives + 2026-06-24 + weekly + 0.7 + + + + + + + + + + + + + + + + + + + https://sync.koalastuff.net/de/alternatives + 2026-06-24 + weekly + 0.7 + + + + + + + + + + + + + + + + + + + https://sync.koalastuff.net/alternatives/teleparty + 2026-06-24 + weekly + 0.7 + + + + + + + + + + + + + + + + + + + https://sync.koalastuff.net/de/alternatives/teleparty + 2026-06-24 + weekly + 0.7 + + + + + + + + + + + + + + + + + + + https://sync.koalastuff.net/alternatives/screen-sharing + 2026-06-24 + weekly + 0.7 + + + + + + + + + + + + + + + + + + + https://sync.koalastuff.net/de/alternatives/screen-sharing + 2026-06-24 + weekly + 0.7 + + + + + + + + + + + + + + + + + https://sync.koalastuff.net/ 2026-06-23 diff --git a/website/style.css b/website/style.css index 470dfe1..c851830 100644 --- a/website/style.css +++ b/website/style.css @@ -1828,6 +1828,17 @@ footer { color: var(--text-muted); } +footer a { + color: var(--text-muted); + text-decoration: none; + transition: color 0.2s ease; +} + +footer a:hover { + color: var(--text); +} + + /* --- Animations --- */ [data-reveal] { opacity: 0; @@ -2564,12 +2575,9 @@ html:not(.lang-de) [lang="de"] { opacity: 0.85; } - .comparison-table td.check::before { - content: "KoalaSync"; - } - + .comparison-table td.check::before, .comparison-table td.cross::before { - content: "Teleparty"; + content: attr(data-label); } /* Keep the KoalaSync row subtly highlighted, like on desktop. */ @@ -2930,7 +2938,29 @@ header[id] { .status-ring.active-pulse, .hero-mockup-wrapper, .cta-group .btn { - will-change: auto; + } +} + +/* --- Alternatives Hub Styles --- */ +.guide-card { + transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.25s ease, border-color 0.25s ease !important; +} +.guide-card:hover { + transform: translateY(-4px); + background-color: rgba(255, 255, 255, 0.07) !important; + border-color: rgba(255, 255, 255, 0.22) !important; + box-shadow: 0 12px 24px -10px rgba(0, 0, 0, 0.4); +} +.guide-card .btn-primary { + transition: background-color 0.2s ease, transform 0.1s ease; +} +.guide-card .btn-primary:active { + transform: scale(0.97); +} +@media (max-width: 640px) { + .guides-grid { + grid-template-columns: 1fr !important; + gap: 1.25rem !important; } } diff --git a/website/template.html b/website/template.html index 069e921..a903049 100644 --- a/website/template.html +++ b/website/template.html @@ -783,8 +783,8 @@ {{COMP_FEAT_1_NAME}} {{COMP_FEAT_1_DESC}} - ✔ {{COMP_FEAT_1_KOALA}} - + ✔ {{COMP_FEAT_1_KOALA}} + ✘ {{COMP_FEAT_1_TELE}} [1] @@ -794,8 +794,8 @@ {{COMP_FEAT_2_NAME}} {{COMP_FEAT_2_DESC}} - ✔ {{COMP_FEAT_2_KOALA}} - + ✔ {{COMP_FEAT_2_KOALA}} + ✘ {{COMP_FEAT_2_TELE}} [2] @@ -805,8 +805,8 @@ {{COMP_FEAT_3_NAME}} {{COMP_FEAT_3_DESC}} - ✔ {{COMP_FEAT_3_KOALA}} - + ✔ {{COMP_FEAT_3_KOALA}} + ✘ {{COMP_FEAT_3_TELE}} [2] @@ -816,8 +816,8 @@ {{COMP_FEAT_4_NAME}} {{COMP_FEAT_4_DESC}} - ✔ {{COMP_FEAT_4_KOALA}} - + ✔ {{COMP_FEAT_4_KOALA}} + ✘ {{COMP_FEAT_4_TELE}} [2] @@ -827,8 +827,8 @@ {{COMP_FEAT_5_NAME}} {{COMP_FEAT_5_DESC}} - ✔ {{COMP_FEAT_5_KOALA}}[3] - + ✔ {{COMP_FEAT_5_KOALA}}[3] + ✘ {{COMP_FEAT_5_TELE}} [1] @@ -838,8 +838,8 @@ {{COMP_FEAT_6_NAME}} {{COMP_FEAT_6_DESC}} - ✔ {{COMP_FEAT_6_KOALA}} - + ✔ {{COMP_FEAT_6_KOALA}} + ✘ {{COMP_FEAT_6_TELE}} @@ -848,8 +848,8 @@ {{COMP_FEAT_7_NAME}} {{COMP_FEAT_7_DESC}} - ✔ {{COMP_FEAT_7_KOALA}} - + ✔ {{COMP_FEAT_7_KOALA}} + ✘ {{COMP_FEAT_7_TELE}} @@ -1265,6 +1265,7 @@