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>
225 lines
4.1 KiB
Plaintext
225 lines
4.1 KiB
Plaintext
---
|
|
description: Performance optimization and bundle size management
|
|
alwaysApply: false
|
|
globs: **/*.{js,ts,vue,jsx,tsx}
|
|
---
|
|
|
|
# Performance & Optimization
|
|
|
|
## Performance Targets
|
|
|
|
- **Bundle Size**: < 200KB gzipped
|
|
- **LCP** (Largest Contentful Paint): < 2.5s
|
|
- **FID** (First Input Delay): < 100ms
|
|
- **Mobile 3G**: Load in under 5s
|
|
- **Desktop**: Load in under 2s
|
|
- **Animation Frame Rate**: 60fps (16.67ms per frame)
|
|
|
|
## Bundle Size Optimization
|
|
|
|
### 1. Code Splitting by Route
|
|
|
|
```javascript
|
|
// Vue Router with lazy loading
|
|
const routes = [
|
|
{
|
|
path: '/',
|
|
component: HomePage // Eager loaded
|
|
},
|
|
{
|
|
path: '/projects/:id',
|
|
component: () => import('./views/ProjectDetail.vue') // Lazy loaded
|
|
}
|
|
]
|
|
```
|
|
|
|
### 2. Lazy Load Heavy Components
|
|
|
|
```javascript
|
|
import { defineAsyncComponent } from 'vue'
|
|
|
|
const HeavyChart = defineAsyncComponent(() =>
|
|
import('./components/HeavyChart.vue')
|
|
)
|
|
```
|
|
|
|
### 3. Tree Shaking
|
|
|
|
```javascript
|
|
// ✅ Good - Named imports (tree-shakeable)
|
|
import { ref, computed } from 'vue'
|
|
|
|
// ❌ Bad - Default import (not tree-shakeable)
|
|
import Vue from 'vue'
|
|
```
|
|
|
|
## Image Optimization
|
|
|
|
### 1. Use Modern Formats
|
|
- **WebP**: 30% smaller than JPEG
|
|
- **AVIF**: Even smaller
|
|
|
|
```html
|
|
<picture>
|
|
<source srcset="image.avif" type="image/avif">
|
|
<source srcset="image.webp" type="image/webp">
|
|
<img src="image.jpg" alt="Fallback">
|
|
</picture>
|
|
```
|
|
|
|
### 2. Lazy Loading
|
|
|
|
```html
|
|
<img src="image.jpg" loading="lazy" alt="Lazy loaded" />
|
|
```
|
|
|
|
### 3. Responsive Images
|
|
|
|
```html
|
|
<img
|
|
srcset="
|
|
image-320.jpg 320w,
|
|
image-640.jpg 640w,
|
|
image-1024.jpg 1024w
|
|
"
|
|
sizes="(max-width: 640px) 100vw, 50vw"
|
|
src="image-640.jpg"
|
|
alt="Responsive image"
|
|
/>
|
|
```
|
|
|
|
## Font Optimization
|
|
|
|
### 1. Preload Critical Fonts
|
|
|
|
```html
|
|
<link
|
|
rel="preload"
|
|
href="/fonts/ProximaNova-Bold.woff2"
|
|
as="font"
|
|
type="font/woff2"
|
|
crossorigin
|
|
>
|
|
```
|
|
|
|
### 2. Font Display Strategy
|
|
|
|
```css
|
|
@font-face {
|
|
font-family: 'Proxima Nova';
|
|
src: url('/fonts/proximanova.woff2') format('woff2');
|
|
font-display: swap; /* Show fallback immediately */
|
|
}
|
|
```
|
|
|
|
## JavaScript Performance
|
|
|
|
### 1. Debounce Expensive Operations
|
|
|
|
```javascript
|
|
let timeout
|
|
const handleSearch = (event) => {
|
|
clearTimeout(timeout)
|
|
timeout = setTimeout(() => {
|
|
// Perform search
|
|
}, 300)
|
|
}
|
|
```
|
|
|
|
### 2. Memoization
|
|
|
|
```javascript
|
|
import { computed } from 'vue'
|
|
|
|
const filteredProjects = computed(() => {
|
|
return projects.value.filter(p =>
|
|
p.title.includes(searchQuery.value)
|
|
)
|
|
})
|
|
```
|
|
|
|
## Rendering Performance
|
|
|
|
### 1. Use CSS Transforms for Animations
|
|
|
|
```css
|
|
/* ❌ Bad - Triggers layout */
|
|
.element {
|
|
transition: top 0.3s;
|
|
}
|
|
|
|
/* ✅ Good - GPU accelerated */
|
|
.element {
|
|
transition: transform 0.3s;
|
|
}
|
|
.element:hover {
|
|
transform: translateY(10px);
|
|
}
|
|
```
|
|
|
|
### 2. Animate Only Transform and Opacity
|
|
|
|
- ✅ Animate `transform` and `opacity` only
|
|
- ❌ Don't animate `width`, `height`, `top`, `left`
|
|
|
|
## Vue-Specific Optimizations
|
|
|
|
### Use `v-once` for Static Content
|
|
|
|
```vue
|
|
<div v-once>
|
|
<h1>{{ staticTitle }}</h1>
|
|
</div>
|
|
```
|
|
|
|
### Shallow Reactive for Large Objects
|
|
|
|
```javascript
|
|
import { shallowRef } from 'vue'
|
|
const projects = shallowRef([...largeArray])
|
|
```
|
|
|
|
### Keep Components Small
|
|
|
|
Split large components into smaller, focused ones.
|
|
|
|
## Mobile Performance
|
|
|
|
### 1. Use Passive Event Listeners
|
|
|
|
```javascript
|
|
element.addEventListener('touchstart', handler, { passive: true })
|
|
```
|
|
|
|
### 2. Test on Real Devices
|
|
|
|
- Use slow 3G throttling
|
|
- Test on mid-range Android devices
|
|
- Use Chrome DevTools CPU throttling (4x slowdown)
|
|
|
|
## Performance Checklist
|
|
|
|
### Build Time
|
|
- ✅ Code split by route
|
|
- ✅ Lazy load heavy components
|
|
- ✅ Tree shake unused code
|
|
- ✅ Minify and compress assets
|
|
- ✅ Optimize images (WebP, compression)
|
|
|
|
### Runtime
|
|
- ✅ Debounce expensive operations
|
|
- ✅ Memoize computed values
|
|
- ✅ Use CSS transforms for animations
|
|
- ✅ Avoid layout thrashing
|
|
|
|
### Network
|
|
- ✅ Enable compression (gzip/brotli)
|
|
- ✅ Set appropriate cache headers
|
|
- ✅ Preload/prefetch resources
|
|
|
|
### Fonts
|
|
- ✅ Preload critical fonts
|
|
- ✅ Use font-display: swap
|
|
|
|
**Remember: Performance is not a one-time task—it's an ongoing practice.**
|