feat(ui): Enhance landing page interactions and animations
This commit is contained in:
450
docs/index.html
450
docs/index.html
@@ -4,137 +4,373 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Conduit - Native Mobile Client for Open-WebUI</title>
|
||||
<title>Conduit — Your AI, Everywhere</title>
|
||||
<meta name="description"
|
||||
content="Conduit is an open-source, cross-platform mobile application for Open-WebUI, providing a native mobile experience for interacting with your self-hosted AI infrastructure.">
|
||||
content="Conduit is an open-source, cross-platform mobile application for Open-WebUI. A native mobile experience for your self-hosted AI infrastructure.">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Outfit:wght@500;700&display=swap"
|
||||
rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,300;12..96,400;12..96,500;12..96,600;12..96,700;12..96,800&family=Crimson+Pro:ital,wght@0,400;0,500;0,600;1,400;1,500&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
|
||||
<link rel="icon" type="image/png"
|
||||
href="https://raw.githubusercontent.com/cogwheel0/conduit/main/assets/icon/icon.png">
|
||||
href="https://raw.githubusercontent.com/cogwheel0/conduit/main/assets/icons/icon.png">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Grain overlay -->
|
||||
<div class="grain"></div>
|
||||
|
||||
<!-- Floating orbs -->
|
||||
<div class="orb orb-1"></div>
|
||||
<div class="orb orb-2"></div>
|
||||
<div class="orb orb-3"></div>
|
||||
|
||||
<nav class="navbar">
|
||||
<div class="container">
|
||||
<a href="#" class="logo">Conduit</a>
|
||||
<a href="#" class="logo">
|
||||
<span class="logo-mark">⬡</span>
|
||||
<span class="logo-text">Conduit</span>
|
||||
</a>
|
||||
<div class="nav-links">
|
||||
<a href="#features">Features</a>
|
||||
<a href="#screenshots">Screenshots</a>
|
||||
<a href="#faq">FAQ</a>
|
||||
<a href="https://github.com/cogwheel0/conduit" target="_blank" class="github-link">
|
||||
<svg height="24" width="24" viewBox="0 0 16 16" fill="currentColor">
|
||||
<path
|
||||
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z">
|
||||
</path>
|
||||
<a href="#gallery">Gallery</a>
|
||||
<a href="https://github.com/cogwheel0/conduit" target="_blank" class="nav-cta">
|
||||
<span>View on GitHub</span>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M7 17L17 7M17 7H7M17 7V17"/>
|
||||
</svg>
|
||||
GitHub
|
||||
</a>
|
||||
</div>
|
||||
<button class="mobile-menu-btn" aria-label="Menu">
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
<div class="mobile-menu">
|
||||
<a href="#features">Features</a>
|
||||
<a href="#gallery">Gallery</a>
|
||||
<a href="https://github.com/cogwheel0/conduit" target="_blank">GitHub</a>
|
||||
</div>
|
||||
|
||||
<header class="hero">
|
||||
<div class="container">
|
||||
<div class="hero-content">
|
||||
<h1 class="hero-title">Your AI, <span class="gradient-text">Unleashed.</span></h1>
|
||||
<p class="hero-subtitle">The premium native mobile client for Open-WebUI. Connect to your self-hosted AI
|
||||
infrastructure with a beautiful, fast, and secure experience.</p>
|
||||
|
||||
<div class="download-badges">
|
||||
<a href="https://play.google.com/store/apps/details?id=app.cogwheel.conduit" class="store-badge">
|
||||
<img src="store-badges/google.webp" alt="Get it on Google Play">
|
||||
</a>
|
||||
<a href="https://apps.apple.com/us/app/conduit-open-webui-client/id6749840287" class="store-badge">
|
||||
<img src="store-badges/apple.webp" alt="Download on the App Store">
|
||||
</a>
|
||||
<div class="hero-badges">
|
||||
<div class="hero-badge">
|
||||
<span class="badge-dot"></span>
|
||||
Open Source & Privacy-First
|
||||
</div>
|
||||
<a href="https://github.com/cogwheel0/conduit" target="_blank" class="social-badge">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
||||
</svg>
|
||||
<span class="badge-value" id="github-stars">—</span>
|
||||
<span class="badge-label">Stars</span>
|
||||
</a>
|
||||
<a href="https://github.com/cogwheel0/conduit/releases" target="_blank" class="social-badge">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
|
||||
<polyline points="7 10 12 15 17 10"/>
|
||||
<line x1="12" y1="15" x2="12" y2="3"/>
|
||||
</svg>
|
||||
<span class="badge-value" id="github-downloads">—</span>
|
||||
<span class="badge-label">Downloads</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h1 class="hero-title">
|
||||
<span class="title-line">Your AI,</span>
|
||||
<span class="title-line title-accent">Everywhere<span class="title-dot">.</span></span>
|
||||
</h1>
|
||||
|
||||
<p class="hero-subtitle">
|
||||
The native mobile client for <strong>Open-WebUI</strong>.<br>
|
||||
Beautiful, fast, and secure—connect to your self-hosted AI from anywhere.
|
||||
</p>
|
||||
|
||||
<div class="hero-stats">
|
||||
<div class="stat-item">
|
||||
<div class="hero-cta">
|
||||
<a href="https://apps.apple.com/us/app/conduit-open-webui-client/id6749840287" class="btn btn-primary">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"/>
|
||||
</svg>
|
||||
<span>App Store</span>
|
||||
</a>
|
||||
<a href="https://play.google.com/store/apps/details?id=app.cogwheel.conduit" class="btn btn-secondary">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M3,20.5V3.5C3,2.91 3.34,2.39 3.84,2.15L13.69,12L3.84,21.85C3.34,21.6 3,21.09 3,20.5M16.81,15.12L6.05,21.34L14.54,12.85L16.81,15.12M20.16,10.81C20.5,11.08 20.75,11.5 20.75,12C20.75,12.5 20.53,12.9 20.18,13.18L17.89,14.5L15.39,12L17.89,9.5L20.16,10.81M6.05,2.66L16.81,8.88L14.54,11.15L6.05,2.66Z"/>
|
||||
</svg>
|
||||
<span>Google Play</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="hero-device">
|
||||
<div class="device-glow"></div>
|
||||
<div class="device-frame">
|
||||
<img src="screenshots/conduit-demo.gif" alt="Conduit App Demo" loading="eager">
|
||||
</div>
|
||||
<div class="device-reflection"></div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="stats">
|
||||
<div class="container">
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<span class="stat-value">Private</span>
|
||||
<span class="stat-label">Your data stays yours</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/>
|
||||
<polyline points="3.27 6.96 12 12.01 20.73 6.96"/>
|
||||
<line x1="12" y1="22.08" x2="12" y2="12"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<span class="stat-value">Open Source</span>
|
||||
<span class="stat-label">GPLv3 Licensed</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-value">Private</span>
|
||||
<span class="stat-label">Your Data, Your Control</span>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="5" y="2" width="14" height="20" rx="2" ry="2"/>
|
||||
<line x1="12" y1="18" x2="12.01" y2="18"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-content">
|
||||
<span class="stat-value">Native</span>
|
||||
<span class="stat-label">iOS & Android</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hero-image">
|
||||
<div class="phone-frame">
|
||||
<img src="screenshots/conduit-demo.gif" alt="Conduit App Demo">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</section>
|
||||
|
||||
<section id="features" class="features">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Why Conduit?</h2>
|
||||
<div class="features-grid">
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">⚡</div>
|
||||
<h3>Real-time Chat</h3>
|
||||
<p>Stream responses from your AI models instantly with low latency WebSocket connections.</p>
|
||||
<div class="section-header">
|
||||
<span class="section-tag">What's inside</span>
|
||||
<h2 class="section-title">Power meets<br><em>simplicity</em></h2>
|
||||
</div>
|
||||
|
||||
<!-- Hero Feature -->
|
||||
<div class="feature-hero">
|
||||
<div class="feature-hero-content">
|
||||
<div class="feature-hero-badge">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
||||
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>
|
||||
</svg>
|
||||
Signature Feature
|
||||
</div>
|
||||
<h3>Voice Call Mode</h3>
|
||||
<p>Have a phone-style conversation with your AI. Speak naturally, hear responses read aloud, and chat completely hands-free.</p>
|
||||
<ul class="feature-hero-list">
|
||||
<li>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>
|
||||
Native CallKit integration on iOS
|
||||
</li>
|
||||
<li>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>
|
||||
Text-to-speech response playback
|
||||
</li>
|
||||
<li>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>
|
||||
Works in background & lock screen
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🎨</div>
|
||||
<h3>Premium Design</h3>
|
||||
<p>Beautifully crafted interface with light, dark, and system themes that feel right at home on your
|
||||
device.</p>
|
||||
<div class="feature-hero-visual">
|
||||
<div class="feature-hero-icon">
|
||||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="feature-hero-rings">
|
||||
<div class="ring"></div>
|
||||
<div class="ring"></div>
|
||||
<div class="ring"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🔐</div>
|
||||
<h3>Secure Storage</h3>
|
||||
<p>Your credentials and API keys are stored securely using the platform's native keychain/keystore.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Feature Categories -->
|
||||
<div class="feature-categories">
|
||||
<!-- Voice & Input -->
|
||||
<div class="feature-category">
|
||||
<div class="category-header">
|
||||
<div class="category-icon">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/>
|
||||
<path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h4>Voice & Input</h4>
|
||||
</div>
|
||||
<div class="category-features">
|
||||
<div class="mini-feature">
|
||||
<span class="mini-feature-name">Speech-to-Text</span>
|
||||
<span class="mini-feature-desc">Dictate messages hands-free</span>
|
||||
</div>
|
||||
<div class="mini-feature">
|
||||
<span class="mini-feature-name">Text-to-Speech</span>
|
||||
<span class="mini-feature-desc">Hear AI responses read aloud</span>
|
||||
</div>
|
||||
<div class="mini-feature">
|
||||
<span class="mini-feature-name">Share Extension</span>
|
||||
<span class="mini-feature-desc">Send from any app to Conduit</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🎙️</div>
|
||||
<h3>Voice Input</h3>
|
||||
<p>Speak naturally to your AI with integrated speech-to-text support for hands-free interaction.</p>
|
||||
|
||||
<!-- System Integration -->
|
||||
<div class="feature-category">
|
||||
<div class="category-header">
|
||||
<div class="category-icon">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"/>
|
||||
<line x1="8" y1="21" x2="16" y2="21"/>
|
||||
<line x1="12" y1="17" x2="12" y2="21"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h4>System Integration</h4>
|
||||
</div>
|
||||
<div class="category-features">
|
||||
<div class="mini-feature">
|
||||
<span class="mini-feature-name">Siri Shortcuts</span>
|
||||
<span class="mini-feature-desc">"Hey Siri, ask Conduit..."</span>
|
||||
</div>
|
||||
<div class="mini-feature">
|
||||
<span class="mini-feature-name">Android Assistant</span>
|
||||
<span class="mini-feature-desc">Trigger via digital assistant</span>
|
||||
</div>
|
||||
<div class="mini-feature">
|
||||
<span class="mini-feature-name">Quick Actions</span>
|
||||
<span class="mini-feature-desc">Home screen shortcuts</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">📁</div>
|
||||
<h3>File Uploads</h3>
|
||||
<p>Upload images and documents for RAG (Retrieval-Augmented Generation) and vision capabilities.</p>
|
||||
|
||||
<!-- AI Capabilities -->
|
||||
<div class="feature-category">
|
||||
<div class="category-header">
|
||||
<div class="category-icon">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h4>AI Capabilities</h4>
|
||||
</div>
|
||||
<div class="category-features">
|
||||
<div class="mini-feature">
|
||||
<span class="mini-feature-name">Real-time Streaming</span>
|
||||
<span class="mini-feature-desc">Instant WebSocket responses</span>
|
||||
</div>
|
||||
<div class="mini-feature">
|
||||
<span class="mini-feature-name">Vision & RAG</span>
|
||||
<span class="mini-feature-desc">Images & document analysis</span>
|
||||
</div>
|
||||
<div class="mini-feature">
|
||||
<span class="mini-feature-name">Tool Support</span>
|
||||
<span class="mini-feature-desc">Function calling & rendering</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🛠️</div>
|
||||
<h3>Tool Support</h3>
|
||||
<p>Full support for Open-WebUI tools and function calling with rich result rendering.</p>
|
||||
|
||||
<!-- Organization -->
|
||||
<div class="feature-category">
|
||||
<div class="category-header">
|
||||
<div class="category-icon">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h4>Organization</h4>
|
||||
</div>
|
||||
<div class="category-features">
|
||||
<div class="mini-feature">
|
||||
<span class="mini-feature-name">Folders</span>
|
||||
<span class="mini-feature-desc">Organize conversations</span>
|
||||
</div>
|
||||
<div class="mini-feature">
|
||||
<span class="mini-feature-name">Search</span>
|
||||
<span class="mini-feature-desc">Find across all history</span>
|
||||
</div>
|
||||
<div class="mini-feature">
|
||||
<span class="mini-feature-name">Secure Storage</span>
|
||||
<span class="mini-feature-desc">Native keychain/keystore</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="screenshots" class="screenshots">
|
||||
<section id="gallery" class="gallery">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Experience Conduit</h2>
|
||||
<div class="screenshot-gallery">
|
||||
<div class="screenshot-item">
|
||||
<img src="screenshots/1.png" alt="Chat Interface">
|
||||
<p>Chat Interface</p>
|
||||
<div class="section-header">
|
||||
<span class="section-tag">See it in action</span>
|
||||
<h2 class="section-title">Feels right<br><em>at home</em></h2>
|
||||
</div>
|
||||
|
||||
<div class="gallery-showcase">
|
||||
<div class="gallery-track">
|
||||
<div class="gallery-item">
|
||||
<img src="screenshots/1.png" alt="Chat Interface" loading="lazy">
|
||||
<span class="gallery-label">Chat</span>
|
||||
</div>
|
||||
<div class="gallery-item">
|
||||
<img src="screenshots/2.png" alt="Model Selector" loading="lazy">
|
||||
<span class="gallery-label">Models</span>
|
||||
</div>
|
||||
<div class="gallery-item">
|
||||
<img src="screenshots/3.png" alt="Navigation" loading="lazy">
|
||||
<span class="gallery-label">Navigate</span>
|
||||
</div>
|
||||
<div class="gallery-item">
|
||||
<img src="screenshots/4.png" alt="Settings" loading="lazy">
|
||||
<span class="gallery-label">Settings</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="screenshot-item">
|
||||
<img src="screenshots/2.png" alt="Model Selector">
|
||||
<p>Model Selector</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="cta-section">
|
||||
<div class="container">
|
||||
<div class="cta-card">
|
||||
<div class="cta-content">
|
||||
<h2>Your AI awaits</h2>
|
||||
<p>Free, open source, and ready when you are. Download now.</p>
|
||||
<div class="cta-buttons">
|
||||
<a href="https://apps.apple.com/us/app/conduit-open-webui-client/id6749840287" class="btn btn-white">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"/>
|
||||
</svg>
|
||||
App Store
|
||||
</a>
|
||||
<a href="https://play.google.com/store/apps/details?id=app.cogwheel.conduit" class="btn btn-outline-white">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M3,20.5V3.5C3,2.91 3.34,2.39 3.84,2.15L13.69,12L3.84,21.85C3.34,21.6 3,21.09 3,20.5M16.81,15.12L6.05,21.34L14.54,12.85L16.81,15.12M20.16,10.81C20.5,11.08 20.75,11.5 20.75,12C20.75,12.5 20.53,12.9 20.18,13.18L17.89,14.5L15.39,12L17.89,9.5L20.16,10.81M6.05,2.66L16.81,8.88L14.54,11.15L6.05,2.66Z"/>
|
||||
</svg>
|
||||
Google Play
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="screenshot-item">
|
||||
<img src="screenshots/3.png" alt="Navigation Drawer">
|
||||
<p>Navigation</p>
|
||||
</div>
|
||||
<div class="screenshot-item">
|
||||
<img src="screenshots/4.png" alt="Settings">
|
||||
<p>Settings</p>
|
||||
<div class="cta-decoration">
|
||||
<div class="cta-ring"></div>
|
||||
<div class="cta-ring"></div>
|
||||
<div class="cta-ring"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -142,20 +378,42 @@
|
||||
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<div class="footer-content">
|
||||
<div class="footer-logo">
|
||||
<h3>Conduit</h3>
|
||||
<p>The native mobile client for Open-WebUI.</p>
|
||||
<div class="footer-main">
|
||||
<div class="footer-brand">
|
||||
<a href="#" class="logo">
|
||||
<span class="logo-mark">⬡</span>
|
||||
<span class="logo-text">Conduit</span>
|
||||
</a>
|
||||
<p>The native mobile client for Open-WebUI.<br>Open source. Privacy-first. Beautiful.</p>
|
||||
</div>
|
||||
<div class="footer-links">
|
||||
<h4>Links</h4>
|
||||
<a href="https://github.com/cogwheel0/conduit">GitHub</a>
|
||||
<a href="https://github.com/cogwheel0/conduit/issues">Issues</a>
|
||||
<a href="https://github.com/cogwheel0/conduit/discussions">Discussions</a>
|
||||
<div class="footer-links-grid">
|
||||
<div class="footer-col">
|
||||
<h4>Product</h4>
|
||||
<a href="#features">Features</a>
|
||||
<a href="#gallery">Gallery</a>
|
||||
<a href="https://github.com/cogwheel0/conduit/releases">Releases</a>
|
||||
</div>
|
||||
<div class="footer-col">
|
||||
<h4>Community</h4>
|
||||
<a href="https://github.com/cogwheel0/conduit">GitHub</a>
|
||||
<a href="https://github.com/cogwheel0/conduit/issues">Issues</a>
|
||||
<a href="https://github.com/cogwheel0/conduit/discussions">Discussions</a>
|
||||
</div>
|
||||
<div class="footer-col">
|
||||
<h4>Legal</h4>
|
||||
<a href="https://github.com/cogwheel0/conduit/blob/main/LICENSE">License (GPLv3)</a>
|
||||
<a href="https://github.com/cogwheel0/conduit/blob/main/PRIVACY_POLICY.md">Privacy Policy</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-legal">
|
||||
<p>© 2025 Conduit. Licensed under GPLv3.</p>
|
||||
<p>Not affiliated with Open-WebUI.</p>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
<p>© 2025 Conduit. Not affiliated with Open-WebUI.</p>
|
||||
<div class="footer-social">
|
||||
<a href="https://github.com/cogwheel0/conduit" aria-label="GitHub">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -164,4 +422,4 @@
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
329
docs/script.js
329
docs/script.js
@@ -1,21 +1,79 @@
|
||||
/**
|
||||
* Conduit Landing Page
|
||||
* Smooth interactions and animations
|
||||
*/
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Smooth scrolling for anchor links
|
||||
// ============================================
|
||||
// SMOOTH SCROLL
|
||||
// ============================================
|
||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
const target = document.querySelector(this.getAttribute('href'));
|
||||
const targetId = this.getAttribute('href');
|
||||
if (targetId === '#') return;
|
||||
|
||||
const target = document.querySelector(targetId);
|
||||
if (target) {
|
||||
target.scrollIntoView({
|
||||
const navHeight = document.querySelector('.navbar').offsetHeight;
|
||||
const targetPosition = target.offsetTop - navHeight - 20;
|
||||
|
||||
window.scrollTo({
|
||||
top: targetPosition,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
|
||||
// Close mobile menu if open
|
||||
mobileMenu.classList.remove('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Intersection Observer for fade-in animations
|
||||
// ============================================
|
||||
// MOBILE MENU
|
||||
// ============================================
|
||||
const mobileMenuBtn = document.querySelector('.mobile-menu-btn');
|
||||
const mobileMenu = document.querySelector('.mobile-menu');
|
||||
|
||||
if (mobileMenuBtn && mobileMenu) {
|
||||
mobileMenuBtn.addEventListener('click', () => {
|
||||
mobileMenu.classList.toggle('active');
|
||||
mobileMenuBtn.classList.toggle('active');
|
||||
});
|
||||
|
||||
// Close menu when clicking a link
|
||||
mobileMenu.querySelectorAll('a').forEach(link => {
|
||||
link.addEventListener('click', () => {
|
||||
mobileMenu.classList.remove('active');
|
||||
mobileMenuBtn.classList.remove('active');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// NAVBAR SCROLL EFFECT
|
||||
// ============================================
|
||||
const navbar = document.querySelector('.navbar');
|
||||
let lastScroll = 0;
|
||||
|
||||
window.addEventListener('scroll', () => {
|
||||
const currentScroll = window.pageYOffset;
|
||||
|
||||
if (currentScroll > 100) {
|
||||
navbar.style.background = 'rgba(10, 10, 12, 0.9)';
|
||||
} else {
|
||||
navbar.style.background = 'rgba(10, 10, 12, 0.6)';
|
||||
}
|
||||
|
||||
lastScroll = currentScroll;
|
||||
}, { passive: true });
|
||||
|
||||
// ============================================
|
||||
// INTERSECTION OBSERVER - FADE IN
|
||||
// ============================================
|
||||
const observerOptions = {
|
||||
threshold: 0.1,
|
||||
rootMargin: '0px 0px -50px 0px'
|
||||
rootMargin: '0px 0px -60px 0px'
|
||||
};
|
||||
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
@@ -27,32 +85,249 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
}, observerOptions);
|
||||
|
||||
// Add fade-in class to elements we want to animate
|
||||
const animatedElements = document.querySelectorAll('.feature-card, .screenshot-item, .hero-content, .hero-image');
|
||||
animatedElements.forEach(el => {
|
||||
// Observe feature cards
|
||||
document.querySelectorAll('.feature-card').forEach(el => {
|
||||
el.classList.add('fade-in');
|
||||
observer.observe(el);
|
||||
});
|
||||
|
||||
// Observe stat cards
|
||||
document.querySelectorAll('.stat-card').forEach((el, i) => {
|
||||
el.classList.add('fade-in');
|
||||
el.style.transitionDelay = `${i * 0.1}s`;
|
||||
observer.observe(el);
|
||||
});
|
||||
|
||||
// Observe gallery items
|
||||
document.querySelectorAll('.gallery-item').forEach((el, i) => {
|
||||
el.classList.add('fade-in');
|
||||
el.style.transitionDelay = `${i * 0.1}s`;
|
||||
observer.observe(el);
|
||||
});
|
||||
|
||||
// Observe section headers
|
||||
document.querySelectorAll('.section-header').forEach(el => {
|
||||
el.classList.add('fade-in');
|
||||
observer.observe(el);
|
||||
});
|
||||
});
|
||||
|
||||
// Add this CSS to styles.css dynamically or ensure it's in the CSS file
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
.fade-in {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
transition: opacity 0.6s ease-out, transform 0.6s ease-out;
|
||||
}
|
||||
// ============================================
|
||||
// PARALLAX ORBS (subtle effect)
|
||||
// ============================================
|
||||
const orbs = document.querySelectorAll('.orb');
|
||||
|
||||
.fade-in.visible {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
if (window.matchMedia('(prefers-reduced-motion: no-preference)').matches) {
|
||||
window.addEventListener('scroll', () => {
|
||||
const scrollY = window.pageYOffset;
|
||||
|
||||
orbs.forEach((orb, i) => {
|
||||
const speed = (i + 1) * 0.03;
|
||||
orb.style.transform = `translateY(${scrollY * speed}px)`;
|
||||
});
|
||||
}, { passive: true });
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// DEVICE FRAME TILT ON MOUSE MOVE
|
||||
// ============================================
|
||||
const deviceFrame = document.querySelector('.device-frame');
|
||||
const heroSection = document.querySelector('.hero');
|
||||
|
||||
.feature-card:nth-child(2) { transition-delay: 0.1s; }
|
||||
.feature-card:nth-child(3) { transition-delay: 0.2s; }
|
||||
.feature-card:nth-child(4) { transition-delay: 0.3s; }
|
||||
.feature-card:nth-child(5) { transition-delay: 0.4s; }
|
||||
.feature-card:nth-child(6) { transition-delay: 0.5s; }
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
if (deviceFrame && heroSection && window.matchMedia('(prefers-reduced-motion: no-preference)').matches) {
|
||||
heroSection.addEventListener('mousemove', (e) => {
|
||||
const rect = heroSection.getBoundingClientRect();
|
||||
const x = (e.clientX - rect.left) / rect.width - 0.5;
|
||||
const y = (e.clientY - rect.top) / rect.height - 0.5;
|
||||
|
||||
const tiltX = y * 10;
|
||||
const tiltY = -x * 10;
|
||||
|
||||
deviceFrame.style.transform = `perspective(1000px) rotateX(${tiltX}deg) rotateY(${tiltY}deg) scale(1.02)`;
|
||||
});
|
||||
|
||||
heroSection.addEventListener('mouseleave', () => {
|
||||
deviceFrame.style.transform = 'perspective(1000px) rotateX(0) rotateY(0) scale(1)';
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// GALLERY DRAG SCROLL
|
||||
// ============================================
|
||||
const galleryTrack = document.querySelector('.gallery-track');
|
||||
|
||||
if (galleryTrack) {
|
||||
let isDown = false;
|
||||
let startX;
|
||||
let scrollLeft;
|
||||
|
||||
galleryTrack.addEventListener('mousedown', (e) => {
|
||||
isDown = true;
|
||||
galleryTrack.style.cursor = 'grabbing';
|
||||
startX = e.pageX - galleryTrack.offsetLeft;
|
||||
scrollLeft = galleryTrack.scrollLeft;
|
||||
});
|
||||
|
||||
galleryTrack.addEventListener('mouseleave', () => {
|
||||
isDown = false;
|
||||
galleryTrack.style.cursor = 'grab';
|
||||
});
|
||||
|
||||
galleryTrack.addEventListener('mouseup', () => {
|
||||
isDown = false;
|
||||
galleryTrack.style.cursor = 'grab';
|
||||
});
|
||||
|
||||
galleryTrack.addEventListener('mousemove', (e) => {
|
||||
if (!isDown) return;
|
||||
e.preventDefault();
|
||||
const x = e.pageX - galleryTrack.offsetLeft;
|
||||
const walk = (x - startX) * 1.5;
|
||||
galleryTrack.scrollLeft = scrollLeft - walk;
|
||||
});
|
||||
|
||||
// Set initial cursor
|
||||
galleryTrack.style.cursor = 'grab';
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// CTA RING ANIMATION RESET
|
||||
// ============================================
|
||||
const ctaSection = document.querySelector('.cta-section');
|
||||
const ctaRings = document.querySelectorAll('.cta-ring');
|
||||
|
||||
if (ctaSection && ctaRings.length) {
|
||||
const ctaObserver = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
// Reset animation when section comes into view
|
||||
ctaRings.forEach(ring => {
|
||||
ring.style.animation = 'none';
|
||||
ring.offsetHeight; // Trigger reflow
|
||||
ring.style.animation = null;
|
||||
});
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.3 });
|
||||
|
||||
ctaObserver.observe(ctaSection);
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// BUTTON RIPPLE EFFECT
|
||||
// ============================================
|
||||
document.querySelectorAll('.btn').forEach(btn => {
|
||||
btn.addEventListener('click', function(e) {
|
||||
const ripple = document.createElement('span');
|
||||
const rect = this.getBoundingClientRect();
|
||||
|
||||
ripple.style.cssText = `
|
||||
position: absolute;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
transform: scale(0);
|
||||
animation: ripple 0.6s ease-out;
|
||||
left: ${e.clientX - rect.left}px;
|
||||
top: ${e.clientY - rect.top}px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
`;
|
||||
|
||||
this.style.position = 'relative';
|
||||
this.style.overflow = 'hidden';
|
||||
this.appendChild(ripple);
|
||||
|
||||
setTimeout(() => ripple.remove(), 600);
|
||||
});
|
||||
});
|
||||
|
||||
// Add ripple keyframes
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
@keyframes ripple {
|
||||
to {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
margin-left: -100px;
|
||||
margin-top: -100px;
|
||||
opacity: 0;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// ============================================
|
||||
// PRELOAD IMAGES
|
||||
// ============================================
|
||||
const preloadImages = [
|
||||
'screenshots/1.png',
|
||||
'screenshots/2.png',
|
||||
'screenshots/3.png',
|
||||
'screenshots/4.png'
|
||||
];
|
||||
|
||||
preloadImages.forEach(src => {
|
||||
const img = new Image();
|
||||
img.src = src;
|
||||
});
|
||||
|
||||
// ============================================
|
||||
// FETCH GITHUB STATS
|
||||
// ============================================
|
||||
const formatNumber = (num) => {
|
||||
if (num >= 1000000) {
|
||||
return (num / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
|
||||
}
|
||||
if (num >= 1000) {
|
||||
return (num / 1000).toFixed(1).replace(/\.0$/, '') + 'k';
|
||||
}
|
||||
return num.toString();
|
||||
};
|
||||
|
||||
const starsElement = document.getElementById('github-stars');
|
||||
const downloadsElement = document.getElementById('github-downloads');
|
||||
|
||||
// Fetch repo stats (stars)
|
||||
if (starsElement) {
|
||||
fetch('https://api.github.com/repos/cogwheel0/conduit')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.stargazers_count !== undefined) {
|
||||
starsElement.textContent = formatNumber(data.stargazers_count);
|
||||
starsElement.classList.add('loaded');
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
starsElement.textContent = '★';
|
||||
});
|
||||
}
|
||||
|
||||
// Fetch releases (downloads)
|
||||
if (downloadsElement) {
|
||||
fetch('https://api.github.com/repos/cogwheel0/conduit/releases')
|
||||
.then(response => response.json())
|
||||
.then(releases => {
|
||||
if (Array.isArray(releases)) {
|
||||
const totalDownloads = releases.reduce((total, release) => {
|
||||
return total + release.assets.reduce((assetTotal, asset) => {
|
||||
return assetTotal + (asset.download_count || 0);
|
||||
}, 0);
|
||||
}, 0);
|
||||
|
||||
if (totalDownloads > 0) {
|
||||
downloadsElement.textContent = formatNumber(totalDownloads);
|
||||
} else {
|
||||
// If no GitHub downloads, show a generic indicator
|
||||
downloadsElement.textContent = 'New';
|
||||
}
|
||||
downloadsElement.classList.add('loaded');
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
downloadsElement.textContent = '↓';
|
||||
});
|
||||
}
|
||||
|
||||
console.log('✨ Conduit landing page initialized');
|
||||
});
|
||||
|
||||
1516
docs/styles.css
1516
docs/styles.css
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user