5.4 KiB
5.4 KiB
Data Model: YouTube Design Preview Replica
Date: 2026-01-29
Entities
PreviewMode (Enum)
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)
type ThemeMode = 'light' | 'dark';
VideoMetadata
User-customizable metadata for preview display.
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 characterschannelName: Required, 1-50 charactersduration: Required, format/^\d{1,2}:\d{2}(:\d{2})?$/viewCount: Required, non-negative integerpublishedAt: Required, valid Date, not in future
UploadedThumbnail
Represents a user-uploaded thumbnail image.
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.
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.
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.
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
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
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
};