Initial commit: IndeeHub decentralized streaming platform

Built a complete Netflix-style streaming interface for IndeeHub's decentralized media platform with real film content.

Features:
- Vue 3 + TypeScript + Vite setup with hot module reloading
- Netflix-inspired UI with hero section and horizontal scrolling content rows
- Glass morphism design system with custom Tailwind configuration
- 20+ real IndeeHub films organized into 6 categories (Bitcoin, Documentaries, Drama, etc.)
- Full-featured video player component with custom controls
- Mobile-responsive design with bottom navigation
- Nostr integration ready (nostr-tools, relay pool, NIP-71 support)
- Pinia state management for content
- MCP tools configured (Filesystem, Memory, Nostr, Puppeteer)

Components:
- Browse.vue: Main streaming interface with hero and content rows
- ContentRow.vue: Horizontal scrolling film cards with navigation arrows
- VideoPlayer.vue: Custom video player with play/pause, seek, volume, fullscreen
- MobileNav.vue: Bottom tab navigation for mobile devices

Tech Stack:
- Frontend: Vue 3 (Composition API), TypeScript
- Build: Vite 7
- Styling: Tailwind CSS with custom theme
- State: Pinia 3
- Router: Vue Router 4.6
- Protocol: Nostr (nostr-tools 2.22)

Design:
- 4px grid spacing system
- Glass morphism UI components
- Netflix-style hero section with featured content
- Smooth animations and hover effects
- Mobile-first responsive breakpoints
- Dark theme with custom color palette

Content:
- 20+ IndeeHub films with titles, descriptions, categories
- Bitcoin documentaries: God Bless Bitcoin, Dirty Coin, Searching for Satoshi
- Independent films and documentaries
- Working Unsplash CDN images for thumbnails and backdrops

Ready for deployment to Umbrel, Start9, and Archy nodes.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Dorian
2026-02-02 22:19:47 +00:00
commit 0bb1bcc5f9
50 changed files with 8278 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
import { ref, onMounted, onUnmounted } from 'vue'
/**
* Mobile back button handler
* Inspired by neode-ui mobile navigation
*/
export function useMobileBackButton(onBack: () => void) {
const handlePopState = () => {
onBack()
}
onMounted(() => {
window.addEventListener('popstate', handlePopState)
})
onUnmounted(() => {
window.removeEventListener('popstate', handlePopState)
})
}
/**
* Detect mobile device
*/
export function useIsMobile() {
const isMobile = ref(false)
const checkMobile = () => {
isMobile.value = window.innerWidth < 768
}
onMounted(() => {
checkMobile()
window.addEventListener('resize', checkMobile)
})
onUnmounted(() => {
window.removeEventListener('resize', checkMobile)
})
return { isMobile }
}
/**
* Touch gestures for mobile
*/
export function useSwipeGesture(
onSwipeLeft?: () => void,
onSwipeRight?: () => void
) {
let touchStartX = 0
let touchEndX = 0
const handleTouchStart = (e: TouchEvent) => {
touchStartX = e.changedTouches[0].screenX
}
const handleTouchEnd = (e: TouchEvent) => {
touchEndX = e.changedTouches[0].screenX
handleSwipe()
}
const handleSwipe = () => {
const swipeThreshold = 50
const diff = touchStartX - touchEndX
if (Math.abs(diff) < swipeThreshold) return
if (diff > 0 && onSwipeLeft) {
onSwipeLeft()
} else if (diff < 0 && onSwipeRight) {
onSwipeRight()
}
}
onMounted(() => {
document.addEventListener('touchstart', handleTouchStart)
document.addEventListener('touchend', handleTouchEnd)
})
onUnmounted(() => {
document.removeEventListener('touchstart', handleTouchStart)
document.removeEventListener('touchend', handleTouchEnd)
})
}