Files
KoalaSync/website
KoalaDev cb84709358 fix(popup): render lobby peer names as text, not markup
Peer usernames are remote-controlled and were interpolated into an
innerHTML string in updateLobbyUI. The server only truncates them to 30
chars, so a peer could inject markup into everyone else's popup: enough
to load a remote image (leaking viewer IPs) or spoof readiness badges.
Inline handlers were already blocked by the MV3 default CSP.

Build the peer items with the DOM API, matching the pattern the sibling
peer list already uses.

Add the two checks that would have caught this before upload:
- eslint no-unsanitized, which reproduces the AMO warning at lint time
- addons-linter on the built XPI in verify-release, with
  --warnings-as-errors since it exits 0 on warnings and AMO rejects them

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 05:57:38 +02:00
..
2026-07-15 04:45:45 +02:00
2026-07-11 15:48:09 +02:00

KoalaSync Website & Invitation Bridge

This directory contains the static KoalaSync website. It is both the public marketing/onboarding site and the browser-side invitation bridge for joining sync rooms.

Where You Are

  • template.html, style.css, styles/*.css, app.js, lang-init.js, and locales/*.json are source files. style.css is the local-development manifest; production concatenates the modules in the order declared by website/build.cjs.
  • build.cjs compiles the static site into website/www/.
  • website/www/ is generated output. Do not edit files there directly.
  • join.html handles room-invite links and communicates with the extension through bridge.js.
  • llms.txt gives AI tools a detailed product profile and is linked from every localized landing-page <head>.
  • alternatives/ contains comparison pages for users evaluating KoalaSync against other watch-party approaches.

Core Roles

1. Marketing & Onboarding

The site explains KoalaSync, links to browser stores, documents self-hosting, and provides localized user-facing copy in 15 languages:

en, de, fr, es, it, nl, pl, pt, pt-BR, tr, ru, ja, ko, zh, and uk.

2. Invitation Bridge (join.html)

When a user opens an invitation such as https://sync.koalastuff.net/join.html#join:roomID:pass, the page:

  • detects whether the KoalaSync extension is installed via the extension's bridge.js content script,
  • keeps room credentials inside the URL hash so they are not sent to the web server,
  • asks the extension to join the target room automatically when possible.

Architecture

The website is 100% static HTML, CSS, and JavaScript.

  • Static i18n compiler: build.cjs combines template.html with dictionaries in locales/.
  • Build-time minification: Source CSS/JS stays readable; generated output uses .min.css and .min.js.
  • Strangler CSS architecture: styles/*.css supplies page-specific production bundles; style.legacy.css is the byte-identical, unloaded reference monolith. The landing bundle preserves the legacy cascade while excluding Join- and Alternatives-only rules. Structural CSS is not activated after paint because that causes layout shifts.
  • Zero backend: The compiled site can be hosted by any static file server.
  • Zero external assets: Fonts, icons, scripts, and images must remain self-hosted.
  • Generated SEO/runtime files: version.json, robots.txt, llms.txt, clean URLs, localized pages, and minified assets are copied into www/; sitemap.xml is generated there from the current route set.

Local Development & Compilation

From the repository root:

node website/build.cjs
npx serve -l 5000 website/www

Then open:

  • http://localhost:5000/ for the default page.
  • http://localhost:5000/de/ for a localized page.
  • http://localhost:5000/join.html#join:test-room:test-pass to test the invitation bridge path.

Focused verification:

node scripts/test-website-locales.mjs
node scripts/test-website-theme.mjs
node --check website/app.js
node --check website/lang-init.js

Full verification:

npm run verify

Hosting with Caddy

Caddy is the recommended production server because it handles HTTPS and static file serving cleanly. For a complete website plus relay reverse-proxy setup, use the root Caddyfile.example.

Minimal static-site block:

sync.koalastuff.net {
    root * /var/www/koalasync/website/www
    try_files {path} {path}.html {path}/
    file_server
    encode zstd gzip

    # Themed 404 page (Caddy returns an empty 404 without this)
    handle_errors {
        @notfound expression {err.status_code} == 404
        rewrite @notfound /404.html
        file_server
    }

    @static {
        file
        path *.ico *.css *.js *.png *.svg *.webp *.avif
    }
    header @static Cache-Control "public, max-age=31536000, must-revalidate"

    header {
        Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self'; img-src 'self' data:; object-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none';"
        Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=()"
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options nosniff
        X-Frame-Options SAMEORIGIN
        Referrer-Policy strict-origin-when-cross-origin
    }
}

Do Not Break

  • Do not edit website/www/ manually; rebuild it from sources.
  • Do not add external CDNs, fonts, analytics, or third-party scripts.
  • Keep invite credentials in the URL hash, not query parameters.
  • Keep locale files synchronized with website/build.cjs and scripts/test-website-locales.mjs.
  • website/www/ is gitignored build output. Commit the source changes only; rebuild www/ locally or in CI for verification and deployment.