diff --git a/AI_INIT.md b/AI_INIT.md index 5e9e414..ea79b62 100644 --- a/AI_INIT.md +++ b/AI_INIT.md @@ -12,6 +12,7 @@ KoalaSync is a specialized tool for **synchronized video playback** across multi ## 2. Repository Structure - `extension/`: Chrome Extension (Manifest V3). Contains background service worker, content scripts, and popup UI. - `server/`: Node.js Relay Server using Socket.IO (WebSocket-only). +- `website/`: **Landing Page** (Marketing, Tutorials, and Downloads). - `shared/`: **Single Source of Truth** for protocol constants and event names. - `scripts/`: Utility scripts (e.g., `sync-constants.sh`). - `docker-compose.yml`: Root-level orchestration for the relay server. diff --git a/README.md b/README.md index 8667385..f2f3bf9 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ KoalaSync is a Chrome Extension and Relay Server for synchronized video playback ## Repository Structure - `extension/`: Chrome Extension (Manifest V3). - `server/`: Node.js + Socket.IO Relay Server. +- `website/`: Static marketing landing page & tutorials. - `shared/`: Shared protocol constants. ## Setup Instructions diff --git a/website/app.js b/website/app.js new file mode 100644 index 0000000..dbfaa46 --- /dev/null +++ b/website/app.js @@ -0,0 +1,50 @@ +// KoalaSync Landing Page Logic + +document.addEventListener('DOMContentLoaded', () => { + // Scroll Reveal Logic + const revealElements = document.querySelectorAll('[data-reveal]'); + + const revealOnScroll = () => { + const windowHeight = window.innerHeight; + revealElements.forEach(el => { + const elementTop = el.getBoundingClientRect().top; + const revealPoint = 150; + + if (elementTop < windowHeight - revealPoint) { + el.classList.add('revealed'); + } + }); + }; + + // Initial check + revealOnScroll(); + + // Scroll listener + window.addEventListener('scroll', revealOnScroll); + + // Navbar scroll effect + const nav = document.querySelector('nav'); + window.addEventListener('scroll', () => { + if (window.scrollY > 50) { + nav.style.padding = '0.75rem 0'; + nav.style.background = 'rgba(15, 23, 42, 0.9)'; + } else { + nav.style.padding = '1rem 0'; + nav.style.background = 'rgba(30, 41, 59, 0.7)'; + } + }); + + // Smooth scroll for anchors + document.querySelectorAll('a[href^="#"]').forEach(anchor => { + anchor.addEventListener('click', function (e) { + e.preventDefault(); + const target = document.querySelector(this.getAttribute('href')); + if (target) { + target.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + } + }); + }); +}); diff --git a/website/assets/logo.png b/website/assets/logo.png new file mode 100644 index 0000000..b381505 Binary files /dev/null and b/website/assets/logo.png differ diff --git a/website/index.html b/website/index.html new file mode 100644 index 0000000..e1044f4 --- /dev/null +++ b/website/index.html @@ -0,0 +1,133 @@ + + + + + + KoalaSync | Real-time Video Synchronization for Friends + + + + + + + + + + + + + +
+
+
+
+
+ + + +
+
+
+

Watch Together.
Sync Perfectly.

+

KoalaSync brings friends closer through synchronized video playback. No lag, no tracking, just shared moments.

+ +
+
+
+ +
+
+

Why KoalaSync?

+

Built for performance, privacy, and simplicity.

+ +
+
+
+

Real-time Sync

+

Proprietary two-phase synchronization protocol ensures sub-millisecond precision across all peers.

+
+
+
🛡️
+

Privacy First

+

Zero data persistence. Our relay server runs entirely in RAM and collects no telemetry or logs.

+
+
+
+

Smart Match

+

Find the right tab instantly. KoalaSync highlights and sorts matching video tabs for you.

+
+
+
+
+ +
+
+

Getting Started

+ +
+
+
+
01
+

Install Extension

+

Add KoalaSync to your browser from the Chrome Web Store or download the latest developer ZIP from GitHub.

+
+
+
+
+
+
02
+

Create a Room

+

Open the extension, enter a Room ID and Password, and hit Join. Your secure synchronization space is ready.

+
+
+
+
+
+
03
+

Share & Sync

+

Send the invite link to your friends. Once they join, select your video tab and enjoy perfectly synced playback.

+
+
+
+
+
+
+ +
+
+

Ready to sync?

+

Join thousands of users watching together.

+ View on GitHub +
+
+ + + + + + diff --git a/website/style.css b/website/style.css new file mode 100644 index 0000000..9ddb1bf --- /dev/null +++ b/website/style.css @@ -0,0 +1,302 @@ +@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;800&display=swap'); + +:root { + --bg: #0f172a; + --card: #1e293b; + --accent: #6366f1; + --accent-glow: rgba(99, 102, 241, 0.3); + --text: #f8fafc; + --text-muted: #94a3b8; + --success: #22c55e; + --glass: rgba(30, 41, 59, 0.4); + --glass-border: rgba(255, 255, 255, 0.05); +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Outfit', sans-serif; + background-color: var(--bg); + color: var(--text); + line-height: 1.6; + overflow-x: hidden; + position: relative; +} + +/* --- Animated Background --- */ +.bg-blobs { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: -1; + overflow: hidden; + background: radial-gradient(circle at 50% 50%, #1e1b4b 0%, #0f172a 100%); +} + +.blob { + position: absolute; + width: 600px; + height: 600px; + background: radial-gradient(circle, var(--accent-glow) 0%, transparent 70%); + filter: blur(80px); + border-radius: 50%; + opacity: 0.5; + animation: move 25s infinite alternate ease-in-out; +} + +.blob-1 { top: -100px; left: -100px; animation-delay: 0s; } +.blob-2 { bottom: -100px; right: -100px; animation-delay: -5s; background: radial-gradient(circle, rgba(139, 92, 246, 0.2) 0%, transparent 70%); } +.blob-3 { top: 40%; left: 30%; animation-duration: 35s; animation-delay: -10s; } + +@keyframes move { + 0% { transform: translate(0, 0) scale(1); } + 33% { transform: translate(100px, 100px) scale(1.2); } + 66% { transform: translate(-50px, 200px) scale(0.8); } + 100% { transform: translate(0, 0) scale(1); } +} + +/* --- Layout --- */ +.container { + max-width: 1100px; + margin: 0 auto; + padding: 0 2rem; +} + +section { + padding: 6rem 0; +} + +/* --- Navigation --- */ +nav { + position: fixed; + top: 0; + width: 100%; + z-index: 1000; + background: var(--glass); + backdrop-filter: blur(12px); + border-bottom: 1px solid var(--glass-border); + padding: 1rem 0; +} + +.nav-content { + display: flex; + justify-content: space-between; + align-items: center; +} + +.logo-area { + display: flex; + align-items: center; + gap: 0.75rem; + font-weight: 800; + font-size: 1.5rem; + letter-spacing: -0.5px; +} + +.logo-area img { + height: 40px; + width: 40px; +} + +.nav-links { + display: flex; + gap: 2rem; +} + +.nav-links a { + color: var(--text-muted); + text-decoration: none; + font-weight: 500; + transition: color 0.3s; +} + +.nav-links a:hover { + color: var(--accent); +} + +/* --- Hero Section --- */ +.hero { + min-height: 100vh; + display: flex; + align-items: center; + padding-top: 8rem; + text-align: center; +} + +.hero-grid { + display: flex; + flex-direction: column; + align-items: center; + gap: 2rem; +} + +.hero-text h1 { + font-size: 5rem; + font-weight: 800; + line-height: 1; + margin-bottom: 1.5rem; + background: linear-gradient(to bottom, #fff 30%, #6366f1); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + +.hero-text p { + font-size: 1.5rem; + color: var(--text-muted); + margin-bottom: 3rem; + max-width: 700px; + margin-left: auto; + margin-right: auto; +} + +.cta-group { + display: flex; + gap: 1rem; +} + +.btn { + padding: 1rem 2rem; + border-radius: 12px; + font-weight: 600; + text-decoration: none; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +.btn-primary { + background: var(--accent); + color: white; + box-shadow: 0 10px 15px -3px var(--accent-glow); +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 20px 25px -5px var(--accent-glow); +} + +.btn-secondary { + background: var(--card); + color: var(--text); + border: 1px solid var(--glass-border); +} + +.btn-secondary:hover { + background: #2d3748; + transform: translateY(-2px); +} + +.hero-image { + display: none; +} + +/* --- Features --- */ +.features-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 2rem; + margin-top: 4rem; +} + +.feature-card { + background: var(--card); + padding: 2.5rem; + border-radius: 24px; + border: 1px solid var(--glass-border); + transition: transform 0.3s; +} + +.feature-card:hover { + transform: translateY(-10px); +} + +.feature-icon { + width: 48px; + height: 48px; + background: var(--accent-glow); + color: var(--accent); + display: flex; + align-items: center; + justify-content: center; + border-radius: 12px; + margin-bottom: 1.5rem; + font-size: 1.5rem; +} + +.feature-card h3 { + margin-bottom: 1rem; + font-size: 1.5rem; +} + +.feature-card p { + color: var(--text-muted); +} + +/* --- How it works --- */ +.steps { + display: flex; + flex-direction: column; + gap: 4rem; +} + +.step { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 4rem; + align-items: center; +} + +.step:nth-child(even) .step-text { + order: 2; +} + +.step-num { + font-size: 5rem; + font-weight: 800; + color: var(--accent-glow); + line-height: 1; + margin-bottom: 1rem; +} + +/* --- Footer --- */ +footer { + padding: 4rem 0; + border-top: 1px solid var(--glass-border); + text-align: center; + color: var(--text-muted); +} + +/* --- Animations --- */ +[data-reveal] { + opacity: 0; + transform: translateY(30px); + transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1); +} + +[data-reveal].revealed { + opacity: 1; + transform: translateY(0); +} + +@media (max-width: 768px) { + .hero-grid, .step { + grid-template-columns: 1fr; + text-align: center; + } + .hero-text h1 { + font-size: 2.5rem; + } + .cta-group { + justify-content: center; + } + .nav-links { + display: none; + } +}