feature: "add share music system" expanded_at: "2025-12-18T18:07:00Z" mode: full_auto # ═══════════════════════════════════════════════════════════════ # REQUIREMENTS ANALYSIS # ═══════════════════════════════════════════════════════════════ analysis: problem_statement: | Users and artists currently have no way to share music content from Sonic Cloud with others outside the platform or to promote their work on social media. Artists cannot easily grow their audience, and users cannot recommend music to friends. target_users: primary: - Musicians/Artists wanting to promote their work - Users wanting to share favorite songs with friends - Playlist curators sharing collections secondary: - Social media users discovering shared music - External website visitors accessing shared links - Music bloggers embedding content core_value: | Enable viral music discovery by making it effortless to share songs, albums, and playlists through unique shareable links and social media integration. This creates organic growth loops where shared content brings new users to the platform. user_stories: - as: Artist want: Share my new song on Twitter so_that: I can promote my music to my followers - as: User want: Copy a link to a song so_that: I can send it to friends via messaging apps - as: Playlist Curator want: Share my curated playlist publicly so_that: Others can discover my music taste - as: Content Creator want: Get embed code for a song so_that: I can include it in my blog post - as: Artist want: See how many times my song was shared so_that: I can measure promotional effectiveness # ═══════════════════════════════════════════════════════════════ # SCOPE DEFINITION # ═══════════════════════════════════════════════════════════════ scope: mvp_features: # Core Sharing - feature: Generate shareable links for songs priority: CRITICAL complexity: LOW - feature: Generate shareable links for playlists priority: CRITICAL complexity: LOW - feature: Generate shareable links for albums priority: CRITICAL complexity: LOW - feature: Copy link to clipboard functionality priority: HIGH complexity: LOW # Social Integration - feature: Share to Twitter with pre-filled text priority: HIGH complexity: MEDIUM - feature: Share to Facebook priority: HIGH complexity: MEDIUM # UI Components - feature: ShareButton component priority: CRITICAL complexity: LOW description: Clickable button that opens share modal - feature: ShareModal component priority: CRITICAL complexity: MEDIUM description: Modal displaying share options and generated link # Landing Page - feature: Shared content landing page priority: CRITICAL complexity: MEDIUM description: Public page displaying shared song/playlist/album # Analytics - feature: Track share creation events priority: MEDIUM complexity: LOW - feature: Track share link clicks priority: MEDIUM complexity: MEDIUM future_features: # Advanced Sharing - feature: Embed player code generation priority: LOW complexity: HIGH rationale: "Nice to have but requires iframe security work" - feature: Share via WhatsApp priority: MEDIUM complexity: LOW rationale: "Popular messaging app, simple URL scheme" # Advanced Analytics - feature: Share analytics dashboard priority: LOW complexity: HIGH rationale: "Artists want metrics but complex to build well" - feature: Geographic share tracking priority: LOW complexity: MEDIUM rationale: "Interesting data but privacy concerns" # Social Features - feature: Direct message sharing within platform priority: MEDIUM complexity: HIGH rationale: "Requires building DM system first" - feature: Share to Instagram Stories priority: MEDIUM complexity: HIGH rationale: "Requires Instagram API approval" explicitly_excluded: - NFT/blockchain sharing - Paid promotion features - Affiliate link generation - Cross-platform playlist sync # ═══════════════════════════════════════════════════════════════ # DATA MODEL # ═══════════════════════════════════════════════════════════════ data_model: entities: - name: Share table_name: shares description: Represents a share action creating a unique shareable link fields: - name: id type: String constraints: "@id @default(cuid())" - name: type type: Enum values: [SONG, PLAYLIST, ALBUM] description: What type of content is being shared - name: target_id type: String description: ID of the song/playlist/album - name: token type: String constraints: "@unique" description: Unique URL-safe token for share link - name: user_id type: String constraints: "nullable" description: User who created the share (null for anonymous) - name: platform type: String constraints: "nullable" values: [twitter, facebook, clipboard, direct] description: Platform where share was initiated - name: created_at type: DateTime constraints: "@default(now())" - name: expires_at type: DateTime constraints: "nullable" description: Optional expiration for temporary shares relationships: - field: user type: User cardinality: many-to-one optional: true - field: clicks type: ShareClick[] cardinality: one-to-many - name: ShareClick table_name: share_clicks description: Tracks when someone clicks a share link fields: - name: id type: String constraints: "@id @default(cuid())" - name: share_id type: String description: Reference to the share - name: clicked_at type: DateTime constraints: "@default(now())" - name: referrer type: String constraints: "nullable" description: HTTP referrer if available - name: user_agent type: String constraints: "nullable" description: Browser user agent string - name: ip_hash type: String constraints: "nullable" description: Hashed IP for privacy-preserving analytics relationships: - field: share type: Share cardinality: many-to-one indexes: - table: shares fields: [token] type: unique - table: shares fields: [type, target_id] - table: share_clicks fields: [share_id, clicked_at] # ═══════════════════════════════════════════════════════════════ # API DESIGN # ═══════════════════════════════════════════════════════════════ api_endpoints: # Share Creation - id: api_create_song_share name: Create Song Share method: POST path: /api/share/song/:id purpose: Generate shareable link for a song authentication: optional request: path_params: - name: id type: string description: Song ID body: - name: platform type: string optional: true values: [twitter, facebook, clipboard, direct] response: success_code: 201 body: - name: share_token type: string description: Unique token for share URL - name: share_url type: string description: Full shareable URL - name: social_text type: string description: Pre-formatted text for social media errors: - code: 404 description: Song not found - code: 403 description: Song is private and user lacks permission - id: api_create_playlist_share name: Create Playlist Share method: POST path: /api/share/playlist/:id purpose: Generate shareable link for a playlist authentication: optional request: path_params: - name: id type: string description: Playlist ID body: - name: platform type: string optional: true response: success_code: 201 body: - name: share_token type: string - name: share_url type: string - name: social_text type: string errors: - code: 404 description: Playlist not found - code: 403 description: Playlist is private - id: api_create_album_share name: Create Album Share method: POST path: /api/share/album/:id purpose: Generate shareable link for an album authentication: optional request: path_params: - name: id type: string description: Album ID body: - name: platform type: string optional: true response: success_code: 201 body: - name: share_token type: string - name: share_url type: string - name: social_text type: string errors: - code: 404 description: Album not found # Share Resolution - id: api_resolve_share name: Resolve Share Token method: GET path: /api/share/:token purpose: Get shared content details and track click authentication: none request: path_params: - name: token type: string description: Share token from URL response: success_code: 200 body: - name: type type: string values: [SONG, PLAYLIST, ALBUM] - name: content type: object description: Full content object (Song/Playlist/Album) - name: share_created_at type: string format: iso8601 errors: - code: 404 description: Share token not found or expired - code: 410 description: Shared content has been deleted # Share Analytics - id: api_get_share_stats name: Get Share Statistics method: GET path: /api/share/:token/stats purpose: Get analytics for a specific share authentication: optional request: path_params: - name: token type: string response: success_code: 200 body: - name: total_clicks type: integer - name: unique_clicks type: integer description: Estimated unique visitors by IP hash - name: clicks_by_date type: array items: date: string count: integer - name: referrers type: array items: source: string count: integer errors: - code: 404 description: Share not found - id: api_get_content_shares name: Get Content Share Summary method: GET path: /api/share/summary/:type/:id purpose: Get share statistics for a song/playlist/album authentication: required authorization: Must be content owner or admin request: path_params: - name: type type: string values: [song, playlist, album] - name: id type: string description: Content ID response: success_code: 200 body: - name: total_shares type: integer - name: total_clicks type: integer - name: platforms type: object description: Breakdown by platform - name: recent_shares type: array description: Last 10 shares with timestamps # ═══════════════════════════════════════════════════════════════ # UI STRUCTURE # ═══════════════════════════════════════════════════════════════ ui_structure: pages: - id: page_share_landing name: Share Landing Page route: /s/:token purpose: Public landing page for shared content components_needed: - SharedContentHeader - AudioPlayer (for songs) - TrackList (for playlists/albums) - CallToAction (sign up prompt) features: - Display shared content with rich metadata - Play preview if allowed - Show artist/creator information - Call to action to join platform - Open Graph tags for social media previews accessibility: - Works without authentication - Mobile responsive - Fast loading with SSR - Proper meta tags for crawlers components: - id: component_share_button name: ShareButton file_path: components/ShareButton.tsx purpose: Trigger share modal from any content props: - name: type type: enum values: [song, playlist, album] required: true - name: contentId type: string required: true - name: contentTitle type: string required: true description: Used in share text - name: artistName type: string required: false description: Used in share text for songs/albums - name: variant type: enum values: [icon, text, full] default: icon description: Visual style behavior: - onClick opens ShareModal - Shows loading state during share creation - Can be used in SongCard, AlbumCard, etc. - id: component_share_modal name: ShareModal file_path: components/ShareModal.tsx purpose: Display share options and generated link props: - name: isOpen type: boolean required: true - name: onClose type: function required: true - name: shareUrl type: string required: true - name: shareText type: string required: true features: - Copy to clipboard button with feedback - Social media share buttons - Generated link display - QR code (future) - id: component_social_share_buttons name: SocialShareButtons file_path: components/SocialShareButtons.tsx purpose: Platform-specific share buttons props: - name: url type: string required: true - name: text type: string required: true - name: platforms type: array default: [twitter, facebook] behavior: - Opens platform share dialog in popup - Tracks platform in analytics - Falls back to clipboard if platform unavailable - id: component_shared_content_header name: SharedContentHeader file_path: components/SharedContentHeader.tsx purpose: Header for share landing page props: - name: type type: enum values: [song, playlist, album] - name: title type: string - name: artist type: string optional: true - name: coverUrl type: string optional: true - name: metadata type: object description: Duration, track count, etc. features: - Large cover art - Title and artist - Metadata display - Share count badge # ═══════════════════════════════════════════════════════════════ # SECURITY & AUTHORIZATION # ═══════════════════════════════════════════════════════════════ security: authentication: share_creation: optional share_access: none analytics_access: required (owner only) authorization: rules: - resource: Song action: share condition: Song is public OR user is owner OR user has access - resource: Playlist action: share condition: Playlist is public OR user is owner - resource: Album action: share condition: Album is public (albums are always public) - resource: Share Analytics action: view condition: User is content owner OR user is admin token_security: - Tokens are cryptographically random (cuid) - Tokens are URL-safe - No sequential IDs exposed - Optional expiration dates - Rate limiting on creation (10/minute per IP) privacy: - IP addresses are hashed, not stored - User agents stored for analytics only - No cross-site tracking - Respects Do Not Track header - GDPR compliant analytics # ═══════════════════════════════════════════════════════════════ # EDGE CASES & ERROR HANDLING # ═══════════════════════════════════════════════════════════════ edge_cases: - scenario: User shares private playlist detection: Check playlist.is_public flag handling: Return 403 error with message "Cannot share private playlists" - scenario: Shared content is deleted detection: Share exists but target_id has no matching record handling: Show friendly "Content no longer available" page - scenario: Share token collision (extremely rare) detection: Unique constraint violation on token handling: Retry with new token automatically - scenario: High share volume (viral content) detection: Rate limiting triggers handling: Return 429 with retry-after header - scenario: Bot traffic clicking shares detection: Suspicious user agents, high frequency handling: Track but flag as bot, don't count in "unique clicks" - scenario: Share link in iframe detection: X-Frame-Options header handling: Allow embedding from trusted domains only - scenario: Expired share token detection: expires_at < now() handling: Return 410 Gone status - scenario: User shares same content multiple times detection: Check for existing share by user_id + target handling: Reuse existing share token, update platform - scenario: Anonymous user shares content detection: No auth token in request handling: Allow, set user_id to null - scenario: Shared song is in private album detection: Song.album.is_public = false handling: Still allow sharing individual song if song.is_public = true # ═══════════════════════════════════════════════════════════════ # ACCEPTANCE CRITERIA # ═══════════════════════════════════════════════════════════════ acceptance_criteria: functional: - Given I am viewing a song, When I click the share button, Then a modal opens with share options - Given a share modal is open, When I click "Copy Link", Then the link is copied and I see confirmation - Given a share modal is open, When I click "Twitter", Then Twitter share dialog opens with pre-filled text - Given I have a share link, When I visit /s/:token, Then I see the shared content - Given I visit an expired share, When the page loads, Then I see "Content no longer available" - Given I am the song owner, When I view share stats, Then I see click counts and platforms - Given I share the same song twice, When I generate the second share, Then I get the same token non_functional: - Share link generation completes in < 500ms - Share landing page loads in < 2s on 3G - Share tokens are at least 20 characters - Share modal is keyboard accessible - Open Graph tags are present for all share pages - Analytics queries complete in < 1s security: - Cannot share private content without permission - Share tokens are unguessable - Rate limiting prevents abuse - IP addresses are hashed, not stored - Analytics are only visible to content owner # ═══════════════════════════════════════════════════════════════ # TECHNICAL CONSIDERATIONS # ═══════════════════════════════════════════════════════════════ technical_notes: performance: - Cache share tokens in Redis for fast lookup - Use database index on shares.token - Batch insert share clicks for high traffic - CDN for share landing pages monitoring: - Track share creation rate - Monitor share click patterns - Alert on unusual traffic spikes - Dashboard for viral content testing: - Unit tests for share token generation - Integration tests for share flow - E2E tests for social sharing - Load testing for viral scenarios deployment: - Feature flag for gradual rollout - A/B test share button placement - Monitor analytics database load - Plan for scale to 10k shares/day # ═══════════════════════════════════════════════════════════════ # SUCCESS METRICS # ═══════════════════════════════════════════════════════════════ success_metrics: launch_goals: - 100 shares created in first week - 500 share link clicks in first week - 10% of shared content viewers sign up - <1% error rate on share creation ongoing_kpis: - Daily active shares - Share-to-click conversion rate - Click-to-signup conversion rate - Top shared content - Platform distribution (Twitter vs Facebook vs direct) business_impact: - Increase organic user acquisition by 20% - Reduce paid marketing cost per acquisition - Increase artist retention (sharing = promotion) - Increase content discovery beyond search