Documentation Rewrites: - AI_INIT.md: fix duplicate section numbers, add file responsibility map, fix stale manual mirror instruction, add room ID constraint - PRIVACY.md: add TL;DR statement, data retention table, explicit <all_urls> justification, self-hosted instance disclaimer - CONTRIBUTING.md: add local testing guide, version warning, room ID constraint, bug report requirements - shared/README.md: complete event table (all 15 events), fix stale manifest.json reference - docs/SYNC_GUIDE.md: Chrome→Browser, add README.md to sync list, drop stale RC5 reference - server/README.md: sync env defaults with .env.example (1000/50) New Documentation: - docs/HOW_IT_WORKS.md: 10-step walkthrough covering room creation, invitation bridge flow, synchronized playback, force sync protocol, heartbeat system, and episode auto-sync. Includes exact data payloads. Infrastructure Cleanup: - docker-compose.yml: remove deprecated version key - .dockerignore: remove dead .bat/.sh patterns - README.md: add self-hosting extension config tip, link HOW_IT_WORKS
8.6 KiB
KoalaSync AI Onboarding (AI_INIT.md)
Welcome to the KoalaSync project. This file is the primary entry point for any developer or AI agent working on this codebase. It defines the architecture, non-negotiables, and workflows required to maintain the stability and security of the system.
Important
Privacy & Data Sovereignty: KoalaSync follows a strict Zero-External-Requests Policy: The extension and website must not make requests to any third-party domains (Google Fonts, CDNs, etc.). All assets (fonts, icons, scripts) must be self-hosted or use system defaults.
- Font Stack: Use a modern system font stack (e.g., -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif) to maintain a premium look without external dependencies. Prohibit the use of
@importor<link>for external font services.
1. Project Overview
KoalaSync is a specialized tool for synchronized video playback across multiple remote peers. It supports YouTube, Twitch, and native HTML5 video elements.
- Users: Friends or groups wanting to watch synchronized content together.
- Workflow: A user creates a room, shares an invitation link, and all peers in that room are synchronized via a Node.js relay server.
- Identity: Users are identified by a unique hex
peerIdcombined with a customizableusername.
2. Repository Structure
extension/: Browser Extension (Chrome & Firefox, Manifest V3). Contains background service worker, content scripts, and popup UI.server/: Node.js Relay Server using Socket.IO (WebSocket-only).website/: Landing Page & Invitation Bridge (Marketing, Tutorials, and Downloads).shared/: Single Source of Truth for protocol constants and event names.scripts/: Development utilities (e.g.,build-extension.js).docker-compose.yml: Root-level orchestration for the relay server.
Important
Single Source of Truth:
shared/constants.jsandshared/blacklist.jsare the master files. They must be synchronized to theextension/shared/directory usingnode scripts/build-extension.js.
- Extension Modules (
background.js,popup.js) import directly from./shared/constants.js.- Content Scripts (
content.js) use a marker-injected synchronous copy of the constants. The build script automatically replaces the marked blocks — no manual mirroring needed.
3. Mandatory Reading
Before touching any code, you MUST read the following documents in order:
- docs/ARCHITECTURE.md – Detailed communication flows, Dual Heartbeat, and two-phase sync protocol.
- extension/README.md – Extension components, tab structure, and loading process.
- docs/SYNC_GUIDE.md – Protocol constants and synchronization requirements.
4. The "Vanilla JS Mirror" Pattern
To avoid boot-time race conditions in Manifest V3 without a bundler, the following architectural trade-off is enforced:
- Synchronous Execution:
content.jsMUST execute synchronously to catch early media events. - Automated Injection: The build script (
node scripts/build-extension.js) automatically injectsEVENTSandHEARTBEAT_INTERVALintocontent.jsusing marker-based replacement (seescripts/README.mdfor marker details). - Maintenance: After modifying
shared/constants.js, simply run the build script. No manual mirroring is required.
5. File Responsibility Map
| File | Responsibility |
|---|---|
background.js |
WebSocket client, state orchestrator, event router, session persistence |
content.js |
Video element detection, media control, event origin detection (loop prevention) |
popup.js |
UI rendering, user input handling, peer display, invitation link generation |
bridge.js |
Landing page ↔ extension communication for invitation join flow |
server/index.js |
Room management, message relay, rate limiting, authentication, peer lifecycle |
6. Design Guidelines
The popup UI follows a strict design system. Do not modify these variables or the layout structure without explicit approval.
- Font: System font stack. MANDATORY: No external CDNs or Google Fonts to ensure 100% privacy.
- Popup Width: Fixed at
320px. - Tab Structure: Must maintain the Room, Sync, Settings, and Dev tabs.
- CSS Variables:
Variable Value Purpose --bg#0f172aMain background --card#1e293bForm and info cards --accent#6366f1Primary actions and branding --success#22c55eSuccess states / Online dot --error#ef4444Errors / Offline dot
7. Non-Negotiables (Core Logic)
The following features are critical and must not be removed or fundamentally altered:
- Two-Phase Force Sync: The
Prepare→ACK→Executeflow ensures all peers are buffered before playback resumes. - Episode Auto-Sync: Ensures series binges stay perfectly synced. A lobby initiates during title transitions, freezing peers until everyone is ready.
- Dual Heartbeat:
- Background Heartbeat (30s): Ensures session persistence even without a video element.
- Content Heartbeat (15s): Transmits current video metadata (time, title).
- Dead Peer Pruning: Server "Reaper" disconnects peers after 5 minutes of total silence (no heartbeats or events).
- Deduplication: Server kills old sockets if a user re-joins with the same
peerIdto prevent ghosts. - Platform Specifics: Specialized click-logic for YouTube (
.ytp-play-button) and Twitch. - pollSeekReady(): Polling mechanism that checks
video.readyStatebefore acknowledging sync. - SW Keep-alive: Use of
chrome.alarmsto prevent the Manifest V3 Service Worker from suspending. - Diagnostics: The "Dev" tab provides real-time access to the underlying
<video>state for troubleshooting. - Persistence:
peerIdandusernamemust be stored to remain stable across sessions. - Room ID Format: Room IDs are restricted to
[a-zA-Z0-9-]only (alphanumeric + hyphens). This is enforced server-side.
8. Technical Constraints
- No Bundler: The extension uses plain ES Modules. Do not introduce build steps or npm packages into the
extension/folder. - Manual Protocol:
background.jsimplements a subset of the Socket.IO wire protocol natively. - Server Transport: Restricted to
websocketonly. Polling is disabled. - Docker Context: The Docker build must run from the Repo Root.
- Manifest Settings:
run_atmust remaindocument_idle, andall_framesmust remainfalse.
9. Security & Deployment
- Tokens: Security tokens are intentionally managed via
shared/constants.jsand server.env. - Environment:
.envis excluded via.gitignore. Only.env.exampleshould be committed. - Revocation:
MIN_VERSIONcheck on the server is used to deprecate old extension versions. - Invitation Links: Correctly propagate server URLs, Room IDs, and Passwords via the URL hash to the bridge.
10. Common Workflows
Releasing a New Version (CRITICAL WORKFLOW FOR AI AGENTS)
Caution
AI AGENTS MUST FOLLOW THIS EXACT SEQUENCE WHEN RELEASING A NEW VERSION OR TAGGING. The CI pipeline automatically injects the version from the git tag into
manifest.base.json,shared/constants.js, andpackage.json. You do NOT need to manually bump version numbers.
- Commit all code changes and push to
main. - Create and push a new tag. MANDATORY: Tags MUST start with a
v(e.g.,v1.4.0). The GitHub Actions release workflow is strictly configured to ignore any tags without thevprefix. - The CI will extract the version from the tag (e.g.,
v1.4.0→1.4.0), inject it into all source files, build the extension artifacts, publish the Docker image, and create a GitHub Release. - Verify the release builds on GitHub Actions.
Adding a Protocol Event
- Add the event name to
shared/constants.js. - Run the build script (
node scripts/build-extension.js). - Implement the handler in
server/index.jsandbackground.js.
Testing Locally
- Run the build script:
node scripts/build-extension.js. - Load
dist/chrome/as an "Unpacked Extension" in Chrome (ordist/firefox/in Firefox). - Start the server from the root:
docker-compose up --build. - Use different browser profiles or vendors to test multi-peer logic.
- Use the Dev tab to verify real-time video element metadata.
Locking Old Versions
- Update
MIN_VERSIONin the server's.envfile to the minimum acceptable version. - Restart the server. Older extensions will be rejected with a "Version too old" error.