Files
2026-01-29 21:05:41 -03:00

258 lines
5.4 KiB
Markdown

# Data Model: YouTube Design Preview Replica
**Date**: 2026-01-29
## Entities
### PreviewMode (Enum)
```typescript
type PreviewMode = 'desktop' | 'sidebar' | 'mobile';
```
| Value | Description | Thumbnail Size |
|-------|-------------|----------------|
| `desktop` | YouTube homepage/search grid layout | 360x202px |
| `sidebar` | YouTube related videos sidebar | 168x94px |
| `mobile` | YouTube mobile app full-width layout | 100% width |
### ThemeMode (Enum)
```typescript
type ThemeMode = 'light' | 'dark';
```
### VideoMetadata
User-customizable metadata for preview display.
```typescript
interface VideoMetadata {
title: string; // Video title (max 100 chars for display)
channelName: string; // Channel name
channelAvatarUrl?: string; // Optional channel avatar image URL
duration: string; // Format: "MM:SS" or "H:MM:SS"
viewCount: number; // Raw number, formatted for display
publishedAt: Date; // Used for "X days ago" calculation
}
```
**Validation Rules:**
- `title`: Required, 1-100 characters
- `channelName`: Required, 1-50 characters
- `duration`: Required, format `/^\d{1,2}:\d{2}(:\d{2})?$/`
- `viewCount`: Required, non-negative integer
- `publishedAt`: Required, valid Date, not in future
### UploadedThumbnail
Represents a user-uploaded thumbnail image.
```typescript
interface UploadedThumbnail {
id: string; // UUID
dataUrl: string; // Base64 data URL of the image
originalName: string; // Original filename
fileSize: number; // Size in bytes (max 5MB)
mimeType: string; // 'image/jpeg' | 'image/png' | 'image/webp'
width: number; // Original image width
height: number; // Original image height
uploadedAt: Date; // Timestamp
}
```
**Validation Rules:**
- `fileSize`: Max 5,242,880 bytes (5MB)
- `mimeType`: Only 'image/jpeg', 'image/png', 'image/webp'
- `width`, `height`: Positive integers
### PreviewState
Complete state for the preview tool, persisted to localStorage.
```typescript
interface PreviewState {
// Active preview configuration
currentThumbnail: UploadedThumbnail | null;
previewMode: PreviewMode;
themeMode: ThemeMode;
metadata: VideoMetadata;
// History for quick switching
recentThumbnails: UploadedThumbnail[]; // Max 10 items
// UI state
showMetadataEditor: boolean;
// Persistence metadata
lastSaved: Date;
version: number; // Schema version for migrations
}
```
### VisualTestResult
Result of Playwright visual comparison test.
```typescript
interface VisualTestResult {
testId: string;
previewMode: PreviewMode;
themeMode: ThemeMode;
capturedAt: Date;
// Comparison metrics
matchPercentage: number; // 0-100
passed: boolean; // matchPercentage >= threshold (98%)
// File references
actualScreenshotPath: string;
expectedScreenshotPath: string;
diffImagePath?: string; // Only if failed
// Error info
errorMessage?: string;
}
```
### ReferenceScreenshot
Stored YouTube reference for visual comparison.
```typescript
interface ReferenceScreenshot {
id: string;
previewMode: PreviewMode;
themeMode: ThemeMode;
capturedAt: Date;
capturedFrom: string; // YouTube URL
filePath: string;
// Metadata
viewportWidth: number;
viewportHeight: number;
browserType: string; // 'chromium' | 'firefox' | 'webkit'
// Version tracking
isActive: boolean; // Current baseline
replacedBy?: string; // ID of newer version
}
```
## Local Storage Schema
Key: `thumbpreview_state`
```typescript
interface LocalStorageSchema {
version: 1;
state: PreviewState;
}
```
**Storage Limits:**
- Total localStorage budget: ~5MB
- Each thumbnail (base64): ~1-2MB typical
- Keep max 10 recent thumbnails
- Automatic cleanup of oldest when limit reached
## State Transitions
### Thumbnail Upload Flow
```
[No Thumbnail]
|
v (user uploads file)
[Validating]
|
+-- (invalid) --> [Error: show message] --> [No Thumbnail]
|
v (valid)
[Processing]
|
v (resize/optimize if needed)
[Preview Ready]
|
v (auto-save to localStorage)
[Persisted]
```
### Preview Mode Switch
```
[Current Mode]
|
v (user selects new mode)
[Transitioning]
|
v (re-render with new layout)
[New Mode Active]
|
v (persist preference)
[Saved]
```
### Theme Mode Switch
```
[Current Theme]
|
v (user clicks toggle)
[Apply Theme Class]
|
v (CSS variables update)
[New Theme Active]
|
v (persist preference)
[Saved]
```
## Relationships
```
PreviewState
|
+-- 1:1 --> currentThumbnail (UploadedThumbnail)
|
+-- 1:N --> recentThumbnails (UploadedThumbnail[])
|
+-- 1:1 --> metadata (VideoMetadata)
|
+-- enum --> previewMode (PreviewMode)
|
+-- enum --> themeMode (ThemeMode)
VisualTestResult
|
+-- ref --> ReferenceScreenshot (expectedScreenshotPath)
|
+-- enum --> previewMode
|
+-- enum --> themeMode
```
## Default Values
```typescript
const DEFAULT_METADATA: VideoMetadata = {
title: 'Your Video Title Here',
channelName: 'Your Channel',
channelAvatarUrl: undefined,
duration: '10:30',
viewCount: 125000,
publishedAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) // 1 week ago
};
const DEFAULT_STATE: PreviewState = {
currentThumbnail: null,
previewMode: 'desktop',
themeMode: 'light',
metadata: DEFAULT_METADATA,
recentThumbnails: [],
showMetadataEditor: false,
lastSaved: new Date(),
version: 1
};
```