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:
239
.cursor/rules/code-quality.mdc
Normal file
239
.cursor/rules/code-quality.mdc
Normal file
@@ -0,0 +1,239 @@
|
||||
---
|
||||
description: Code quality principles and clean code practices
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# Code Quality & Clean Code Standards
|
||||
|
||||
## Core Principles
|
||||
|
||||
### 1. Readability First
|
||||
|
||||
Code is read far more often than it's written.
|
||||
|
||||
```javascript
|
||||
// ❌ Bad - Unclear, cryptic
|
||||
const d = new Date()
|
||||
const y = d.getFullYear()
|
||||
|
||||
// ✅ Good - Clear, self-documenting
|
||||
const today = new Date()
|
||||
const year = today.getFullYear()
|
||||
```
|
||||
|
||||
### 2. Single Responsibility Principle
|
||||
|
||||
Each function/component should do one thing well.
|
||||
|
||||
```javascript
|
||||
// ✅ Good - Single responsibility
|
||||
function validateEmail(email) {
|
||||
return email && email.length > 0
|
||||
}
|
||||
|
||||
function formatEmail(email) {
|
||||
return email.toLowerCase().trim()
|
||||
}
|
||||
```
|
||||
|
||||
### 3. DRY (Don't Repeat Yourself)
|
||||
|
||||
Extract repeated logic into reusable functions.
|
||||
|
||||
### 4. Meaningful Names
|
||||
|
||||
Names should reveal intent.
|
||||
|
||||
```javascript
|
||||
// ❌ Bad
|
||||
const d = 86400000
|
||||
const arr = []
|
||||
|
||||
// ✅ Good
|
||||
const MILLISECONDS_PER_DAY = 86400000
|
||||
const activeProjects = []
|
||||
```
|
||||
|
||||
### 5. Keep It Simple (KISS)
|
||||
|
||||
Simplicity is the ultimate sophistication.
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Always Handle Errors
|
||||
|
||||
```javascript
|
||||
// ✅ Good - Comprehensive error handling
|
||||
async function fetchProjects() {
|
||||
const error = ref(null)
|
||||
const isLoading = ref(true)
|
||||
const data = ref(null)
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/projects')
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
|
||||
data.value = await response.json()
|
||||
} catch (err) {
|
||||
error.value = err.message
|
||||
console.error('Failed to fetch projects:', err)
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
|
||||
return { data, error, isLoading }
|
||||
}
|
||||
```
|
||||
|
||||
### User-Friendly Error Messages
|
||||
|
||||
```javascript
|
||||
function getErrorMessage(error) {
|
||||
const messages = {
|
||||
'ERR_CONNECTION_REFUSED': 'Unable to connect. Please check your internet.',
|
||||
'ERR_TIMEOUT': 'Request timed out. Please try again.',
|
||||
}
|
||||
|
||||
return messages[error.code] || 'An unexpected error occurred.'
|
||||
}
|
||||
```
|
||||
|
||||
## Comments & Documentation
|
||||
|
||||
### When to Comment
|
||||
|
||||
#### ✅ DO Comment:
|
||||
- **Why** something is done (not what)
|
||||
- Complex algorithms
|
||||
- Non-obvious decisions
|
||||
- Workarounds for bugs
|
||||
|
||||
```javascript
|
||||
// ✅ Good - Explains WHY
|
||||
// We use a 300ms debounce to avoid overwhelming the API
|
||||
// with requests while the user is still typing
|
||||
const debouncedSearch = debounce(searchProjects, 300)
|
||||
```
|
||||
|
||||
#### ❌ DON'T Comment:
|
||||
- Obvious code
|
||||
- Outdated information
|
||||
- Commented-out code (delete it instead)
|
||||
|
||||
### JSDoc for Public APIs
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* Formats a date into human-readable format
|
||||
*
|
||||
* @param {string|Date} date - The date to format
|
||||
* @param {Object} options - Formatting options
|
||||
* @returns {string} Formatted date string
|
||||
*
|
||||
* @example
|
||||
* formatDate('2026-02-02', { format: 'long' })
|
||||
* // Returns: "February 2, 2026"
|
||||
*/
|
||||
export function formatDate(date, options = {}) {
|
||||
// Implementation
|
||||
}
|
||||
```
|
||||
|
||||
## Import Order
|
||||
|
||||
```javascript
|
||||
// 1. External libraries
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
// 2. Internal modules
|
||||
import { useAuth } from '@/composables/useAuth'
|
||||
import { formatDate } from '@/utils/date'
|
||||
|
||||
// 3. Components
|
||||
import Button from '@/components/atoms/Button.vue'
|
||||
|
||||
// 4. Styles
|
||||
import './styles.css'
|
||||
```
|
||||
|
||||
## Code Review Checklist
|
||||
|
||||
### Before Submitting PR
|
||||
- ✅ Code runs without errors
|
||||
- ✅ Tests pass
|
||||
- ✅ No console errors or warnings
|
||||
- ✅ Linter passes
|
||||
- ✅ Code follows conventions
|
||||
- ✅ Complex logic is commented
|
||||
- ✅ No commented-out code
|
||||
- ✅ Mobile responsive
|
||||
- ✅ Accessibility checked
|
||||
|
||||
### What to Look For in Review
|
||||
- **Correctness**: Does it work as intended?
|
||||
- **Readability**: Is it easy to understand?
|
||||
- **Maintainability**: Can it be easily modified?
|
||||
- **Performance**: Any obvious bottlenecks?
|
||||
- **Security**: Any vulnerabilities?
|
||||
- **Testing**: Adequate test coverage?
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Guard Clauses
|
||||
|
||||
```javascript
|
||||
// ✅ Good - Early returns
|
||||
function processUser(user) {
|
||||
if (!user) return null
|
||||
if (!user.email) return null
|
||||
if (!user.isActive) return null
|
||||
|
||||
// Main logic here
|
||||
return processedUser
|
||||
}
|
||||
```
|
||||
|
||||
### Avoid Nested Ifs
|
||||
|
||||
```javascript
|
||||
// ❌ Bad
|
||||
if (user) {
|
||||
if (user.isActive) {
|
||||
if (user.hasPermission) {
|
||||
// Do something
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ Good
|
||||
if (!user) return
|
||||
if (!user.isActive) return
|
||||
if (!user.hasPermission) return
|
||||
|
||||
// Do something
|
||||
```
|
||||
|
||||
## Summary Checklist
|
||||
|
||||
### Code
|
||||
- ✅ Readable and self-documenting
|
||||
- ✅ Single responsibility
|
||||
- ✅ DRY (no repetition)
|
||||
- ✅ Meaningful names
|
||||
- ✅ Simple and clear
|
||||
|
||||
### Error Handling
|
||||
- ✅ All errors caught
|
||||
- ✅ User-friendly messages
|
||||
- ✅ Logged appropriately
|
||||
|
||||
### Documentation
|
||||
- ✅ Complex logic commented
|
||||
- ✅ Public APIs documented
|
||||
- ✅ No outdated comments
|
||||
|
||||
**Remember: Quality is not an act, it's a habit.**
|
||||
Reference in New Issue
Block a user