Update PRDs

This commit is contained in:
Justin Edmund 2025-06-11 22:49:56 -07:00
parent d44bcbb80e
commit af7122a7f6
2 changed files with 532 additions and 0 deletions

View file

@ -0,0 +1,283 @@
# Product Requirements Document: Apple Music Integration
## Overview
Integrate Apple Music API to enhance the music features on jedmund.com by replacing the current iTunes Search API with the full Apple Music API. This will provide higher quality artwork and 30-second preview clips immediately, while fetching and storing richer metadata for future UI enhancements. The initial implementation will maintain the current UI design with minimal changes.
## Current State
- **Last.fm Integration**: Fetches recent listening history (10 albums)
- **iTunes Search API**: Enhances album artwork (600x600 resolution)
- **Display**: Shows albums on homepage with basic metadata
- **Limitations**: Low-res artwork, no previews, limited metadata
## Goals
### Primary Goals
- **Replace iTunes Search API** with Apple Music API for better data quality
- **Add 30-second preview playback** for discovered music
- **Fetch and store enhanced metadata** (genres, release dates, track listings) for future use
- **Improve artwork quality** from 600x600 to 3000x3000 resolution
### Secondary Goals
- **Implement proper caching** using Redis (matching other API patterns)
- **Create reusable audio components** for future music features
- **Maintain current UI** while preparing data structure for future enhancements
- **Prepare foundation** for future user library integration
### Technical Goals
- Secure JWT token generation and management
- Efficient API response caching
- Clean component architecture for audio playback
- Type-safe Apple Music API integration
## Success Metrics
- Successfully replace all iTunes Search API calls
- Zero increase in page load time despite fetching more data
- Functional audio previews with smooth playback
- Higher quality artwork displayed throughout site
- Enhanced metadata properly cached and ready for future use
## Implementation Phases
### Phase 1: Foundation Setup (Week 1)
#### JWT Authentication & Configuration
- [ ] Install required dependencies (`jsonwebtoken`, `node-fetch`)
- [ ] Create `/src/lib/server/apple-music-auth.ts` for JWT generation
- [ ] Port Deno JWT code to Node.js environment
- [ ] Implement token caching mechanism (6-month expiry)
- [ ] Add environment variables to `.env.example`:
- `APPLE_MUSIC_TEAM_ID`
- `APPLE_MUSIC_KEY_ID`
- `APPLE_MUSIC_PRIVATE_KEY_PATH`
- [ ] Create secure storage solution for .p8 private key file
- [ ] Add environment validation in server startup
#### Type Definitions & Interfaces
- [ ] Create `/src/lib/types/apple-music.ts` with interfaces for:
- `AppleMusicAlbum`
- `AppleMusicTrack`
- `AppleMusicArtwork`
- `AppleMusicPreview`
- `AppleMusicSearchResponse`
- [ ] Extend existing `Album` type to include Apple Music fields
- [ ] Create type guards for API response validation
- [ ] Document all new interfaces with JSDoc comments
### Phase 2: API Integration (Week 1-2)
#### Apple Music API Client
- [ ] Create `/src/lib/server/apple-music-client.ts` with methods:
- `searchAlbums(query: string, limit?: number)`
- `getAlbum(id: string)`
- `getAlbumTracks(id: string)`
- `searchTracks(query: string, limit?: number)`
- [ ] Implement proper error handling and retry logic
- [ ] Add request rate limiting (Apple Music allows 3000/hour)
- [ ] Create response transformation utilities
#### Replace iTunes Search Integration
- [ ] Backup current `/src/routes/api/lastfm/+server.ts`
- [ ] Remove `node-itunes-search` dependency
- [ ] Update `addItunesArtToAlbums` to use Apple Music API
- [ ] Fetch full album metadata but only expose artwork and preview URLs initially
- [ ] Store enhanced metadata in response for future use
- [ ] Maintain existing response structure for UI compatibility
- [ ] Add fallback to Last.fm images if Apple Music fails
- [ ] Test with various album/artist combinations
#### Caching Layer
- [ ] Extend Redis client usage to Apple Music responses
- [ ] Implement cache keys: `apple:album:{id}`, `apple:search:{query}`
- [ ] Set TTL to 24 hours for catalog data
- [ ] Add cache warming for popular albums
- [ ] Create cache invalidation utilities
- [ ] Monitor cache hit rates
### Phase 3: Frontend Enhancement (Week 2-3)
#### Audio Preview Component
- [ ] Create `/src/lib/components/MusicPreview.svelte` with:
- Play/pause toggle button
- Progress bar (30-second duration)
- Volume control
- Loading state
- Error handling
- [ ] Implement keyboard controls (space for play/pause)
- [ ] Add accessibility labels and ARIA attributes
- [ ] Create smooth fade in/out for previews
- [ ] Handle multiple preview instances (pause others when playing)
#### Enhanced Album Component
- [ ] Update `/src/lib/components/Album.svelte` to:
- Use high-resolution artwork (with lazy loading)
- Add "Preview" button (if preview URL available)
- Keep all other UI elements unchanged
- [ ] Store enhanced metadata in component props for future use
- [ ] Implement progressive image loading (blur-up technique)
- [ ] Add error states for missing preview URLs
- [ ] Optimize preview button for mobile touch interactions
#### Homepage Integration
- [ ] Update music section data fetching
- [ ] Add preview player controls to album grid
- [ ] Implement smooth transitions between previews
- [ ] Add loading states during API calls
- [ ] Test cross-browser audio compatibility
### Phase 4: Testing & Optimization (Week 3)
#### Performance Optimization
- [ ] Implement image optimization pipeline for artwork
- [ ] Add WebP format support with fallbacks
- [ ] Lazy load audio preview components
- [ ] Minimize Apple Music API calls
- [ ] Profile and optimize render performance
#### Testing
- [ ] Unit tests for Apple Music client
- [ ] Integration tests for API endpoints
- [ ] Component tests for MusicPreview
- [ ] E2E tests for preview playback flow
- [ ] Cross-browser testing (Safari, Chrome, Firefox)
- [ ] Mobile device testing
#### Documentation
- [ ] Update README with Apple Music setup instructions
- [ ] Document all new environment variables
- [ ] Create component usage examples
- [ ] Add troubleshooting guide
- [ ] Document API rate limits and caching strategy
### Phase 5: Future Enhancements (Post-Launch)
#### User Library Integration
- [ ] Research Apple Music OAuth requirements
- [ ] Design user authentication flow
- [ ] Create library sync endpoints
- [ ] Build playlist display components
- [ ] Implement recently played tracking
#### Recommendations & Discovery
- [ ] Integrate Apple Music recommendations API
- [ ] Create "Similar Artists" component
- [ ] Build "Discover" page with curated content
- [ ] Add music taste profile generation
- [ ] Implement collaborative filtering
#### Advanced Features
- [ ] Full-length playback (with proper licensing)
- [ ] Playlist creation and management
- [ ] Social sharing of previews
- [ ] Music stats and analytics
- [ ] Apple Music embed widgets
## Technical Architecture
### API Flow
```
Last.fm API → Recent Albums → Apple Music Search → Enhanced Data → Redis Cache → Frontend
```
### Component Hierarchy
```
HomePage
└── AlbumGrid
└── Album
├── AlbumArtwork (enhanced)
├── AlbumMetadata (enhanced)
└── MusicPreview (new)
```
### Data Structure
```typescript
interface EnhancedAlbum extends Album {
appleMusicId?: string;
highResArtwork?: string; // Used immediately
previewUrl?: string; // Used immediately
// Stored for future use (not displayed yet):
genres?: string[];
releaseDate?: string;
trackCount?: number;
tracks?: AppleMusicTrack[];
}
```
## Security Considerations
- Private key (.p8) must never be committed to repository
- JWT tokens should be generated server-side only
- Implement proper CORS headers for API endpoints
- Rate limit client requests to prevent abuse
- Validate all Apple Music API responses
## Dependencies
### New Dependencies
- `jsonwebtoken`: JWT generation
- `@types/jsonwebtoken`: TypeScript types
### Existing Dependencies to Leverage
- `redis`: Caching layer
- `$lib/server/redis-client`: Existing Redis connection
### Dependencies to Remove
- `node-itunes-search`: Replaced by Apple Music API
## Rollback Plan
1. Keep iTunes Search code commented but not removed initially
2. Implement feature flag for Apple Music integration
3. Monitor error rates and performance metrics
4. Have quick rollback script ready
5. Maintain data structure compatibility
## Open Questions
1. Should we display Apple Music attribution/badges?
2. Do we want to track preview play analytics?
3. Should previews auto-play on hover or require click?
4. How should we handle explicit content?
5. Do we want to implement Apple Music affiliate links?
## Success Criteria
- [ ] All iTunes Search API calls replaced successfully
- [ ] 30-second previews playing smoothly across all browsers
- [ ] Artwork quality noticeably improved
- [ ] Enhanced metadata fetched and cached (even if not displayed)
- [ ] No increase in page load time
- [ ] Current UI remains unchanged (except preview button)
- [ ] Zero security vulnerabilities
- [ ] Redis cache hit rate > 80%
## Timeline
- **Week 1**: Foundation setup and API client development
- **Week 2**: Integration and frontend components
- **Week 3**: Testing, optimization, and launch
- **Post-launch**: Monitor and iterate based on usage
## Resources
- [Apple Music API Documentation](https://developer.apple.com/documentation/applemusicapi)
- [JWT Best Practices](https://tools.ietf.org/html/rfc8725)
- [Original Deno Implementation](https://gist.github.com/NetOpWibby/fca4e7942617095677831d6c74187f84)
- [MusicKit JS](https://developer.apple.com/documentation/musickitjs) (for future client-side features)

View file

@ -0,0 +1,249 @@
# PRD: SEO & Metadata System
## Executive Summary
This PRD outlines the implementation of a comprehensive SEO and metadata system for jedmund.com. Currently, many pages lack proper browser titles, OpenGraph tags, and Twitter cards, which impacts search engine visibility and social media sharing. This upgrade will create a systematic approach to metadata management across all pages.
## Problem Statement
### Current Issues
1. **Inconsistent Implementation**: Only 2 out of 10+ page types have proper metadata
2. **Missing Social Media Support**: No Twitter cards on any pages
3. **Poor Search Visibility**: Missing canonical URLs, structured data, and sitemaps
4. **Hardcoded Values**: Base meta tags in app.html cannot be dynamically updated
5. **No Image Strategy**: Most pages lack OpenGraph images, reducing social media engagement
### Impact
- Reduced search engine visibility
- Poor social media sharing experience
- Missed opportunities for rich snippets in search results
- Inconsistent branding across shared links
## Goals
1. **Implement comprehensive metadata** on all pages
2. **Create reusable components** for consistent implementation
3. **Support dynamic content** with appropriate fallbacks
4. **Enhance social sharing** with proper images and descriptions
5. **Improve SEO** with structured data and technical optimizations
## Success Metrics
- 100% of pages have appropriate title tags
- All shareable pages have OpenGraph and Twitter card support
- Dynamic pages pull metadata from their content
- Consistent branding across all metadata
- Valid structured data on relevant pages
## Proposed Solution
### 1. Core Components
#### SeoMetadata Component
A centralized Svelte component that handles all metadata needs:
```svelte
<SeoMetadata
title="Project Title"
description="Project description"
type="article"
image="/path/to/image.jpg"
author="@jedmund"
publishedTime={date}
modifiedTime={date}
tags={['tag1', 'tag2']}
/>
```
Features:
- Automatic title formatting (e.g., "Title | @jedmund")
- Fallback chains for missing data
- Support for all OpenGraph types
- Twitter card generation
- Canonical URL handling
- JSON-LD structured data
### 2. Page-Specific Implementation
#### High Priority Pages
**Home Page (/)**
- Title: "@jedmund — Software designer and strategist"
- Description: Professional summary
- Type: website
- Image: Professional headshot or branded image
**Work Project Pages (/work/[slug])**
- Title: "[Project Name] by @jedmund"
- Description: Project description
- Type: article
- Image: Project logo on brand color background
- Structured data: CreativeWork schema
**Photo Pages (/photos/[slug]/[id])**
- Title: "[Photo Title] | Photography by @jedmund"
- Description: Photo caption or album context
- Type: article
- Image: The photo itself
- Structured data: ImageObject schema
**Universe Posts (/universe/[slug])**
- Essays (long-form): "[Essay Name] — @jedmund"
- Posts (short-form): "@jedmund: [Post snippet]"
- Description: Post excerpt (first 160 chars)
- Type: article
- Image: First attachment or fallback
- Structured data: BlogPosting schema
#### Medium Priority Pages
**Labs Projects (/labs/[slug])**
- Similar to Work projects but with "Lab" designation
- Experimental project metadata
**About Page (/about)**
- Title: "About | @jedmund"
- Description: Professional bio excerpt
- Type: profile
- Structured data: Person schema
**Photo Albums (/photos/[slug])**
- Title: "[Album Name] | Photography by @jedmund"
- Description: Album description
- Type: website
- Image: Album cover or first photo
### 3. Dynamic OG Image Generation
Create an API endpoint (`/api/og-image`) that generates images:
- For projects: Logo on brand color background
- For photos: The photo itself with optional watermark
- For text posts: Branded template with title
- Fallback: Site-wide branded image
### 4. Technical SEO Improvements
**Sitemap Generation**
- Dynamic sitemap.xml generation
- Include all public pages
- Update frequency and priority hints
**Robots.txt**
- Allow all crawlers by default
- Block admin routes
- Reference sitemap location
**Canonical URLs**
- Automatic canonical URL generation
- Handle www/non-www consistency
- Support pagination parameters
### 5. Utilities & Helpers
**formatSeoTitle(title, suffix = "@jedmund")**
- Consistent title formatting
- Character limit enforcement (60 chars)
**generateDescription(content, limit = 160)**
- Extract description from content
- HTML stripping
- Smart truncation
**getCanonicalUrl(path)**
- Generate absolute URLs
- Handle query parameters
- Ensure consistency
## Implementation Plan
### Phase 1: Foundation (Week 1)
- [ ] Create SeoMetadata component
- [ ] Implement basic meta tag support
- [ ] Add title/description utilities
- [ ] Update app.html to remove hardcoded values
### Phase 2: Critical Pages (Week 2)
- [ ] Home page metadata
- [ ] Work project pages
- [ ] Universe post pages
- [ ] Photo detail pages
### Phase 3: Secondary Pages (Week 3)
- [ ] About page
- [ ] Labs page and projects
- [ ] Photo albums and index
- [ ] Universe feed
### Phase 4: Advanced Features (Week 4)
- [ ] Dynamic OG image generation
- [ ] Structured data implementation
- [ ] Sitemap generation
- [ ] Technical SEO improvements
### Phase 5: Testing & Refinement (Week 5)
- [ ] Test all pages with social media debuggers
- [ ] Validate structured data
- [ ] Performance optimization
- [ ] Documentation
## Technical Considerations
### Performance
- Metadata generation should not impact page load time
- Cache generated OG images
- Minimize JavaScript overhead
### Maintenance
- Centralized component reduces update complexity
- Clear documentation for adding new pages
- Automated testing for metadata presence
### Compatibility
- Support major social platforms (Twitter, Facebook, LinkedIn)
- Ensure search engine compatibility
- Fallback for missing data
## Risks & Mitigation
**Risk**: Dynamic image generation could be slow
**Mitigation**: Implement caching and pre-generation for known content
**Risk**: Incorrect metadata could hurt SEO
**Mitigation**: Thorough testing and validation tools
**Risk**: Increased complexity for developers
**Mitigation**: Clear component API and documentation
## Future Enhancements
1. **A/B Testing**: Test different titles/descriptions for engagement
2. **Analytics Integration**: Track which metadata drives traffic
3. **Internationalization**: Support for multiple languages
4. **Rich Snippets**: Implement more schema types (FAQ, HowTo, etc.)
5. **Social Media Automation**: Auto-generate platform-specific variants
## Appendix
### Current Implementation Status
✅ **Good Implementation**
- /universe/[slug]
- /photos/[albumSlug]/[photoId]
⚠️ **Partial Implementation**
- /photos/[slug]
- /universe
❌ **No Implementation**
- / (home)
- /about
- /labs
- /labs/[slug]
- /photos
- /work/[slug]
### Resources
- [OpenGraph Protocol](https://ogp.me/)
- [Twitter Cards](https://developer.twitter.com/en/docs/twitter-for-websites/cards)
- [Schema.org](https://schema.org/)
- [Google SEO Guidelines](https://developers.google.com/search/docs)