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>
153 lines
3.2 KiB
Plaintext
153 lines
3.2 KiB
Plaintext
---
|
|
description: Theme system architecture with CSS-based theming
|
|
alwaysApply: false
|
|
globs: **/*.{css,vue,jsx,tsx}
|
|
---
|
|
|
|
# Theme System Architecture
|
|
|
|
## Core Principle
|
|
|
|
Build applications with theming as a **core architectural decision from day one**.
|
|
|
|
## Theme Architecture Rules
|
|
|
|
### 1. CSS-Based Themes with Reactive State
|
|
- Themes are pure CSS (performance)
|
|
- State management is reactive (Vue/React)
|
|
- No JavaScript for style calculations
|
|
|
|
### 2. Unified Background System ⚠️ CRITICAL
|
|
|
|
**Header, sidebar, and main background MUST use the same fill color.**
|
|
|
|
```css
|
|
/* ✅ Good - Unified background */
|
|
.theme-name {
|
|
background-color: #0a0a0a;
|
|
}
|
|
|
|
.theme-name aside,
|
|
.theme-name header {
|
|
background: #0a0a0a; /* Same as root */
|
|
}
|
|
|
|
/* ❌ Bad - Clashing backgrounds */
|
|
.theme-name aside {
|
|
background: #1a1a1a; /* Different - creates visual clash */
|
|
}
|
|
```
|
|
|
|
### 3. No Separator Borders
|
|
|
|
Do not add borders between sidebar/content or header/content. Let backgrounds blend seamlessly.
|
|
|
|
## Implementation
|
|
|
|
### Theme State Management (Vue)
|
|
|
|
```javascript
|
|
// composables/useTheme.js
|
|
import { ref } from 'vue'
|
|
|
|
const currentTheme = ref('ultra-modern-light')
|
|
|
|
export function useTheme() {
|
|
const setTheme = (themeName) => {
|
|
currentTheme.value = themeName
|
|
localStorage.setItem('theme', themeName)
|
|
document.documentElement.className = themeName
|
|
}
|
|
|
|
const initTheme = () => {
|
|
const saved = localStorage.getItem('theme')
|
|
if (saved) currentTheme.value = saved
|
|
}
|
|
|
|
return { currentTheme, setTheme, initTheme }
|
|
}
|
|
```
|
|
|
|
### Theme CSS Structure
|
|
|
|
```css
|
|
/* ===== THEME: Theme Name ===== */
|
|
|
|
/* Root Background */
|
|
.theme-name {
|
|
background-color: #color !important;
|
|
}
|
|
|
|
/* Sidebar - MUST match root */
|
|
.theme-name aside {
|
|
background: #color !important;
|
|
}
|
|
|
|
/* Header - MUST match root */
|
|
.theme-name header {
|
|
background: #color !important;
|
|
}
|
|
|
|
/* Content Cards */
|
|
.theme-name .content-card {
|
|
background: linear-gradient(...) !important;
|
|
border: 1px solid #color;
|
|
box-shadow: 0 8px 24px rgba(...);
|
|
border-radius: 16px;
|
|
}
|
|
|
|
/* Buttons */
|
|
.theme-name .btn-primary {
|
|
background: linear-gradient(...);
|
|
color: #fff;
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* Navigation */
|
|
.theme-name nav a.active {
|
|
background: linear-gradient(...) !important;
|
|
color: #color !important;
|
|
}
|
|
```
|
|
|
|
## Theme Testing Checklist
|
|
|
|
Before shipping a new theme:
|
|
|
|
- ✅ Header, sidebar, and background match
|
|
- ✅ No visual borders/separation
|
|
- ✅ Text is readable (sufficient contrast)
|
|
- ✅ Buttons have clear hover states
|
|
- ✅ Active navigation item is distinct
|
|
- ✅ Icons are visible
|
|
- ✅ Theme persists after page reload
|
|
- ✅ Works on mobile and desktop
|
|
|
|
## Dark Mode Support
|
|
|
|
```css
|
|
/* Light Theme */
|
|
.theme-light {
|
|
background-color: #faf9f6;
|
|
}
|
|
|
|
/* Dark Theme */
|
|
.theme-dark {
|
|
background-color: #0a0a0a;
|
|
}
|
|
```
|
|
|
|
## Theme Best Practices
|
|
|
|
### ✅ DO:
|
|
- Match header, sidebar, and root backgrounds
|
|
- Use `!important` for theme overrides (necessary)
|
|
- Test themes in browser before considering complete
|
|
- Group theme styles together
|
|
|
|
### ❌ DON'T:
|
|
- Add borders between sidebar and content
|
|
- Use different background colors for header/sidebar/root
|
|
- Create themes without testing visual harmony
|
|
- Use inline styles that override themes
|