docs: add PRD for album system redesign and update dependencies
- Add comprehensive PRD documenting album system redesign - Update README with new features and setup instructions - Update package dependencies for new functionality - Add required packages for geolocation and enhanced editing - Document new album content structure and API changes - Include migration guide for existing data Documents the major architectural changes in this release. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
ce13e5225d
commit
82327ce73f
4 changed files with 9411 additions and 9175 deletions
|
|
@ -22,16 +22,19 @@ Personal portfolio website built with SvelteKit featuring a content management s
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
Install dependencies:
|
Install dependencies:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
Start development server:
|
Start development server:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Build for production:
|
Build for production:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
```
|
```
|
||||||
|
|
@ -39,10 +42,12 @@ npm run build
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
|
|
||||||
Required environment variables:
|
Required environment variables:
|
||||||
|
|
||||||
- `LASTFM_API_KEY` - Last.fm API key for music data
|
- `LASTFM_API_KEY` - Last.fm API key for music data
|
||||||
- `REDIS_URL` - Redis connection URL for caching
|
- `REDIS_URL` - Redis connection URL for caching
|
||||||
|
|
||||||
Optional environment variables:
|
Optional environment variables:
|
||||||
|
|
||||||
- `DEBUG` - Enable debug logging for specific categories (e.g., `DEBUG=music` for music-related logs)
|
- `DEBUG` - Enable debug logging for specific categories (e.g., `DEBUG=music` for music-related logs)
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
|
||||||
27
package-lock.json
generated
27
package-lock.json
generated
|
|
@ -37,6 +37,7 @@
|
||||||
"@tiptap/starter-kit": "^2.12.0",
|
"@tiptap/starter-kit": "^2.12.0",
|
||||||
"@tiptap/suggestion": "^2.12.0",
|
"@tiptap/suggestion": "^2.12.0",
|
||||||
"@types/jsonwebtoken": "^9.0.9",
|
"@types/jsonwebtoken": "^9.0.9",
|
||||||
|
"@types/leaflet": "^1.9.18",
|
||||||
"@types/multer": "^1.4.12",
|
"@types/multer": "^1.4.12",
|
||||||
"@types/redis": "^4.0.10",
|
"@types/redis": "^4.0.10",
|
||||||
"@types/steamapi": "^2.2.5",
|
"@types/steamapi": "^2.2.5",
|
||||||
|
|
@ -48,6 +49,7 @@
|
||||||
"ioredis": "^5.4.1",
|
"ioredis": "^5.4.1",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"katex": "^0.16.22",
|
"katex": "^0.16.22",
|
||||||
|
"leaflet": "^1.9.4",
|
||||||
"lowlight": "^3.3.0",
|
"lowlight": "^3.3.0",
|
||||||
"lucide-svelte": "^0.511.0",
|
"lucide-svelte": "^0.511.0",
|
||||||
"marked": "^15.0.12",
|
"marked": "^15.0.12",
|
||||||
|
|
@ -1291,7 +1293,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.8.2.tgz",
|
||||||
"integrity": "sha512-5II+vbyzv4si6Yunwgkj0qT/iY0zyspttoDrL3R4BYgLdp42/d2C8xdi9vqkrYtKt9H32oFIukvyw3Koz5JoDg==",
|
"integrity": "sha512-5II+vbyzv4si6Yunwgkj0qT/iY0zyspttoDrL3R4BYgLdp42/d2C8xdi9vqkrYtKt9H32oFIukvyw3Koz5JoDg==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.18"
|
"node": ">=18.18"
|
||||||
},
|
},
|
||||||
|
|
@ -2846,6 +2847,11 @@
|
||||||
"@types/send": "*"
|
"@types/send": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/geojson": {
|
||||||
|
"version": "7946.0.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
|
||||||
|
"integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="
|
||||||
|
},
|
||||||
"node_modules/@types/hast": {
|
"node_modules/@types/hast": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
|
||||||
|
|
@ -2876,6 +2882,14 @@
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/leaflet": {
|
||||||
|
"version": "1.9.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.18.tgz",
|
||||||
|
"integrity": "sha512-ht2vsoPjezor5Pmzi5hdsA7F++v5UGq9OlUduWHmMZiuQGIpJ2WS5+Gg9HaAA79gNh1AIPtCqhzejcIZ3lPzXQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/geojson": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/linkify-it": {
|
"node_modules/@types/linkify-it": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
|
||||||
|
|
@ -3701,9 +3715,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001641",
|
"version": "1.0.30001724",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001641.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001724.tgz",
|
||||||
"integrity": "sha512-Phv5thgl67bHYo1TtMY/MurjkHhV4EDaCosezRXgZ8jzA/Ub+wjxAvbGvjoFENStinwi5kCyOYV3mi5tOGykwA==",
|
"integrity": "sha512-WqJo7p0TbHDOythNTqYujmaJTvtYRZrjpP8TCvH6Vb9CYJerJNKamKzIWOM4BkQatWj9H2lYulpdAQNBe7QhNA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|
@ -5797,6 +5811,11 @@
|
||||||
"integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==",
|
"integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/leaflet": {
|
||||||
|
"version": "1.9.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
|
||||||
|
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
|
||||||
|
},
|
||||||
"node_modules/levn": {
|
"node_modules/levn": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@
|
||||||
"@tiptap/starter-kit": "^2.12.0",
|
"@tiptap/starter-kit": "^2.12.0",
|
||||||
"@tiptap/suggestion": "^2.12.0",
|
"@tiptap/suggestion": "^2.12.0",
|
||||||
"@types/jsonwebtoken": "^9.0.9",
|
"@types/jsonwebtoken": "^9.0.9",
|
||||||
|
"@types/leaflet": "^1.9.18",
|
||||||
"@types/multer": "^1.4.12",
|
"@types/multer": "^1.4.12",
|
||||||
"@types/redis": "^4.0.10",
|
"@types/redis": "^4.0.10",
|
||||||
"@types/steamapi": "^2.2.5",
|
"@types/steamapi": "^2.2.5",
|
||||||
|
|
@ -98,6 +99,7 @@
|
||||||
"ioredis": "^5.4.1",
|
"ioredis": "^5.4.1",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"katex": "^0.16.22",
|
"katex": "^0.16.22",
|
||||||
|
"leaflet": "^1.9.4",
|
||||||
"lowlight": "^3.3.0",
|
"lowlight": "^3.3.0",
|
||||||
"lucide-svelte": "^0.511.0",
|
"lucide-svelte": "^0.511.0",
|
||||||
"marked": "^15.0.12",
|
"marked": "^15.0.12",
|
||||||
|
|
|
||||||
210
prd/PRD-album-system-redesign.md
Normal file
210
prd/PRD-album-system-redesign.md
Normal file
|
|
@ -0,0 +1,210 @@
|
||||||
|
# Product Requirements Document: Album System Redesign
|
||||||
|
|
||||||
|
## Summary of Changes
|
||||||
|
|
||||||
|
This PRD outlines a comprehensive redesign of the album system to transform albums from simple photo containers into rich photographic stories with enhanced content capabilities. The key changes include:
|
||||||
|
|
||||||
|
1. **Many-to-Many Photo-Album Relationships**: Enable a single photo to belong to multiple albums, providing greater flexibility in content organization
|
||||||
|
2. **Enhanced Photo Permalinks**: Display all associated albums on individual photo pages for better context
|
||||||
|
3. **Refined Collection Views**: Remove albums from public collection views while maintaining permalink access
|
||||||
|
4. **Rich Album Composer**: Implement an essay-style composer for albums allowing mixed text and photo content
|
||||||
|
5. **Geo-Location Features**: Add embedded map cards with point-of-interest markers for location-based storytelling
|
||||||
|
|
||||||
|
## Task List by Phase
|
||||||
|
|
||||||
|
### Additional Completed Tasks
|
||||||
|
|
||||||
|
- [x] Add geolocation capability to Edra editor (allows adding maps to any rich text content)
|
||||||
|
|
||||||
|
### Phase 1: Data Model Migration
|
||||||
|
|
||||||
|
- [x] Create database migration to remove direct photo-album relationship
|
||||||
|
- [x] Update schema to ensure AlbumMedia join table supports many-to-many relationships
|
||||||
|
- [x] Add album content field to store rich text/media composition
|
||||||
|
- [x] Create geo-location schema for map embedding (lat/lng, POI data)
|
||||||
|
- [x] Write data migration script to preserve existing album-photo relationships
|
||||||
|
- [x] Update all API endpoints to use new data model
|
||||||
|
|
||||||
|
### Phase 2: Photo Management Updates
|
||||||
|
|
||||||
|
- [x] Update photo permalink page to display associated albums
|
||||||
|
- [x] Create UI component for album badges/links on photo pages
|
||||||
|
- [x] Update photo API to fetch album associations
|
||||||
|
- [x] Modify admin photo editor to manage album associations
|
||||||
|
- [x] Create album selector component for photo editing
|
||||||
|
|
||||||
|
### Phase 3: Album Composer Development
|
||||||
|
|
||||||
|
- [x] Create new AlbumComposer component based on UniverseComposer
|
||||||
|
- [x] Implement rich text editor with photo insertion capabilities
|
||||||
|
- [x] Add photo browser/selector for inserting album photos
|
||||||
|
- [x] Create preview mode for composed album content
|
||||||
|
- [x] Implement auto-save functionality
|
||||||
|
- [ ] Add version history/drafts support
|
||||||
|
|
||||||
|
### Phase 4: Geo-Location Features
|
||||||
|
|
||||||
|
- [x] Design geo-card component with map embed
|
||||||
|
- [x] Integrate mapping library (e.g., Mapbox, Leaflet)
|
||||||
|
- [x] Create POI marker system with customizable popovers
|
||||||
|
- [x] Add geo-location picker in composer
|
||||||
|
- [x] Implement responsive map sizing
|
||||||
|
- [x] Add fallback for non-JS environments
|
||||||
|
|
||||||
|
### Phase 5: Frontend Updates
|
||||||
|
|
||||||
|
- [ ] Update album permalink pages to render composed content
|
||||||
|
- [ ] Remove albums from public collection views
|
||||||
|
- [ ] Update navigation/menus to reflect new album structure
|
||||||
|
- [ ] Implement new album listing page design
|
||||||
|
- [ ] Add SEO metadata for composed albums
|
||||||
|
- [ ] Update Universe feed album cards
|
||||||
|
|
||||||
|
### Phase 6: Admin Interface Updates
|
||||||
|
|
||||||
|
- [ ] Replace current AlbumForm with new composer interface
|
||||||
|
- [ ] Update album list view in admin
|
||||||
|
- [ ] Add bulk operations for album-photo associations
|
||||||
|
- [ ] Create album analytics dashboard
|
||||||
|
- [ ] Implement permission controls for album editing
|
||||||
|
|
||||||
|
## Implementation Plan
|
||||||
|
|
||||||
|
### Technical Architecture
|
||||||
|
|
||||||
|
1. **Database Structure**:
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
model Album {
|
||||||
|
id String @id
|
||||||
|
slug String @unique
|
||||||
|
title String
|
||||||
|
content Json? // Rich content blocks
|
||||||
|
geoLocations GeoLocation[]
|
||||||
|
media AlbumMedia[]
|
||||||
|
// ... existing fields
|
||||||
|
}
|
||||||
|
|
||||||
|
model Media {
|
||||||
|
id String @id
|
||||||
|
albums AlbumMedia[]
|
||||||
|
// ... existing fields
|
||||||
|
}
|
||||||
|
|
||||||
|
model AlbumMedia {
|
||||||
|
albumId String
|
||||||
|
mediaId String
|
||||||
|
displayOrder Int
|
||||||
|
album Album @relation(...)
|
||||||
|
media Media @relation(...)
|
||||||
|
|
||||||
|
@@id([albumId, mediaId])
|
||||||
|
}
|
||||||
|
|
||||||
|
model GeoLocation {
|
||||||
|
id String @id
|
||||||
|
albumId String
|
||||||
|
latitude Float
|
||||||
|
longitude Float
|
||||||
|
title String
|
||||||
|
description String?
|
||||||
|
album Album @relation(...)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Content Block Structure**:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type ContentBlock =
|
||||||
|
| { type: 'text'; content: string }
|
||||||
|
| { type: 'photo'; mediaId: string; caption?: string }
|
||||||
|
| { type: 'photoGrid'; mediaIds: string[]; layout: 'masonry' | 'grid' }
|
||||||
|
| { type: 'geoCard'; locationId: string }
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **API Updates**:
|
||||||
|
- `GET /api/media/[id]/albums` - Get all albums for a photo
|
||||||
|
- `PUT /api/albums/[id]/content` - Update album composed content
|
||||||
|
- `POST /api/albums/[id]/locations` - Add geo-location
|
||||||
|
- `PUT /api/media/[id]/albums` - Update photo's album associations
|
||||||
|
|
||||||
|
### Migration Strategy
|
||||||
|
|
||||||
|
1. **Phase 1**: Deploy database changes with backward compatibility
|
||||||
|
2. **Phase 2**: Update APIs to support both old and new patterns
|
||||||
|
3. **Phase 3**: Migrate frontend components incrementally
|
||||||
|
4. **Phase 4**: Run data migration to new structure
|
||||||
|
5. **Phase 5**: Remove deprecated code and fields
|
||||||
|
|
||||||
|
## Possible Challenges
|
||||||
|
|
||||||
|
### Technical Challenges
|
||||||
|
|
||||||
|
1. **Data Migration Complexity**:
|
||||||
|
|
||||||
|
- Risk of data loss during migration from direct relationships to join table
|
||||||
|
- Need to handle orphaned photos and maintain referential integrity
|
||||||
|
- Performance impact during migration on large datasets
|
||||||
|
|
||||||
|
2. **Performance Considerations**:
|
||||||
|
|
||||||
|
- Many-to-many queries could impact page load times
|
||||||
|
- Rich content rendering may require optimization
|
||||||
|
- Map embeds could slow down initial page loads
|
||||||
|
|
||||||
|
3. **Content Editor Complexity**:
|
||||||
|
|
||||||
|
- Building a robust WYSIWYG editor with photo insertion
|
||||||
|
- Handling drag-and-drop reordering of content blocks
|
||||||
|
- Ensuring responsive preview matches final output
|
||||||
|
|
||||||
|
4. **Geo-Location Integration**:
|
||||||
|
- Map API rate limits and costs
|
||||||
|
- Offline/fallback handling for maps
|
||||||
|
- Privacy concerns with location data
|
||||||
|
|
||||||
|
### User Experience Challenges
|
||||||
|
|
||||||
|
1. **Migration Path for Existing Users**:
|
||||||
|
|
||||||
|
- Users may be confused by the new album structure
|
||||||
|
- Need clear communication about changes
|
||||||
|
- Potential breaking of bookmarked album URLs
|
||||||
|
|
||||||
|
2. **Content Creation Learning Curve**:
|
||||||
|
|
||||||
|
- More complex interface compared to simple photo upload
|
||||||
|
- Need intuitive UI for mixed content creation
|
||||||
|
- Balancing power vs simplicity
|
||||||
|
|
||||||
|
3. **Navigation Changes**:
|
||||||
|
- Albums no longer in collection views may confuse users
|
||||||
|
- Need alternative discovery methods for albums
|
||||||
|
- Maintaining SEO value of existing album pages
|
||||||
|
|
||||||
|
### Operational Challenges
|
||||||
|
|
||||||
|
1. **Storage and Bandwidth**:
|
||||||
|
|
||||||
|
- Rich content will increase storage needs
|
||||||
|
- Map tiles and assets increase bandwidth usage
|
||||||
|
- Need efficient caching strategy
|
||||||
|
|
||||||
|
2. **Content Moderation**:
|
||||||
|
|
||||||
|
- More complex content requires better moderation tools
|
||||||
|
- Geo-location data needs privacy controls
|
||||||
|
- Version control for composed content
|
||||||
|
|
||||||
|
3. **Backward Compatibility**:
|
||||||
|
- API versioning to support existing integrations
|
||||||
|
- Gradual deprecation of old endpoints
|
||||||
|
- Supporting old album URLs with redirects
|
||||||
|
|
||||||
|
### Mitigation Strategies
|
||||||
|
|
||||||
|
1. **Phased Rollout**: Deploy features incrementally with feature flags
|
||||||
|
2. **Comprehensive Testing**: Unit, integration, and end-to-end tests for all changes
|
||||||
|
3. **Performance Monitoring**: Track query performance and optimize hot paths
|
||||||
|
4. **User Documentation**: Create guides and tutorials for new features
|
||||||
|
5. **Rollback Plan**: Maintain ability to revert to previous system if needed
|
||||||
Loading…
Reference in a new issue