diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 34e8b5f..56727d6 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,7 +2,7 @@ name: 🚀 Feature Request about: Suggest a new feature or enhancement for KoalaSync title: '' -labels: enhancement +labels: feature assignees: '' --- diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e3662a9..775db90 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -37,7 +37,7 @@ Closes # - [ ] I have performed a self-review of my code - [ ] I have added/updated tests if needed - [ ] I have updated documentation if needed (`docs/`, README, etc.) -- [ ] Protocol changes: I ran `node scripts/build-extension.js` and updated relevant docs +- [ ] Protocol changes: I ran `node scripts/build-extension.cjs` and updated relevant docs - [ ] No new warnings, secrets, or hardcoded credentials introduced ### Additional Context diff --git a/.github/workflows/beta-server-image.yml b/.github/workflows/beta-server-image.yml new file mode 100644 index 0000000..25ae743 --- /dev/null +++ b/.github/workflows/beta-server-image.yml @@ -0,0 +1,75 @@ +name: Beta Server Image + +# Publishes the relay server as a Docker image under NON-production tags so a +# feature branch can be deployed to a staging/backup server and used as a custom +# server, without ever touching the ':latest' tag the official relay tracks. +# +# Tags produced (on ghcr.io//): +# - beta moving channel pointer to the newest build +# - e.g. feature-host-control-mode +# - sha- immutable, pin to an exact build +# - only on manual run, e.g. hostcontrol01 +# Never ':latest' (flavor: latest=false). +# +# Remove this workflow once the feature is merged & released the normal way. + +on: + push: + branches: + - feature/host-control-mode + workflow_dispatch: + inputs: + tag: + description: 'Extra immutable tag for this build (e.g. hostcontrol01). Optional.' + required: false + default: '' + +concurrency: + group: beta-image-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-beta-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout code + uses: actions/checkout@v7 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v6 + with: + images: ghcr.io/${{ github.repository }} + # Never publish ':latest' from a beta build. + flavor: | + latest=false + tags: | + type=raw,value=beta + type=ref,event=branch + type=sha,prefix=sha- + type=raw,value=${{ github.event.inputs.tag }},enable=${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag != '' }} + + - name: Build and push Docker image + uses: docker/build-push-action@v7 + with: + context: . + file: server/Dockerfile + push: true + platforms: linux/amd64,linux/arm64 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..14bd8e9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,46 @@ +name: CI + +# Runs the full verification suite (lint, unit/integration tests, production +# audits, extension + website build) on every push to main and every PR, so a +# regression can never reach main or a release tag unchecked. +on: + push: + branches: [main] + pull_request: + +permissions: + contents: read + +# Cancel superseded runs on the same ref to save CI minutes. Unlike the release +# workflow, an interrupted CI run has no side effects. +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + verify: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v7 + + - name: Set up Node.js + uses: actions/setup-node@v6 + with: + node-version: '24' + cache: 'npm' + cache-dependency-path: | + package-lock.json + server/package-lock.json + + - name: Install root dependencies + run: npm ci + + # The server test suite (test-server-ws/routes/ops) imports express, + # socket.io, and dotenv from server/node_modules, so install them too. + - name: Install server dependencies + run: npm ci + working-directory: server + + - name: Run verification suite + run: npm run verify diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dd39159..5da471e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,23 +5,29 @@ on: tags: - 'v*' +# A release run must never be interrupted (it commits back to main and publishes +# artifacts). Only dedupe accidental re-pushes of the same tag. +concurrency: + group: release-${{ github.ref_name }} + cancel-in-progress: false + jobs: release-server: runs-on: ubuntu-latest permissions: - contents: write + contents: read packages: write id-token: write attestations: write steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Log in to GitHub Container Registry - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ github.actor }} @@ -29,7 +35,7 @@ jobs: - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: ghcr.io/${{ github.repository }} tags: | @@ -38,7 +44,7 @@ jobs: - name: Build and push Docker image id: build - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v7 with: context: . file: server/Dockerfile @@ -46,6 +52,9 @@ jobs: platforms: linux/amd64,linux/arm64 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + # Reuse layers across releases to speed up the multi-arch build. + cache-from: type=gha + cache-to: type=gha,mode=max - name: Generate artifact attestation uses: actions/attest@v4 @@ -62,7 +71,13 @@ jobs: attestations: write steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v7 + + - name: Set up Node.js + uses: actions/setup-node@v6 + with: + node-version: '24' + cache: 'npm' - name: Extract version from tag id: version @@ -79,7 +94,7 @@ jobs: echo " ✓ manifest.base.json -> $VERSION" # 2. shared/constants.js — APP_VERSION - sed -i "s/export const APP_VERSION = '.*'/export const APP_VERSION = '$VERSION'/" shared/constants.js + sed -i "s/export const APP_VERSION = [\"'].*[\"']/export const APP_VERSION = \"$VERSION\"/" shared/constants.js echo " ✓ shared/constants.js -> $VERSION" # 3. package.json @@ -94,8 +109,9 @@ jobs: sed -i "s/\"softwareVersion\": \".*\"/\"softwareVersion\": \"$VERSION\"/" website/template.html echo " ✓ website/template.html -> softwareVersion $VERSION" - # 6. README.md — version badge - sed -i "s/v[0-9]\+\.[0-9]\+\.[0-9]\+/v$VERSION/g" README.md + # 6. README.md — version badge & banner + sed -i "s|Release-v[0-9]\+\.[0-9]\+\.[0-9]\+-blue|Release-v$VERSION-blue|g" README.md + sed -i "s/New v[0-9]\+\.[0-9]\+\.[0-9]\+ Release/New v$VERSION Release/g" README.md echo " ✓ README.md -> v$VERSION" # 7. website/sitemap.xml — lastmod dates @@ -116,7 +132,7 @@ jobs: - name: Build Extensions run: | - npm install + npm ci npm run build:extension - name: Generate artifact attestation for extensions @@ -128,14 +144,14 @@ jobs: run: node website/build.cjs - name: Upload Website Artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: website-www path: website/www/ if-no-files-found: error - name: Create GitHub Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v3 with: files: | dist/koalasync-chrome.zip diff --git a/.gitignore b/.gitignore index 65830fc..c0b6b82 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ Thumbs.db # IDEs .vscode/ .idea/ +.claude/ *.swp *.swo diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 141859e..b9ddb8d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,7 +31,7 @@ Please note that by participating in this project, you agree to abide by our [Co git clone https://github.com/Shik3i/KoalaSync.git cd KoalaSync npm install -node scripts/build-extension.js +node scripts/build-extension.cjs ``` --- @@ -62,7 +62,7 @@ node scripts/build-extension.js ### Website ```bash -node website/build.js # Compile static site → www/ +node website/build.cjs # Compile static site → www/ python3 -m http.server 8080 -d website/www # Serve locally ``` @@ -77,7 +77,7 @@ KoalaSync uses a **single source of truth** for all protocol constants in `share > [!IMPORTANT] > After modifying `shared/constants.js`, you **must** run the build script to sync changes to the extension: > ```bash -> node scripts/build-extension.js +> node scripts/build-extension.cjs > ``` > This automatically injects constants into `content.js` and regenerates browser bundles in `dist/`. @@ -109,7 +109,7 @@ If you are new to open-source contributions, follow these steps to propose your 3. **Create a Branch**: `git checkout -b my-new-feature` (e.g. `feature/dark-mode` or `fix/translation-de`) 4. **Make your Changes**: Edit the files, then verify them locally. - *Extension/Server changes*: Test on Chrome/Firefox and check `npm run lint`. - - *Website/Translation changes*: Run `node website/build.js` and check the output in `www/`. + - *Website/Translation changes*: Run `node website/build.cjs` and check the output in `www/`. 5. **Commit and Push**: `git commit -m "Add my feature"` and `git push origin my-new-feature` 6. **Open a Pull Request (PR)**: Go to the original KoalaSync repository on GitHub and click "New Pull Request". @@ -156,9 +156,9 @@ KoalaSync supports multiple languages. To add or improve translations: 1. Read the **[Translation Guide](docs/TRANSLATION.md)** first. It explains how our localization system works. 2. Edit the `.json` files in `website/locales/` (for the website) and `extension/locales/` (for the extension). 3. Test your translations locally by running: - - `node scripts/test-locales.js` (for extension) + - `node scripts/test-locales.cjs` (for extension) - `node scripts/test-website-locales.mjs` (for website) - - `node website/build.js` (to build the site) + - `node website/build.cjs` (to build the site) 4. Follow the **Open Source Workflow** above (Fork -> Branch -> Edit -> PR) to submit your translations. --- diff --git a/LANDINGPAGE_UI_OVERHAUL_PLAN.md b/LANDINGPAGE_UI_OVERHAUL_PLAN.md new file mode 100644 index 0000000..e6e8dea --- /dev/null +++ b/LANDINGPAGE_UI_OVERHAUL_PLAN.md @@ -0,0 +1,153 @@ +> **TEMPORÄR:** Diese Datei dient nur der gemeinsamen Planung des Landingpage-UI-Overhauls +> auf dem Branch `landingpage-ui-overhaul`. Sie ist **kein** Teil des finalen Features und +> **muss vor dem Öffnen des PRs wieder gelöscht werden**. + +# Landingpage UI Overhaul — Hero Mockup + +## Ausgangslage +Die Landingpage (`website/template.html`, `website/style.css`, `website/app.js`, kompiliert +via `website/build.cjs` nach `website/www/`) ist bereits sehr gut, soll aber **statisch und +backend-frei** bleiben. Einziger Fokus dieses Overhauls: das rechte Hero-Mockup +(`.hero-mockup-wrapper` / `.extension-mockup`, `template.html:304-579`). + +**Heutiger Zustand:** Ein 1:1-Nachbau des Extension-Popups mit 4 Tabs (Room / Sync / +Settings / Status). Tab-Wechsel nur per Klick (`app.js:391-407`), keine Animationen, kein +Auto-Play, kein Bezug zu den eigentlichen Video-Tabs, die synchronisiert werden. + +## Ziel +Ein dynamischeres, platzoptimiertes Hero-Visual, das das Kernversprechen von KoalaSync +("zwei Browser-Tabs synchron abspielen") direkt zeigt — mit echten Animationen, einem +automatischen Durchlauf beim ersten Sichtbarwerden und voller manueller Bedienbarkeit +danach. Auf Mobile (Bildschirmgröße) bleibt exakt das heutige, statische Popup-Mockup +erhalten — kein neues Mobile-Design nötig, kein zusätzlicher Wartungsaufwand dort. + +## Getroffene Entscheidungen (aus Rückfrage-Runde) + +1. **Layout:** Gestapelt/Layered — zwei Browser-Tab-Karten leicht versetzt im Hintergrund + (Tiefeneffekt via `transform`/`box-shadow`), Extension-Popup öffnet sich als Overlay + davor/darüber. +2. **Tab-Inhalt:** Abstraktes Video-Mock — Gradient-Placeholder als "Video", Play-Button, + Fortschrittsbalken, Timestamp. Kein echtes Videomaterial, keine Marken/Logos, im + bestehenden minimalistischen `mock-*`-Stil. +3. **Auto-Play-Verhalten:** Einmaliger Durchlauf beim Sichtbarwerden (IntersectionObserver), + danach reiner manueller Modus. Kein Endlos-Loop im Hintergrund. +4. **Popup-Umfang:** Alle 4 Tabs (Room/Sync/Settings/Status) bleiben inhaltlich unverändert + — nur in die neue Animations-/Overlay-Logik eingebettet, kein Content-Kahlschlag. + +## Vorgeschlagenes Storyboard (einmaliger Auto-Durchlauf) + +1. **Ausgangszustand:** Zwei Tab-Karten ("Tab A" / "Tab B") sichtbar, Video-Mocks pausiert, + Fortschrittsbalken bei 0. Popup geschlossen, nur ein kleiner Launcher-Button sichtbar. +2. Popup öffnet sich (scale/slide-in) vor den Tab-Karten. +3. Simulierter Klick auf "Play" im Sync-Tab → beide Tab-Karten starten gleichzeitig + (Fortschrittsbalken laufen synchron), begleitet von einem kurzen "Sync-Pulse" + (Glow/Connection-Line) zwischen den beiden Karten. +4. Nach ein paar Sekunden: simulierter Klick auf "Pause" → beide Tabs pausieren synchron. +5. Popup schließt sich, Endzustand bleibt stehen (beide Tabs pausiert, synchron, + "Synced"-Indikator dezent sichtbar) — kein Reset auf Ausgangszustand. +6. **Danach/parallel volle manuelle Steuerung:** + - Klick auf eine Tab-Karte togglet deren eigenes Play/Pause *unabhängig* — spielt eine + Karte allein, laufen die Fortschrittsbalken bewusst auseinander ("out of sync"), um den + Schmerzpunkt zu illustrieren, den KoalaSync löst. + - Klick auf Play/Pause im Popup synchronisiert immer beide Tabs. + - Popup lässt sich jederzeit manuell öffnen/schließen, Tabs (Room/Sync/Settings/Status) + bleiben wie heute klickbar. + - Jede manuelle Interaktion während des Auto-Durchlaufs bricht diesen sofort ab und + übergibt die volle Kontrolle. + +## Technischer Ansatz (Vorschlag) + +- **Keine neuen Dependencies** — reines Vanilla JS + CSS, passend zur "Zero-Dependency"- + Philosophie des Projekts (siehe `website/README.md`). +- **Eine "Director"-Funktion** in `app.js`, die exakt dieselben Click-Handler wie die + manuelle Bedienung aufruft (kein doppelter Code-Pfad zwischen Auto- und Manual-Modus). +- **IntersectionObserver** triggert den einmaligen Durchlauf beim ersten Sichtbarwerden. +- **`prefers-reduced-motion`**: Auto-Durchlauf und Cursor-Ripple-Indikatoren werden + übersprungen, Endzustand wird direkt gesetzt (Pattern existiert bereits in + `style.css:2915-2939`). +- **Kein DOM-Duplikat für Mobile:** Das Popup-Markup bleibt eine einzige Quelle. Der neue + `.hero-mockup-dynamic`-Wrapper enthält die Tab-Karten + das Popup; unterhalb des + bestehenden Breakpoints (768px, siehe `style.css:1913`) werden die Tab-Karten und + Animationen per CSS ausgeblendet, das Popup fällt optisch auf das heutige, statische + Erscheinungsbild zurück, JS initialisiert dort keine Animationen. Vermeidet doppelte + i18n-Pflege der ~270 Zeilen Popup-Markup. +- **i18n-Vorsicht:** 15 Locale-Dateien unter `website/locales/*.json`. Neue sichtbare Texte + (Tab-Labels etc.) nach Möglichkeit vermeiden oder wie bestehende Mock-Inhalte + (z. B. "CoolUsername", "Stranger Things - S4E1") als nicht-lokalisierte Platzhalter + behandeln, um Übersetzungsaufwand in 15 Sprachen zu vermeiden. Neue `{{MOCK_XX}}`-Keys nur + falls wirklich nötig, dann mit Übersetzung in allen 15 Dateien. +- **Build:** Änderungen nur in den Source-Dateien (`template.html`, `style.css`, `app.js`), + niemals in `website/www/**` (generiert via `website/build.cjs`). + +## Detailentscheidungen (bei der Umsetzung getroffen) + +- [x] Breakpoint Mobile-Fallback: bestehende 768px übernommen (`matchMedia('(min-width: 769px)')` + im JS, `@media (max-width: 768px)` im CSS). +- [x] Auto-Durchlauf-Timing: Start ~1,4s nach 45% Sichtbarkeit (IntersectionObserver), dann + Cursor → Launcher → Sync-Tab → Play (läuft ~3s synchron) → Pause → Popup schließt. + Gesamtdauer ca. 10s. +- [x] Tab-Karten haben User-Badges passend zur Peer-Liste im Popup: "CoolUsername" (indigo) + und "KoalaPC" (grün), gleicher Episodentitel "Stranger Things - S4E1". +- [x] Echter animierter Ghost-Mauszeiger (SVG-Cursor mit Klick-Ripple), kein reiner + Ripple-Indikator — verkauft den Durchlauf deutlich besser. +- [x] Keine externe Referenz — eigener Stil, konsistent mit dem bestehenden `mock-*`-Design. +- [x] ~~Drift-Konzept~~ **Verworfen nach Feedback** — es stellte die Extension falsch dar + (als bräuchte sie das offene Popup). Ersetzt durch das **Broadcast-Modell**: Play/ + Pause/Seek auf *irgendeinem* Video wird automatisch zum Peer gespiegelt (Puls wandert + über die Verbindungslinie, Peer folgt ~260ms später, Engine gleicht die Zeit an). Der + Status-Chip bleibt grün "In sync" und blitzt bei jedem Broadcast kurz das Event auf + ("▶ CoolUsername", "❚❚ KoalaPC", "» …" für Seek). Das Popup ist nur die Fernbedienung + obendrauf, nie Voraussetzung. +- [x] Rework 2 nach Feedback: Kein reservierter Popup-Platz mehr; KoalaSync-Icon als + Extension-Button in der Toolbar des vorderen Fensters; Fortschrittsbalken klickbar + (Seek wird mitgesynct, Scrub-Thumb bei Hover). +- [x] Rework 3 nach Feedback: Fenster-Kaskade statt starker Überlappung — das **rechte** + Fenster (CoolUsername, mit dem Toolbar-Icon oben rechts) liegt im Vordergrund, das + linke (KoalaPC) versetzt dahinter unten links. Das Popup öffnet **rechts außen** + (right: 0, verankert unterm Icon), die beiden Tabs weichen dabei animiert nach links + aus und bleiben sichtbar. Verbindungslinie komplett entfernt (Sync-Feedback = Puls- + Ring auf beiden Karten + Event-Chip). Peer-Latenz von 260ms auf 90ms gesenkt — wirkt + quasi instant. +- [x] Rework 4 nach Feedback: **Story-Walkthrough in 5 Akten** beim ersten Sichtbarwerden — + (1) Extension über das Toolbar-Icon öffnen, (2) "Raum erstellen" (eigener Pre-Room- + Screen im Popup, `#demo-room-empty`), (3) Invite-Link fliegt animiert vom Popup zum + zweiten Browserfenster (Toast "Raum beigetreten", KoalaPC erscheint in der Peer-Liste, + "IN SYNC"-Chip blendet erst jetzt ein), (4) beide wählen den Video-Tab (Select-Flash im + Popup + Toast am zweiten Fenster), (5) Play für alle → Popup schließt → Pause vom + anderen Tab, Seek mit Nachziehen, Play. Danach voll manuell. Jede Interaktion während + der Story bricht ab und springt via idempotentem `finishDemo()` sofort in den End- + zustand (Raum verbunden, Chip an, Hint an; Popup schließt bei Klicks außerhalb); + der Nutzer-Klick wirkt anschließend normal. 4 neue Locale-Keys (DEMO_NO_ROOM, + DEMO_CREATE_ROOM, DEMO_JOINED, DEMO_TAB_SELECTED) in allen 15 Sprachen. +- [x] Abspiel-Animation: abstrakter **Strichfigur-Kurzfilm** pro Video (SVG: Hügel- + Silhouetten, laufende Figur mit schwingenden Armen/Beinen, hüpfender Ball) — läuft + nur bei `playing`, Pause friert beide Filme im selben Frame ein + (`animation-play-state`), was die Synchronität sofort sichtbar macht. + +## Umsetzungsstatus + +- [x] `website/template.html`: Hero-Mockup in `.hero-demo-scene` eingebettet (Chip, 2 Tab- + Karten, Verbindungslinie, Launcher, Ghost-Cursor, Hint); Popup-Inhalt unverändert, + nur IDs für Play/Pause/Force-Sync ergänzt. +- [x] `website/style.css`: Demo-Styles mit Container-Queries (cqw + px-Fallbacks), + Mobile-Fallback, `prefers-reduced-motion`-Support. +- [x] `website/app.js`: `initHeroDemo()` — Playback-Uhr (rAF, 8x Zeitraffer), Broadcast- + Logik (Play/Pause/Seek → Peer folgt), manuelle Steuerung, einmaliger Auto-Durchlauf + (Play in Tab A → Seek in Tab B → Pause in Tab B → Popup öffnen/Play/schließen); jede + Interaktion bricht den Durchlauf sofort ab. Auto- und Manuell-Modus nutzen dieselben + Click-Handler. Launcher-Klicks sind vom Karten-Play/Pause entkoppelt (closest-Guard). +- [x] `website/locales/*.json`: 3 neue Keys (`DEMO_SYNC`, `DEMO_DRIFT`, `DEMO_HINT`) in + allen 15 Sprachen. +- [x] `eslint.config.mjs`: `requestAnimationFrame`/`cancelAnimationFrame` zu den Globals. +- [x] Verifiziert im Browser-Preview: Auto-Durchlauf, Drift-Szenario, Chip-Rettungsweg, + Re-Sync, Mobile-Fallback (statisches Popup wie vorher), keine Konsolenfehler, + Lint sauber, Build ohne offene Platzhalter. +- [ ] `.claude/launch.json` zeigt auf einen Session-Scratchpad-Server — vor dem PR prüfen, + ob die Datei ins Repo soll (ggf. löschen oder auf dauerhaften Pfad umstellen). + +## Scope / Nicht-Ziele + +- Kein Backend, keine echten Videos/Assets, keine neuen npm-Dependencies. +- Kein Umbau des restlichen Landingpage-Contents (Features, Compat-Section, Footer etc.) — + ausschließlich das Hero-Mockup. +- Mobile-Ansicht bekommt **kein** neues Design, bleibt 1:1 der heutige Stand. diff --git a/README.md b/README.md index ac1275f..2bc692f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@

Release Status - GitHub release + GitHub release License Firefox Add-on Chrome Extension @@ -14,7 +14,7 @@

KoalaSync is a lightweight Browser Extension and Relay Server for synchronized video playback on almost any website with a video element—YouTube, Twitch, Netflix, Emby, Jellyfin, and beyond. Built with a focus on Data Sovereignty and Performance.

-

New v2.4.0 Release! — See what's changed

+

New v2.5.3 Release! — See what's changed

### 🌟 Why KoalaSync? @@ -59,7 +59,7 @@ The easiest and safest way to install KoalaSync is directly through the official ### 🌐 Localization & Translations Both the official KoalaSync website and the **v2.0 Browser Extension** feature full dynamic localization: -- **Available Languages**: Support is included for 13 languages: English (`en`), German (`de`), French (`fr`), Spanish (`es`), Portuguese (Brazil) (`pt-BR`), Russian (`ru`), Italian (`it`), Polish (`pl`), Turkish (`tr`), Dutch (`nl`), Japanese (`ja`), Korean (`ko`), and European Portuguese (`pt`). +- **Available Languages**: Support is included for 15 languages: English (`en`), German (`de`), French (`fr`), Spanish (`es`), Portuguese (Brazil) (`pt-BR`), Russian (`ru`), Italian (`it`), Polish (`pl`), Turkish (`tr`), Dutch (`nl`), Japanese (`ja`), Korean (`ko`), Chinese (Simplified) (`zh`), Ukrainian (`uk`), and European Portuguese (`pt`). - **Real-Time Extension Localization**: Inside the extension Settings panel, users can swap languages instantly. The entire interface, notifications, Empty States, and onboarding guides re-translate dynamically in real-time. - **Contributing**: We welcome community translations for both the website and the extension! Please refer directly to the [TRANSLATION.md](docs/TRANSLATION.md) guide for step-by-step instructions on how to audit, refine, or add new languages. @@ -103,7 +103,7 @@ To connect your extension to a self-hosted server, open the popup → **Room** t To verify your relay is reachable from outside, visit `https://your-domain.com` in a browser — it should return `{"status":"online","service":"KoalaSync Relay"}`. -#### Supply Chain Security (v2.4.0+) +#### Supply Chain Security (v2.2.2+) All official release artifacts (Docker images and extension binaries) are published with signed [artifact attestations](https://docs.github.com/en/actions/how-tos/secure-your-work/use-artifact-attestations) to prove they were built from this repository's source code. @@ -131,6 +131,7 @@ gh attestation verify dist/koalasync-chrome.zip \ - **[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)**: Our community standards and expectations. - **[HOW_IT_WORKS.md](docs/HOW_IT_WORKS.md)**: Step-by-step walkthrough of the complete user flow. - **[ARCHITECTURE.md](docs/ARCHITECTURE.md)**: Deep-dive into the two-phase sync and heartbeat logic. +- **[PROTOCOL.md](docs/PROTOCOL.md)**: WebSocket protocol specification and event reference. - **[ROADMAP.md](docs/ROADMAP.md)**: Planned features, backlog, and rejected ideas. - **[SECURITY.md](SECURITY.md)**: Disclosure policy and security practices. - **[Caddyfile.example](examples/Caddyfile.example)**: Production Caddy configuration for website and relay. @@ -138,7 +139,7 @@ gh attestation verify dist/koalasync-chrome.zip \ ---
- Ko-Fi + Support KoalaSync GitGem Badge Built with ❤️ by Shik3i. KoalaSync is Open Source under the MIT License. diff --git a/SECURITY.md b/SECURITY.md index 4db6145..2f0ef79 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -82,6 +82,12 @@ KoalaSync's security is grounded in its architecture: If you find a way to bypass any of these protections, we want to know about it. +> [!NOTE] +> Some frequently-reported "issues" are **intentional and out of scope** for our +> threat model (ephemeral, account-less rooms of invited participants) — e.g. an +> unauthenticated `peerId` or non-constant-time room-password compare. Before +> reporting, please read **[`docs/KNOWN_LIMITATIONS.md`](docs/KNOWN_LIMITATIONS.md)**. + --- ## Responsible Disclosure diff --git a/assets/MarketingCopy.md b/assets/MarketingCopy.md new file mode 100644 index 0000000..b7c2d5d --- /dev/null +++ b/assets/MarketingCopy.md @@ -0,0 +1,66 @@ +# KoalaSync — Marketing Copy Kit + +Ready-to-paste copy for product listings, launch pages, directory submissions, and anywhere else you keep re-typing the same pitch. Three lengths, one consistent message. Pick the one that fits the field limit. + +--- + +## 1. One-Sentence Pitch + +> KoalaSync is a privacy-first browser extension that synchronizes video playback across almost any website so you can watch with friends in real time — no accounts, no tracking, and your video never passes through anyone's server but the original site's. + +**Shorter alternative** (for tight tagline fields): + +> Private, universal watch parties on any website — no accounts, no tracking, no media proxying. + +--- + +## 2. Three-Sentence Overview + +> KoalaSync is a lightweight browser extension that keeps you and your friends perfectly in sync on YouTube, Netflix, Twitch, Prime Video, Jellyfin, Emby, and almost any other site with an HTML5 video player — press play once and everyone stays together. It's built privacy-first: no accounts, no telemetry, and the official relay server runs entirely in volatile RAM with zero persistence, so nothing about your sessions is ever stored. Open source under the MIT license and fully self-hostable with a single Docker command, KoalaSync is a transparent watch-party tool that works everywhere and respects your data sovereignty. + +--- + +## 3. Full Description + +### Watch together — on any site, on your terms. + +Counting down "3, 2, 1, play" over voice chat doesn't scale past two people. KoalaSync fixes that with a tiny browser extension that synchronizes play, pause, and seeking across everyone in the room, on almost any website with a `
@@ -402,14 +403,18 @@
Manual Connect / Advanced
-
- -
- - + +
+
+ +
+ + +
+
-
+
@@ -450,6 +455,22 @@
+ +
@@ -530,6 +551,25 @@
+
+ Privacy Settings +
+ + +
+
+ + +
+
+
@@ -600,7 +642,7 @@
Enjoying KoalaSync? Leave a review!
★ Rate us · - ☕ Buy me a coffee + Support KoalaSync · v0.0.0
@@ -611,7 +653,10 @@
- Disconnected + + Disconnected + + @@ -641,13 +686,25 @@
Enjoying KoalaSync? Leave a review!
★ Rate us · - ☕ Buy me a coffee + Support KoalaSync · v0.0.0
+
+ +
+ + +
+ +
+ Build: __BUILD_TIMESTAMP__ +
+
+ @@ -659,14 +716,14 @@ @@ -768,8 +939,8 @@ {{COMP_FEAT_1_NAME}} {{COMP_FEAT_1_DESC}} - ✔ {{COMP_FEAT_1_KOALA}} - + ✔ {{COMP_FEAT_1_KOALA}} + ✘ {{COMP_FEAT_1_TELE}} [1] @@ -779,8 +950,8 @@ {{COMP_FEAT_2_NAME}} {{COMP_FEAT_2_DESC}} - ✔ {{COMP_FEAT_2_KOALA}} - + ✔ {{COMP_FEAT_2_KOALA}} + ✘ {{COMP_FEAT_2_TELE}} [2] @@ -790,8 +961,8 @@ {{COMP_FEAT_3_NAME}} {{COMP_FEAT_3_DESC}} - ✔ {{COMP_FEAT_3_KOALA}} - + ✔ {{COMP_FEAT_3_KOALA}} + ✘ {{COMP_FEAT_3_TELE}} [2] @@ -801,8 +972,8 @@ {{COMP_FEAT_4_NAME}} {{COMP_FEAT_4_DESC}} - ✔ {{COMP_FEAT_4_KOALA}} - + ✔ {{COMP_FEAT_4_KOALA}} + ✘ {{COMP_FEAT_4_TELE}} [2] @@ -812,8 +983,8 @@ {{COMP_FEAT_5_NAME}} {{COMP_FEAT_5_DESC}} - ✔ {{COMP_FEAT_5_KOALA}}[3] - + ✔ {{COMP_FEAT_5_KOALA}}[3] + ✘ {{COMP_FEAT_5_TELE}} [1] @@ -823,8 +994,8 @@ {{COMP_FEAT_6_NAME}} {{COMP_FEAT_6_DESC}} - ✔ {{COMP_FEAT_6_KOALA}} - + ✔ {{COMP_FEAT_6_KOALA}} + ✘ {{COMP_FEAT_6_TELE}} @@ -833,8 +1004,8 @@ {{COMP_FEAT_7_NAME}} {{COMP_FEAT_7_DESC}} - ✔ {{COMP_FEAT_7_KOALA}} - + ✔ {{COMP_FEAT_7_KOALA}} + ✘ {{COMP_FEAT_7_TELE}} @@ -877,73 +1048,6 @@

{{STEP_1_DESC}}

-
-
-
-
- - - -
-
- https://sync.koalastuff.net -
-
-
- KoalaSync Extension -
-
-
-
-
-
- -
-
KoalaSync
-
- {{STEP_1_ILLUS_DESC}} -
-
-
-
-
- Chrome Logo - {{STEP_1_ILLUS_DL_CHROME}} -
-
- Firefox Logo - {{STEP_1_ILLUS_DL_FIREFOX}} -
-
-
- - -
- - - -
-
-
-
- -
-
- -

{{STEP_2_TITLE}}

-

{{STEP_2_DESC}}

-
-
@@ -983,6 +1087,51 @@
+
+
+ +

{{STEP_2_TITLE}}

+

{{STEP_2_DESC}}

+
+ +
+
+
+
+ KoalaSync Logo + KoalaSync +
+
{{VERSION}}
+
+
+
+ {{STEP_2_ILLUS_ROOM}} +
+
+ {{STEP_2_ILLUS_SYNC}} +
+
+ {{STEP_2_ILLUS_SETTINGS}} +
+
+
+ + +
+
+
+
@@ -992,15 +1141,38 @@
- +
- 🐨 KoalaPC + 🐱 ChillCat PLAYING
-
+
@@ -1022,15 +1194,38 @@
- +
- 💻 LaptopKoala + 🐶 HappyDog PLAYING
-
+
@@ -1182,6 +1377,10 @@ {{FAQ_Q1}}

{{FAQ_A1}}

+
+ {{FAQ_Q_VIDEO_ACCESS}} +

{{FAQ_A_VIDEO_ACCESS}}

+
{{FAQ_Q2}}

{{FAQ_A2}}

@@ -1250,9 +1449,10 @@