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

100
src/utils/nostr.ts Normal file
View File

@@ -0,0 +1,100 @@
// Nostr relay pool and connection management
import { SimplePool, Event as NostrEvent } from 'nostr-tools'
const DEFAULT_RELAYS = [
'wss://relay.damus.io',
'wss://nos.lol',
'wss://relay.nostr.band',
'wss://relay.snort.social'
]
// Kind numbers for IndeeHub content types
export const NOSTR_KINDS = {
VIDEO_HORIZONTAL: 34235, // NIP-71 Video horizontal
VIDEO_VERTICAL: 34236, // NIP-71 Video vertical
LONG_FORM: 30023, // NIP-23 Long-form content
SHORT_FORM: 1, // Regular notes for shorts
}
class NostrService {
private pool: SimplePool
private relays: string[]
constructor(relays: string[] = DEFAULT_RELAYS) {
this.pool = new SimplePool()
this.relays = relays
}
/**
* Fetch video content from Nostr
* Using NIP-71 for video events
*/
async fetchVideos(limit: number = 50): Promise<NostrEvent[]> {
try {
const events = await this.pool.querySync(this.relays, {
kinds: [NOSTR_KINDS.VIDEO_HORIZONTAL, NOSTR_KINDS.VIDEO_VERTICAL],
limit
})
return events
} catch (error) {
console.error('Error fetching videos from Nostr:', error)
return []
}
}
/**
* Fetch content by creator (pubkey)
*/
async fetchByCreator(pubkey: string, limit: number = 20): Promise<NostrEvent[]> {
try {
const events = await this.pool.querySync(this.relays, {
kinds: [NOSTR_KINDS.VIDEO_HORIZONTAL, NOSTR_KINDS.VIDEO_VERTICAL],
authors: [pubkey],
limit
})
return events
} catch (error) {
console.error('Error fetching creator content:', error)
return []
}
}
/**
* Subscribe to new content events
*/
subscribeToContent(
callback: (event: NostrEvent) => void,
kinds: number[] = [NOSTR_KINDS.VIDEO_HORIZONTAL, NOSTR_KINDS.VIDEO_VERTICAL]
) {
const sub = this.pool.subscribeMany(
this.relays,
[{ kinds, limit: 10 }],
{
onevent(event) {
callback(event)
}
}
)
return () => sub.close()
}
/**
* Publish a view/watch event
*/
async publishView(videoEventId: string, userPrivkey: string) {
// TODO: Implement NIP-XX for view tracking
console.log('Publishing view for:', videoEventId)
}
/**
* Close all connections
*/
close() {
this.pool.close(this.relays)
}
}
export const nostrService = new NostrService()