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,281 @@
---
description: WCAG AA accessibility standards and patterns
alwaysApply: false
globs: **/*.{vue,html,jsx,tsx}
---
# Accessibility Standards (A11y)
## Philosophy
Accessible design is not optional. It's a fundamental requirement for building inclusive, usable applications.
**Target: WCAG AA Compliance**
## Color & Contrast
### Contrast Ratios (WCAG AA)
- **Normal text**: 4.5:1 minimum
- **Large text** (18pt+): 3:1 minimum
- **UI components**: 3:1 minimum
```html
<!-- ✅ Good - High contrast -->
<div class="bg-white text-gray-900">
Readable text with 21:1 ratio
</div>
<!-- ❌ Bad - Low contrast -->
<div class="bg-gray-300 text-gray-400">
Hard to read - only 1.5:1 ratio
</div>
```
### Don't Rely on Color Alone
```html
<!-- ✅ Good - Icon + color + text -->
<span class="text-red-500 flex items-center gap-2">
<svg class="w-4 h-4"><!-- Error icon --></svg>
Error: Invalid input
</span>
```
## Semantic HTML
### Use the Right Elements
```html
<!-- ✅ Good - Semantic -->
<header>
<nav>
<ul>
<li><a href="/">Home</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h1>Article Title</h1>
<p>Content...</p>
</article>
</main>
<!-- ❌ Bad - Divitis -->
<div class="header">
<div class="nav">...</div>
</div>
```
### Heading Hierarchy
```html
<!-- ✅ Good - Proper hierarchy -->
<h1>Page Title</h1>
<h2>Section Title</h2>
<h3>Subsection Title</h3>
```
## Keyboard Navigation
### Focus Indicators
**Always show visible focus states.**
```html
<button class="focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2">
Click Me
</button>
<input class="focus:border-primary focus:ring-2 focus:ring-primary-focus" />
```
### Skip Links
```html
<a href="#main-content" class="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:z-50">
Skip to main content
</a>
<main id="main-content">
<!-- Main content -->
</main>
```
### Test Keyboard Navigation
- Tab through entire page
- Shift+Tab to go backwards
- Enter/Space to activate buttons
- Escape to close modals/dropdowns
## ARIA (Use Sparingly)
**First rule of ARIA: Don't use ARIA if you can use semantic HTML instead.**
### ARIA Labels
```html
<!-- Button with only icon -->
<button aria-label="Close modal">
<svg><!-- X icon --></svg>
</button>
<!-- Decorative image -->
<img src="decoration.svg" alt="" aria-hidden="true" />
```
### ARIA Live Regions
```html
<!-- Announce status updates -->
<div
role="status"
aria-live="polite"
aria-atomic="true"
class="sr-only"
>
{{ statusMessage }}
</div>
```
## Forms Accessibility
### Label Every Input
```html
<!-- ✅ Good - Explicit label -->
<label for="email">Email Address</label>
<input id="email" type="email" name="email" />
<!-- ❌ Bad - No label -->
<input type="email" placeholder="Email" />
```
### Required Fields
```html
<label for="email">
Email <span class="text-red-500" aria-label="required">*</span>
</label>
<input
id="email"
type="email"
required
aria-required="true"
/>
```
### Error Messages
```html
<input
id="email"
:aria-invalid="hasError"
:aria-describedby="hasError ? 'email-error' : undefined"
/>
<div
v-if="hasError"
id="email-error"
role="alert"
class="text-red-500"
>
Please enter a valid email
</div>
```
## Touch Targets & Mobile
### Minimum Touch Target Size
**WCAG Guideline: 44x44px minimum**
```html
<!-- ✅ Good - Large enough -->
<button class="p-4">
<svg class="w-6 h-6"><!-- Icon --></svg>
</button>
<!-- ❌ Bad - Too small -->
<button class="p-1">
<svg class="w-3 h-3"><!-- Icon --></svg>
</button>
```
### Spacing Between Targets
```html
<!-- ✅ Good - Adequate spacing -->
<nav class="flex flex-col gap-6 md:gap-2">
<a href="/home" class="py-3 md:py-2">Home</a>
</nav>
```
## Motion & Animation
### Respect Prefers-Reduced-Motion
```css
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
```
## Screen Reader Support
### Alt Text for Images
```html
<!-- ✅ Informative image -->
<img src="chart.png" alt="Bar chart showing 25% revenue increase" />
<!-- ✅ Decorative image -->
<img src="decoration.svg" alt="" />
```
### Screen Reader Only Text
```css
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
```
## Accessibility Checklist
### Perceivable
- ✅ Text has sufficient contrast (4.5:1)
- ✅ Images have alt text
- ✅ Color is not the only indicator
- ✅ Content works at 200% zoom
### Operable
- ✅ All functionality keyboard accessible
- ✅ Focus indicators visible
- ✅ No keyboard traps
- ✅ Touch targets at least 44x44px
### Understandable
- ✅ Clear, simple language
- ✅ Labels for all form inputs
- ✅ Error messages are clear
- ✅ Consistent navigation
### Robust
- ✅ Semantic HTML
- ✅ Valid ARIA attributes
- ✅ Works with assistive technologies
**Remember: Accessibility is not a checklist—it's an ongoing commitment to inclusive design.**

View File

@@ -0,0 +1,69 @@
---
description: Animation timing, easing, stagger patterns, and motion design principles
alwaysApply: false
globs: **/*.{ts,tsx,js,jsx,vue,css,scss}
---
# Animation Principles & Motion Design
## Core Philosophy
Every animation should serve one of these purposes:
- **Guide Attention**: Direct user focus to important elements
- **Provide Feedback**: Confirm actions and state changes
- **Show Relationships**: Reveal spatial and hierarchical connections
- **Enhance Perception**: Make loading and transitions feel faster
- **Add Delight**: Create memorable micro-interactions
## Duration Guidelines
```javascript
const durations = {
instant: 100, // Micro-feedback (hover states)
fast: 200, // Small elements (tooltips, dropdowns)
moderate: 300, // Standard UI transitions (modals, cards)
normal: 500, // Page sections, complex components
slow: 600, // Hero animations, page transitions
};
```
## Easing Functions
- **ease-out**: 90% of entrance animations (fade in, slide in)
- **ease-in**: Exit animations (fade out, slide out)
- **ease-in-out**: Position changes, transforms
- **spring**: Playful interactions, emphasis
- **linear**: Progress bars, loading spinners
## Staggered Animation Pattern
```javascript
// Delay calculation
const staggerDelay = (index, baseDelay = 100) => index * baseDelay;
```
Guidelines:
- Delay increment: 50-150ms between items
- Max items: Limit to 6-8 visible items
- Direction: Top-to-bottom or left-to-right
## Reduced Motion Accessibility
Always respect `prefers-reduced-motion` settings:
```css
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
```
## Performance
- ✅ Animate `transform` and `opacity` only
- ✅ Use `will-change` sparingly
- ✅ Limit simultaneous animations
- ❌ Don't animate `width`, `height`, `top`, `left`

View 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.**

View File

@@ -0,0 +1,79 @@
---
description: Component composition patterns and architecture principles
alwaysApply: false
globs: **/*.{ts,tsx,js,jsx,vue,svelte}
---
# Component Architecture & Composition Patterns
## Core Philosophy
**Composition Over Configuration**
Build complex UIs from simple, focused components that compose well together.
### Key Tenets
- **Single Responsibility**: Each component does one thing well
- **Composition Slots**: Use children/slots instead of complex prop APIs
- **Default Props**: Provide sensible defaults for easy use
- **Prop Interfaces**: Clear contracts with TypeScript/PropTypes
- **Minimal State**: Keep component state local and minimal
## Anti-patterns to Avoid
- ❌ God components that do everything
- ❌ Prop drilling through many layers
- ❌ Hard-coded values instead of props
- ❌ Component logic mixed with layout
- ❌ Tight coupling between components
## Template Pattern
Create base templates that handle common layouts and let content be injected.
```jsx
const PageTemplate = ({ title, children }) => (
<div className="page-container">
<Header />
<main className="page-content">
{title && <h1>{title}</h1>}
{children}
</main>
<Footer />
</div>
);
```
## Container/Presenter Pattern
Split components into smart (containers) and dumb (presenters) components.
- **Container**: Handles data and logic
- **Presenter**: Pure presentation, receives data via props
## Prop Interface Design
```typescript
interface BaseComponentProps {
className?: string;
children?: React.ReactNode;
testId?: string;
}
interface ButtonProps extends BaseComponentProps {
variant?: 'primary' | 'secondary' | 'ghost';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
loading?: boolean;
onClick?: (event: React.MouseEvent) => void;
}
```
### Prop Naming Conventions
- Boolean props: `isOpen`, `hasError`, `disabled`
- Handler props: `onClick`, `onClose`, `onChange`
- Render props: `renderHeader`, `renderItem`
- Data props: `items`, `data`, `value`
- Config props: `variant`, `size`, `theme`

View File

@@ -0,0 +1,172 @@
---
description: Git workflow and commit message conventions
alwaysApply: false
globs: .git/**
---
# Git Workflow & Version Control
## Commit Message Format
```
<type>(<scope>): <subject>
<body>
<footer>
```
### Types
- **feat**: New feature
- **fix**: Bug fix
- **docs**: Documentation only
- **style**: Code style (formatting)
- **refactor**: Code restructuring
- **perf**: Performance improvement
- **test**: Adding tests
- **chore**: Build process, dependencies
### Examples
```bash
# ✅ Good commit messages
feat(auth): add password reset functionality
fix(button): resolve hover state in dark mode
docs(readme): update installation instructions
refactor(utils): extract date formatting logic
perf(images): lazy load project thumbnails
# ❌ Bad commit messages
fix bug
update stuff
changes
WIP
```
## Branching Strategy
### Branch Naming
```
<type>/<short-description>
Examples:
feature/user-authentication
fix/mobile-navigation-bug
refactor/theme-system
docs/api-documentation
```
## Feature Development Workflow
```bash
# 1. Start from main
git checkout main
git pull origin main
# 2. Create feature branch
git checkout -b feature/user-profile
# 3. Make changes and commit
git add src/components/UserProfile.vue
git commit -m "feat(profile): add user profile component"
# 4. Push branch
git push -u origin feature/user-profile
# 5. Create Pull Request
```
## Pull Request Guidelines
### PR Title Format
```
<type>(<scope>): <description>
Examples:
feat(theme): add dark mode toggle
fix(navigation): resolve mobile menu closing issue
```
### PR Checklist
- ✅ Code follows project conventions
- ✅ Tests added/updated
- ✅ Documentation updated
- ✅ No merge conflicts
- ✅ CI/CD passes
- ✅ Mobile responsive
- ✅ Accessibility checked
## Code Review Process
### As a Reviewer
- **Be kind and constructive**
- **Explain why, not just what**
- **Ask questions, don't make demands**
- **Praise good work**
```markdown
<!-- ❌ Bad review comment -->
This is wrong.
<!-- ✅ Good review comment -->
This approach might cause performance issues with large datasets.
Consider using pagination instead. What do you think?
```
## Useful Git Commands
### Daily Commands
```bash
# Check status
git status
# View changes
git diff
# View commit history
git log --oneline --graph --all
# Stash changes
git stash
# Apply stash
git stash pop
```
### Undoing Changes
```bash
# Discard changes to file
git restore src/App.vue
# Unstage file
git restore --staged src/App.vue
# Undo last commit, keep changes
git reset --soft HEAD~1
```
## Git Best Practices Summary
### Commits
- ✅ Small, focused commits
- ✅ Clear, descriptive messages
- ✅ Commit often
- ✅ One logical change per commit
### Branches
- ✅ Descriptive branch names
- ✅ Keep branches short-lived
- ✅ Delete merged branches
- ✅ Pull frequently
### Pull Requests
- ✅ Clear title and description
- ✅ Link to relevant issues
- ✅ Request reviews
- ✅ Address feedback promptly
**Remember: Git is a tool for collaboration. Use it to make your team more effective.**

View File

@@ -0,0 +1,109 @@
---
description: Core front-end development philosophy and principles
alwaysApply: true
---
# Master Front-End Development Philosophy
## Core Mission
Build the best front-end code ever made by combining modern frameworks, utility-first CSS, systematic design thinking, and flawless execution.
## Philosophical Pillars
### 1. Mobile-First, Everywhere-Perfect
- Every component works flawlessly on mobile, tablet, and desktop
- Mobile is the foundation, not an afterthought
- Touch targets, viewport management, and safe areas are first-class citizens
### 2. Consistency is Sacred
- Mobile and desktop versions show **identical content and functionality** unless explicitly designed otherwise
- Design tokens ensure visual consistency across all breakpoints
- User experience never diverges accidentally between screen sizes
**Verification Before Shipping:**
- ✅ Same navigation items on mobile and desktop
- ✅ Same content sections visible
- ✅ Same buttons and CTAs available
- ✅ Only layout and presentation differ
### 3. Theme-First Architecture
- Applications are built with theming as a core architectural decision from day one
- Themes are CSS-based with reactive state management
- Dark mode and light mode are equals, not primary/secondary
**CRITICAL THEME RULE**: Header, sidebar, and main background must use the same fill color.
### 4. Utility-First, Component-Second
- Tailwind CSS utilities in templates for maximum flexibility
- Component classes only for truly reusable patterns
- Extract components when you repeat, not before
### 5. Performance as a Feature
- **Bundle Size**: < 200KB gzipped
- **LCP**: < 2.5s
- **FID**: < 100ms
- CSS transforms for GPU acceleration
- Lazy loading and code splitting by default
### 6. Design System as Foundation
- Typography scale, spacing scale, and color palettes defined upfront
- **4px base grid system** for mathematical harmony
- Consistent component patterns documented
### 7. Accessibility is Non-Negotiable
- **WCAG AA compliance minimum**
- Keyboard navigation works everywhere
- Screen reader friendly
- **4.5:1 contrast ratio** for normal text
- **44x44px minimum touch targets**
### 8. Real Users, Real Devices
- Test on actual phones and tablets
- Consider network conditions (3G, 4G, WiFi)
- Handle offline states gracefully
- Progressive enhancement over graceful degradation
## Success Metrics
### Code Quality
- ✅ Can a new developer understand the codebase in under 1 hour?
- ✅ Does the app work perfectly on a 5-year-old phone?
- ✅ Is mobile/desktop consistency maintained automatically?
### User Experience
- ✅ Does it feel native on every device?
- ✅ Does the interface respond instantly to user input?
- ✅ Load in under 2s on desktop, under 5s on mobile 3G
## Anti-Patterns to Avoid
### ❌ Desktop-First Thinking
Never build desktop first and "make it responsive later"
### ❌ Inconsistent Experiences
Mobile users should never get a degraded experience
### ❌ Hardcoded Values
Use design tokens, variables, and systematic scales
### ❌ Ignoring Performance
Every kilobyte matters, every millisecond counts
### ❌ Accessibility as Afterthought
Build accessible from day one, not as a retrofit
### ❌ Skipping Documentation
Code without documentation is technical debt
## The Ultimate Goal
**When someone uses your application:**
- "This feels incredibly polished"
- "Everything just works"
- "This looks beautiful on my device"
**When a developer reads your code:**
- "This is so well organized"
- "I understand exactly what's happening"
- "Adding features will be straightforward"

View File

@@ -0,0 +1,118 @@
---
description: Mobile-first UX patterns and touch interaction design
alwaysApply: false
globs: **/*.{ts,tsx,js,jsx,vue,css,scss}
---
# Mobile UX Patterns & Touch Interactions
## Mobile-First Philosophy
Start with mobile constraints, then progressively enhance for larger screens.
### Design Process
1. **Mobile (320-480px)**: Core functionality only
2. **Tablet (768-1024px)**: Add supporting features
3. **Desktop (1280px+)**: Enhanced experience
## Touch Target Sizing
### Minimum 44x44px Touch Targets
```css
.touch-target {
min-width: 44px;
min-height: 44px;
/* Apple HIG recommendation */
}
.touch-target-optimal {
min-width: 48px;
min-height: 48px;
/* Material Design recommendation */
}
```
### Spacing Between Targets
```css
.button-group {
display: flex;
gap: 16px; /* Comfortable spacing */
}
```
## Thumb-Friendly Zones
```
┌─────────────────┐
│ Hard to reach │ ← Top 20%
├─────────────────┤
│ Easy reach │ ← Middle 60%
├─────────────────┤
│ Natural thumb │ ← Bottom 20%
│ zone │ (place primary actions here)
└─────────────────┘
```
Primary actions should be placed in the bottom 20% for one-handed use.
## Dynamic Viewport Height
```css
/* Use dvh instead of vh for mobile */
.hero {
height: 100dvh; /* Dynamic viewport height */
}
/* Fallback for older browsers */
.hero {
height: 100vh;
height: 100dvh;
}
```
## Safe Area Insets (iOS)
```css
.header {
padding-top: env(safe-area-inset-top);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
.footer {
padding-bottom: env(safe-area-inset-bottom);
}
```
## Form Input Optimization
```html
<!-- Use correct input types for mobile keyboards -->
<input type="email" inputmode="email">
<input type="number" inputmode="numeric">
<input type="tel" inputmode="tel">
<input type="url" inputmode="url">
```
```css
/* Prevent iOS zoom on focus */
input, select, textarea {
font-size: 16px; /* Minimum to prevent zoom */
}
```
## Touch Feedback
```css
.button {
transition: transform 0.1s ease, opacity 0.1s ease;
}
.button:active {
transform: scale(0.95);
opacity: 0.8;
}
```

View File

@@ -0,0 +1,224 @@
---
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.**

View File

@@ -0,0 +1,183 @@
---
description: Quick reference for common patterns and commands
alwaysApply: false
globs: **/*.{vue,js,ts,html}
---
# Quick Reference Guide
## Vue 3 Composition API Template
```vue
<template>
<div>{{ message }}</div>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
// Props
const props = defineProps({
title: String
})
// Emits
const emit = defineEmits(['update'])
// State
const message = ref('Hello')
// Computed
const displayMessage = computed(() => message.value.toUpperCase())
// Methods
const handleClick = () => {
emit('update', { value: message.value })
}
// Lifecycle
onMounted(() => {
console.log('Component mounted')
})
</script>
```
## Tailwind Quick Classes
### Layout
```html
<div class="flex items-center justify-between gap-4">
<div class="grid grid-cols-3 gap-6">
<div class="max-w-7xl mx-auto px-4">
```
### Spacing (4px grid)
```html
<div class="p-4"> <!-- 16px all sides -->
<div class="px-6 py-3"> <!-- 24px H, 12px V -->
<div class="mb-6"> <!-- 24px bottom -->
```
### Typography
```html
<p class="text-sm"> <!-- 14px -->
<p class="text-base"> <!-- 16px -->
<p class="text-xl"> <!-- 20px -->
<p class="font-semibold"> <!-- 600 -->
<p class="font-bold"> <!-- 700 -->
```
### Responsive
```html
<div class="text-base md:text-lg lg:text-xl">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
<div class="hidden md:block"> <!-- Desktop only -->
<div class="block md:hidden"> <!-- Mobile only -->
```
## Common Component Patterns
### Button
```html
<button class="px-6 py-3 bg-primary text-white rounded-lg font-semibold
hover:bg-primary-dark transition-colors">
Click Me
</button>
```
### Input
```html
<input
type="text"
class="w-full px-4 py-2.5 border border-gray-300 rounded-lg
focus:border-primary focus:ring-2 focus:ring-primary-focus"
/>
```
### Card
```html
<div class="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow">
<h3 class="text-xl font-semibold mb-2">Title</h3>
<p class="text-gray-600">Content</p>
</div>
```
## Error Handling Pattern
```javascript
async function fetchData() {
const error = ref(null)
const isLoading = ref(true)
const data = ref(null)
try {
const response = await fetch('/api/data')
if (!response.ok) throw new Error(`HTTP ${response.status}`)
data.value = await response.json()
} catch (err) {
error.value = err.message
} finally {
isLoading.value = false
}
return { data, error, isLoading }
}
```
## Git Commands
```bash
# Daily workflow
git status
git checkout -b feature/new-feature
git add .
git commit -m "feat: add feature"
git push origin feature/new-feature
# Undo changes
git restore .
# Stash
git stash
git stash pop
```
## Performance Targets
```
LCP (Largest Contentful Paint): < 2.5s
FID (First Input Delay): < 100ms
CLS (Cumulative Layout Shift): < 0.1
Bundle Size: < 200KB gzipped
```
## Accessibility Quick Checks
- [ ] Images have alt text
- [ ] Color contrast ≥ 4.5:1
- [ ] Keyboard navigation works
- [ ] Focus indicators visible
- [ ] Form labels present
- [ ] Touch targets ≥ 44x44px
## Responsive Breakpoints
```
sm: 640px // Tablet
md: 768px // Desktop
lg: 1024px // Large
xl: 1280px // XL
```
## Common Regex Patterns
```javascript
// Email
/^[^\s@]+@[^\s@]+\.[^\s@]+$/
// URL
/^https?:\/\/.+/
// Hex color
/^#[0-9A-Fa-f]{6}$/
```

View File

@@ -0,0 +1,111 @@
---
description: Scroll behavior and navigation patterns
alwaysApply: false
globs: **/*.{ts,tsx,js,jsx,vue,css,scss}
---
# Scroll & Navigation Patterns
## Scroll Philosophy
**Default to Natural Scrolling**
Natural, uncontrolled scrolling should be your default. Only implement controlled scroll behaviors when they serve a clear purpose.
### When to Control Scroll
- ✅ Full-page sections (snap scrolling) - ONLY for portfolios/showcases
- ✅ Carousels and galleries
- ✅ Onboarding flows
- ✅ Modal/overlay open states
### When to Allow Natural Scroll (Most Cases)
- ✅ Long-form content
- ✅ Blog posts and articles
- ✅ List views
- ✅ Traditional navigation
- ✅ E-commerce sites
- ✅ Documentation
- ✅ Applications and dashboards
## Snap Scrolling (Use Sparingly)
**⚠️ CAVEAT**: Snap scrolling is NOT always appropriate. Use only for specific cases like portfolios and presentations.
```css
/* Container with snap behavior */
html {
scroll-snap-type: y mandatory;
scroll-padding-top: 4rem;
}
.snap-section {
scroll-snap-align: start;
scroll-snap-stop: always;
min-height: 100vh;
min-height: 100dvh;
}
```
## Smooth Scrolling
```css
html {
scroll-behavior: smooth;
}
/* Respect user preferences */
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
}
```
## Scroll Lock (Modal Open)
```javascript
const lockScroll = () => {
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
document.body.style.overflow = 'hidden';
document.body.style.paddingRight = `${scrollbarWidth}px`;
};
const unlockScroll = () => {
document.body.style.overflow = '';
document.body.style.paddingRight = '';
};
```
## Scroll Position Persistence
```javascript
// Save before navigation
const saveScrollPosition = () => {
sessionStorage.setItem('scrollPosition', window.scrollY.toString());
};
// Restore on page load
const restoreScrollPosition = () => {
const savedPosition = sessionStorage.getItem('scrollPosition');
if (savedPosition) {
window.scrollTo(0, parseInt(savedPosition, 10));
sessionStorage.removeItem('scrollPosition');
}
};
```
## Overscroll Behavior
```css
/* Disable bounce on body */
body {
overscroll-behavior: none;
}
/* Contain overscroll to element */
.modal {
overscroll-behavior: contain;
}
```

View File

@@ -0,0 +1,112 @@
---
description: SEO optimization and social meta tag strategy
alwaysApply: false
globs: **/*.{html,tsx,jsx,vue,astro}
---
# SEO & Meta Tag Strategy
## Core Philosophy
SEO combines three pillars:
1. **Content SEO**: Quality, relevance, keywords
2. **Technical SEO**: Structure, performance, crawlability
3. **Social SEO**: Open Graph, Twitter Cards, sharing optimization
## Page Title Optimization
**Formula**: `[Primary Keyword] - [Secondary Keyword] | [Brand Name]`
**Guidelines**:
- Optimal: 50-60 characters
- Maximum: 70 characters
- Mobile: 55 characters
```html
<title>Bitcoin UX Design - Lightning Network Development | PROUX</title>
```
## Meta Descriptions
**Formula**: `[Hook/Benefit] + [Key Details] + [Call-to-Action]`
**Guidelines**:
- Optimal: 150-160 characters
- Mobile: 120 characters
- Minimum: 120 characters
```html
<meta name="description" content="Transform your Bitcoin app's UX. 10+ years designing for Lightning Network. 98% user satisfaction. Explore projects →">
```
## Open Graph Tags
**Essential OG Tags**:
```html
<meta property="og:title" content="Page Title">
<meta property="og:description" content="Description">
<meta property="og:image" content="https://example.com/og-image.png">
<meta property="og:url" content="https://example.com/page">
<meta property="og:type" content="website">
<meta property="og:site_name" content="Brand">
```
### OG Image Specifications
- Dimensions: 1200x630px (1.91:1 ratio)
- Format: PNG or JPG
- File Size: < 5MB (ideally < 300KB)
- Safe Zone: Keep text/logos in center 1200x600px
## Twitter Card Tags
```html
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@yourusername">
<meta name="twitter:title" content="Page Title">
<meta name="twitter:description" content="Description">
<meta name="twitter:image" content="https://example.com/image.jpg">
```
## Structured Data (Schema.org)
```html
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Company Name",
"description": "Company description",
"url": "https://example.com",
"logo": "https://example.com/logo.png"
}
</script>
```
## Canonical URLs
```html
<link rel="canonical" href="https://example.com/page">
```
Use canonical URLs to:
- Prevent duplicate content issues
- Handle URL parameters
- Indicate preferred URL version
## Performance for SEO
Core Web Vitals affect rankings:
- **LCP** (Largest Contentful Paint): < 2.5s
- **FID** (First Input Delay): < 100ms
- **CLS** (Cumulative Layout Shift): < 0.1
```html
<!-- Preload critical resources -->
<link rel="preload" href="hero.jpg" as="image">
<link rel="preload" href="font.woff2" as="font" crossorigin>
<!-- Lazy load images -->
<img src="image.jpg" loading="lazy" alt="Description">
```

View File

@@ -0,0 +1,156 @@
---
description: Tailwind CSS utility-first design system patterns
alwaysApply: false
globs: **/*.{vue,html,jsx,tsx}
---
# Tailwind CSS Mastery
## Core Principles
### 1. Embrace Utility Classes
Don't fight against utilities - they're your superpower.
### 2. Extract Components When You Repeat
Create component classes only after repeating a pattern **3+ times**.
### 3. Mobile-First Responsive Design
Always start mobile, progressively enhance for larger screens.
```html
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<!-- Content scales beautifully -->
</div>
```
### 4. Use Design Tokens
Extend Tailwind's config with your design system.
```javascript
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
primary: {
DEFAULT: '#606060',
light: '#808080',
dark: '#404040',
},
},
}
}
}
```
## Spacing System (4px Grid)
**The 4px Base Grid Rule**: All spacing follows a 4px base grid for mathematical harmony.
```
4px = p-1, m-1, gap-1
8px = p-2, m-2, gap-2
16px = p-4, m-4, gap-4
24px = p-6, m-6, gap-6
32px = p-8, m-8, gap-8
```
## Responsive Breakpoints
```javascript
sm: 640px // Mobile landscape
md: 768px // Tablets
lg: 1024px // Desktop
xl: 1280px // Large desktop
```
### Mobile-First Pattern
```html
<!-- Base = Mobile, then enhance -->
<div class="text-base md:text-lg lg:text-xl">
<!-- 16px → 18px → 20px -->
</div>
<div class="p-4 md:p-6 lg:p-8">
<!-- 16px → 24px → 32px padding -->
</div>
```
## Component Patterns
### Buttons
```html
<!-- Primary -->
<button class="px-6 py-3 bg-primary text-white rounded-lg font-semibold
hover:bg-primary-dark transition-colors duration-200
focus:outline-none focus:ring-2 focus:ring-primary-focus">
Primary Action
</button>
<!-- Secondary -->
<button class="px-6 py-3 border-2 border-primary text-primary rounded-lg
hover:bg-primary hover:text-white transition-all">
Secondary Action
</button>
```
### Cards
```html
<div class="bg-white rounded-lg shadow-md p-6 mb-6
hover:shadow-lg transition-shadow duration-300">
<h3 class="text-xl font-semibold mb-2">Card Title</h3>
<p class="text-gray-600">Content</p>
</div>
```
### Form Elements
```html
<input
type="text"
class="w-full px-4 py-2.5 border border-gray-300 rounded-lg
focus:border-primary focus:ring-2 focus:ring-primary-focus
transition-colors"
placeholder="Enter text"
/>
```
## Color Contrast for Accessibility
Always ensure **4.5:1 contrast ratio** minimum (WCAG AA).
```html
<!-- Good - High contrast -->
<p class="text-gray-900 bg-white">Dark text on light</p>
<!-- Bad - Low contrast (avoid) -->
<p class="text-gray-400 bg-gray-300">Hard to read!</p>
```
## Custom Component Classes
Only extract after 3+ repetitions:
```css
@layer components {
.btn-primary {
@apply px-6 py-3 bg-primary text-white rounded-lg font-semibold;
@apply hover:bg-primary-dark transition-colors duration-200;
@apply focus:outline-none focus:ring-2 focus:ring-primary-focus;
}
}
```
## Summary Checklist
- ✅ Start mobile-first, enhance for larger screens
- ✅ Use design tokens (extend Tailwind config)
- ✅ Follow 4px spacing grid
- ✅ Extract components after 3+ repetitions
- ✅ Keep utility classes in HTML
- ✅ Ensure color contrast for accessibility
- ✅ Use transitions for smooth interactions
- ✅ Configure PurgeCSS for production

View File

@@ -0,0 +1,152 @@
---
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

View File

@@ -0,0 +1,166 @@
---
description:
alwaysApply: true
---
# Visual Design System Principles
## Typography Philosophy
### Bold, Statement Typography
Large, confident typography that dominates visual hierarchy. Text is a design element, not just content.
**Scale Guidelines**:
- Hero Text: 6-9rem (96-144px)
- Page Titles: 3-4rem (48-64px)
- Section Headers: 2-3rem (32-48px)
- Body Text: 1-1.125rem (16-18px)
- Small Text: 0.875rem (14px)
```css
.hero-text {
font-size: clamp(4rem, 10vw, 9rem);
font-weight: 700;
line-height: 1.1;
}
```
## Gradient-Based Visual Hierarchy
Use gradients strategically to create visual interest without clutter.
```css
/* Text gradient */
.gradient-heading {
background: linear-gradient(to right, #ffffff, #9ca3af);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
```
## Glass Morphism
Create depth through semi-transparent layers with backdrop blur.
```css
.glass-card {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
```
### Usage Guidelines
- ✅ Cards and containers over complex backgrounds
- ✅ Navigation bars with fixed positioning
- ✅ Modal overlays and dialogs
- ❌ Body text containers (readability issues)
- ❌ Form inputs (confusing UX)
## Color System Architecture
**Semantic Color Tokens** - Define colors by purpose, not appearance:
```javascript
const colors = {
brand: {
primary: '#F7931A',
secondary: '#8E44AD',
},
neutral: {
50: '#FAFAFA',
900: '#171717',
},
semantic: {
success: '#22C55E',
error: '#EF4444',
},
};
```
## Shadow & Glow Systems
Use shadows sparingly for depth perception:
```css
.shadow-card {
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
.glow-on-hover:hover {
box-shadow: 0 0 20px rgba(255, 255, 255, 0.1);
}
```
## Spacing System
**8px Base Grid** - All spacing follows 8px increments:
```javascript
const spacing = {
1: '0.25rem', // 4px
2: '0.5rem', // 8px
4: '1rem', // 16px
8: '2rem', // 32px
16: '4rem', // 64px
32: '8rem', // 128px
};
```
## Border Radius System
```css
rounded-lg /* 8px - buttons */
rounded-2xl /* 16px - cards */
rounded-3xl /* 24px - modals */
rounded-full /* 9999px - circles/pills */
```
## Responsive Breakpoints
Mobile-first progressive enhancement:
```javascript
const breakpoints = {
sm: '640px', // Mobile landscape
md: '768px', // Tablets
lg: '1024px', // Laptop
xl: '1280px', // Desktop
};
```
## Dark Mode
Design with both modes from the start:
```css
:root {
--bg-primary: #ffffff;
--text-primary: #171717;
}
[data-theme="dark"] {
--bg-primary: #171717;
--text-primary: #fafafa;
}
```
## Hover State Patterns
All interactive elements provide immediate feedback:
```css
.interactive {
transition: all 0.3s ease;
}
.interactive:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
}
```

View File

@@ -0,0 +1,200 @@
---
description: Vue 3 Composition API conventions and best practices
alwaysApply: false
globs: **/*.vue
---
# Vue.js Conventions & Best Practices
## Component Architecture
### Use Composition API with `<script setup>`
```vue
<script setup>
import { ref, computed, onMounted } from 'vue'
// Props
const props = defineProps({
userId: {
type: String,
required: true
}
})
// State
const user = ref(null)
const isLoading = ref(false)
// Computed
const displayName = computed(() => {
return user.value ? `${user.value.firstName} ${user.value.lastName}` : ''
})
// Methods
const fetchUser = async () => {
isLoading.value = true
try {
// Fetch logic
} finally {
isLoading.value = false
}
}
// Lifecycle
onMounted(() => {
fetchUser()
})
</script>
```
### Component Organization Order
1. **Imports** - External, then internal
2. **Props** - TypeScript-style validation
3. **Emits** - Explicitly defined
4. **State** (refs and reactive)
5. **Computed** - Derived values
6. **Watchers** - Side effects
7. **Methods** - Business logic
8. **Lifecycle hooks** - Ordered by execution
9. **Expose** - Public API (if needed)
## Props Best Practices
### Always Validate Props
```javascript
defineProps({
title: {
type: String,
required: true,
validator: (value) => value.length > 0
},
status: {
type: String,
default: 'pending',
validator: (value) => ['pending', 'active', 'complete'].includes(value)
}
})
```
### Prop Naming
- Use descriptive names: `isLoading` not `loading`
- Boolean props: `is`, `has`, `can`, `should`
- Avoid abbreviations: `projectData` not `projData`
## Reactive State
### When to Use ref vs reactive
**Use `ref` for:**
- Primitives (string, number, boolean)
- Single values
- When you need `.value` explicit access
**Use `reactive` for:**
- Objects with multiple properties
- Complex nested data structures
## Event Handling
### Define Emits Explicitly
```javascript
const emit = defineEmits(['update', 'delete', 'close'])
const handleUpdate = () => {
emit('update', { id: 1, name: 'Updated' })
}
```
## Template Best Practices
### Keep Templates Clean
```vue
<!-- Good - Logic in script -->
<template>
<div class="project-card" :class="cardClasses">
<h3>{{ project.title }}</h3>
<p v-if="hasDescription">{{ project.description }}</p>
</div>
</template>
<script setup>
const cardClasses = computed(() => ({
'is-featured': project.featured,
'is-complete': project.status === 'complete'
}))
const hasDescription = computed(() => {
return project.description && project.description.length > 0
})
</script>
```
## Performance Optimization
### Lazy Loading Components
```javascript
// Router lazy loading
const ProjectDetail = () => import('@/pages/ProjectDetail.vue')
// Component lazy loading
const HeavyChart = defineAsyncComponent(() =>
import('@/components/HeavyChart.vue')
)
```
### 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])
```
## Common Pitfalls to Avoid
### ❌ Mutating Props
Never mutate props directly - emit events instead
### ❌ Forgetting .value in script
```javascript
const count = ref(0)
if (count.value === 0) { } // ✅ Correct
```
### ❌ Creating Objects in Template
```vue
<!-- Bad - Creates new object every render -->
<Child :config="{ theme: 'dark' }" />
<!-- Good - Stable reference -->
<script setup>
const config = { theme: 'dark' }
</script>
<Child :config="config" />
```
## Summary Checklist
- ✅ Use Composition API with `<script setup>`
- ✅ Validate all props with types and defaults
- ✅ Define emits explicitly
- ✅ Keep templates clean - move logic to script
- ✅ Use computed for derived state
- ✅ Always provide `:key` for lists
- ✅ Handle errors gracefully
- ✅ Lazy load heavy components
- ✅ Never mutate props
- ✅ Remember `.value` for refs in script