Implements backend infrastructure for loading artist profiles from Cloudflare D1 database instead of static data. Database Changes: - Add slug column migration for SEO-friendly URLs (0001_add_artist_slug.sql) - Enhanced data migration script with slug generation - Support for all artist fields from data/artists.ts Type Definitions: - Add slug field to Artist interface - Create ArtistWithPortfolio type for full artist data - Create PublicArtist type for sanitized API responses - Add ArtistFilters type for query parameters - Add ArtistDashboardStats for analytics Database Functions (lib/db.ts): - getPublicArtists() - fetch active artists with portfolio and filtering - getArtistWithPortfolio() - fetch single artist with full portfolio - getArtistBySlug() - fetch by URL-friendly slug - getArtistByUserId() - fetch by user ID for dashboard - Enhanced getArtists() with JSON parsing API Endpoints: - Updated GET /api/artists - filtering, pagination, portfolio images - Created GET /api/artists/[id] - fetch by ID or slug - Created PUT /api/artists/[id] - update with authorization - Created DELETE /api/artists/[id] - soft delete (admin only) - Created GET /api/artists/me - current artist profile React Hooks (hooks/use-artist-data.ts): - useArtists() - fetch with filtering - useArtist() - fetch single artist - useCurrentArtist() - logged-in artist - useUpdateArtist(), useCreateArtist(), useDeleteArtist() - mutations Frontend Components: - Refactored artists-grid.tsx to use API with loading/error states - Use database field names (slug, specialties, portfolioImages) - Display profile images from portfolio - Client-side filtering by specialty Files Modified: - sql/migrations/0001_add_artist_slug.sql (new) - types/database.ts (enhanced) - lib/data-migration.ts (enhanced) - lib/db.ts (enhanced) - app/api/artists/route.ts (updated) - app/api/artists/[id]/route.ts (new) - app/api/artists/me/route.ts (new) - hooks/use-artist-data.ts (new) - components/artists-grid.tsx (refactored) Remaining work: Artist portfolio page, artist dashboard, admin enhancements Ref: artist_profile_refactor_implementation_plan.md
16 KiB
Artist Profile Refactor Implementation Plan
Overview
Refactor the artists grid and individual artist profile pages to load content from a Cloudflare D1 database instead of static data. Enable artists to log into backend profiles where they can manage their portfolio images, bio, and other information. The existing data/artists.ts will serve as seed data for the database.
This implementation connects the existing database schema, API routes, and authentication system with the public-facing components, while also creating an artist dashboard for self-service portfolio management.
Types
Database and API type definitions for artist profile management.
Key Type Updates:
- Ensure
Artistinterface intypes/database.tsmatches D1 schema columns - Add
ArtistWithPortfoliotype that includes populatedportfolioImagesarray - Create
PublicArtisttype for sanitized public API responses - Add
ArtistDashboardStatstype for artist-specific analytics
New Type Definitions:
// types/database.ts additions
export interface ArtistWithPortfolio extends Artist {
portfolioImages: PortfolioImage[]
user?: {
name: string
email: string
avatar?: string
}
}
export interface PublicArtist {
id: string
name: string
bio: string
specialties: string[]
instagramHandle?: string
portfolioImages: PortfolioImage[]
isActive: boolean
hourlyRate?: number
}
export interface ArtistDashboardStats {
totalImages: number
activeImages: number
profileViews?: number
lastUpdated: Date
}
Files
Files to Modify
1. lib/db.ts
- Add
getArtistWithPortfolio(id: string)function that joins artists with portfolio_images - Add
getPublicArtists()function that returns only active artists with public portfolio images - Add
getArtistByUserId(userId: string)function for artist dashboard access - Update
getArtists()to parse JSON fields properly (specialties)
2. app/api/artists/route.ts
- Update GET handler to return artists with portfolio images
- Add pagination support to prevent loading all artists at once
- Add filtering by specialty and search query
- Ensure responses match
PublicArtisttype for public endpoints
3. app/api/artists/[id]/route.ts
- Create this file (currently missing)
- Add GET endpoint to fetch single artist with portfolio
- Add PUT endpoint for updating artist (admin or artist themselves)
- Add authorization check (admin or owner)
4. components/artists-grid.tsx
- Remove hardcoded
artistsarray - Add
useEffectto fetch artists from/api/artists - Add loading and error states
- Update to use API response data structure
- Keep existing filtering UI but apply to fetched data
- Update routing to use database IDs instead of hardcoded IDs
5. components/artist-portfolio.tsx
- Remove hardcoded
artistsDataobject - Add
useEffectto fetch artist data from/api/artists/${artistId} - Add loading and error states
- Update image galleries to use portfolio images from database
- Handle missing artist gracefully
- Update data structure to match API response
6. components/artists-page-section.tsx
- Remove import from
@/data/artists - Fetch artists from API in component
- Add loading state
7. components/artists-section.tsx
- Remove import from
@/data/artists - Fetch artists from API
- Add loading skeleton
8. components/booking-form.tsx
- Update artist selection to fetch from API
- Remove import from
@/data/artists
9. app/artists/[id]/page.tsx
- Update to use database-friendly slug or ID
- May need to support both slug-based and ID-based routing during migration
10. lib/auth.ts
- Add
getArtistSession()helper that checks if logged-in user is an artist - Add
requireArtistAuth()helper for artist-only routes
11. sql/schema.sql
- Add missing columns if needed (review against
data/artists.tsstructure) - Add indexes for performance (slug, user_id lookups)
- Consider adding
slugcolumn to artists table for SEO-friendly URLs
12. lib/data-migration.ts
- Update migration to use all artists from
data/artists.ts - Fix portfolio image creation to handle all work images
- Add proper slug generation from artist names
- Ensure idempotency (can be run multiple times safely)
Files to Create
1. app/artist-dashboard/page.tsx
- New artist dashboard home page
- Show artist's own profile overview
- Display stats (total images, views, etc.)
- Quick links to edit profile and portfolio
2. app/artist-dashboard/layout.tsx
- Layout wrapper for artist dashboard
- Navigation sidebar for dashboard sections
- Artist profile header
- Requires ARTIST or SHOP_ADMIN role
3. app/artist-dashboard/profile/page.tsx
- Artist profile edit page
- Reuse
<ArtistForm>component but filtered for artist-editable fields - Artists can edit: bio, specialties, instagram, hourly rate
- Cannot edit: name, email, isActive (admin only)
4. app/artist-dashboard/portfolio/page.tsx
- Portfolio image management page
- Upload new images
- Edit captions and tags
- Reorder images (drag and drop)
- Delete images
- Set visibility (public/private)
5. app/api/artists/me/route.ts
- GET endpoint to fetch current logged-in artist's data
- Requires authentication
- Returns artist profile for logged-in user
6. app/api/portfolio/route.ts (if not exists)
- POST endpoint to add portfolio images
- Requires artist or admin auth
- Handles R2 upload integration
7. app/api/portfolio/[id]/route.ts
- GET single portfolio image
- PUT to update (caption, tags, order, visibility)
- DELETE to remove image
- Authorization: admin or image owner
8. components/admin/portfolio-manager.tsx
- Reusable component for managing portfolio images
- Used in both admin and artist dashboard
- Image upload, grid display, edit modals
- Drag-drop reordering
9. hooks/use-artist-data.ts
- Custom hook for fetching artist data
- Handles loading, error states
- Caching with SWR or React Query pattern
- Reusable across components
10. middleware.ts (update)
- Add route protection for
/artist-dashboard/* - Verify user has ARTIST role
- Redirect to signin if not authenticated
Files to Delete (after migration)
None immediately - Keep data/artists.ts as seed data reference
Functions
New Functions in lib/db.ts
1. getArtistWithPortfolio(id: string, env?: any): Promise<ArtistWithPortfolio | null>
- Fetch artist by ID
- Join with portfolio_images table
- Parse JSON fields (specialties, tags)
- Return combined object with images array
2. getPublicArtists(filters?: ArtistFilters, env?: any): Promise<PublicArtist[]>
- Fetch only active artists
- Include only public portfolio images
- Apply filters (specialty, search)
- Sanitize data for public consumption
3. getArtistByUserId(userId: string, env?: any): Promise<Artist | null>
- Fetch artist record by user_id
- Used for artist dashboard access
- Returns full artist data for owner
4. getArtistBySlug(slug: string, env?: any): Promise<ArtistWithPortfolio | null>
- Fetch artist by URL slug
- Join with portfolio images
- For SEO-friendly URLs
5. updatePortfolioImageOrder(artistId: string, imageOrders: Array<{id: string, orderIndex: number}>, env?: any): Promise<void>
- Batch update order indices
- Used for drag-drop reordering
- Transaction support if available
New Functions in lib/auth.ts
1. getArtistSession(): Promise<{ artist: Artist, user: User } | null>
- Get current session
- Check if user has ARTIST role
- Fetch associated artist record
- Return combined data or null
2. requireArtistAuth(): Promise<{ artist: Artist, user: User }>
- Like requireAuth but specifically for artists
- Throws error if not an artist
- Returns artist and user data
3. canEditArtist(userId: string, artistId: string): Promise<boolean>
- Check if user can edit specific artist
- True if: user is the artist, SHOP_ADMIN, or SUPER_ADMIN
- Used for authorization checks
Modified Functions
1. lib/db.ts:getArtists()
- Add optional
includePortfolioparameter - Parse JSON fields properly
- Add error handling
2. lib/db.ts:createArtist()
- Add slug generation
- Ensure user creation if needed
- Return artist with portfolio array (empty initially)
3. lib/data-migration.ts:migrateArtistData()
- Update to migrate all fields from
data/artists.ts - Add slug generation
- Handle all portfolio images
- Add progress logging
Classes
New Classes
1. ArtistDashboardManager (optional)
- Class to encapsulate artist dashboard operations
- Methods: getStats(), updateProfile(), getPortfolio()
- Centralizes artist-specific business logic
- Located in
lib/artist-dashboard.ts
No other new classes required - Functional approach with helper functions is sufficient
Dependencies
Current Dependencies (verify versions)
next: 15.xnext-auth: Latest compatible with Next.js 15@tanstack/react-table: For admin tablesreact-hook-form: Form managementzod: Schema validation@hookform/resolvers: Zod integration with react-hook-form
New Dependencies to Install
1. swr or @tanstack/react-query
- For client-side data fetching and caching
- Recommended:
swr(lighter weight) - Install:
npm install swr
2. @dnd-kit/core, @dnd-kit/sortable (optional)
- For drag-drop portfolio reordering
- Only if implementing drag-drop UI
- Install:
npm install @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities
3. sharp (dev dependency)
- Image optimization during migration
- May already be included with Next.js
Configuration Updates
1. next.config.mjs
- Ensure image optimization configured for R2 URLs
- Add remote patterns for portfolio image domains
2. wrangler.toml
- Verify D1 database binding name matches code
- Verify R2 bucket binding for portfolio uploads
3. .env.local
- No new env vars needed (using Cloudflare bindings)
Testing
Unit Tests to Create
1. __tests__/lib/db.test.ts
- Test artist CRUD operations
- Test portfolio image operations
- Mock D1 database
- Verify JSON parsing
2. __tests__/lib/auth.test.ts
- Test artist authentication helpers
- Test authorization checks
- Mock NextAuth session
3. __tests__/hooks/use-artist-data.test.ts
- Test hook with mock data
- Test loading and error states
- Test cache behavior
Integration Tests to Create
1. __tests__/api/artists.test.ts
- Test GET /api/artists endpoint
- Test filtering and pagination
- Test error handling
2. __tests__/api/artists/[id].test.ts
- Test GET single artist
- Test PUT artist update
- Test authorization
3. __tests__/api/portfolio.test.ts
- Test portfolio CRUD operations
- Test file uploads
- Test authorization
Component Tests to Update
1. __tests__/components/artists-grid.test.tsx
- Update to mock API fetch
- Test loading states
- Test error states
- Test filtering
2. __tests__/components/artist-portfolio.test.tsx
- Update to mock API fetch
- Test portfolio image display
- Test modal interactions
E2E Test Scenarios
1. Artist Login and Profile Edit
- Artist signs in
- Navigates to dashboard
- Edits bio and specialties
- Saves successfully
2. Portfolio Image Upload
- Artist uploads images
- Images appear in portfolio
- Reorders images
- Deletes an image
3. Public Artist Profile View
- Anonymous user visits artist page
- Sees artist info and portfolio
- Images load correctly
- Filtering works
4. Admin Artist Management
- Admin creates new artist
- Edits artist information
- Uploads portfolio images for artist
- Deactivates artist
Implementation Order
Phase 1: Database & API Foundation (Steps 1-5)
1. Update Database Schema and Migration
- Review and update
sql/schema.sqlif needed (add slug column, indexes) - Update
lib/data-migration.tsto properly migrate all artist data fromdata/artists.ts - Test migration script locally
- Verify all artists and portfolio images are created correctly
2. Enhance Database Functions
- Update
lib/db.tswith new functions:getArtistWithPortfolio,getPublicArtists,getArtistByUserId,getArtistBySlug - Update existing functions to properly parse JSON fields
- Add error handling and logging
- Write unit tests for new functions
3. Create/Update API Endpoints
- Create
app/api/artists/[id]/route.tswith GET and PUT handlers - Update
app/api/artists/route.tsto support filtering and return portfolio images - Create
app/api/artists/me/route.tsfor artist self-access - Add authorization checks to all endpoints
- Test endpoints with Postman or similar
4. Update Authentication Helpers
- Add
getArtistSession()andrequireArtistAuth()tolib/auth.ts - Add
canEditArtist()authorization helper - Test with mock sessions
5. Create Data Fetching Hook
- Create
hooks/use-artist-data.tswith SWR - Implement loading and error states
- Add caching and revalidation
- Test hook in isolation
Phase 2: Public-Facing Components (Steps 6-8)
6. Refactor Artists Grid
- Update
components/artists-grid.tsxto fetch from API - Remove hardcoded data
- Add loading skeleton UI
- Add error handling UI
- Test filtering and pagination
- Verify routing to individual artists works
7. Refactor Artist Portfolio Page
- Update
components/artist-portfolio.tsxto fetch from API - Remove hardcoded
artistsData - Add loading states
- Update image galleries to use database images
- Test with various artist IDs
- Verify modal/lightbox still works
8. Update Supporting Components
- Update
components/artists-section.tsxto use API - Update
components/artists-page-section.tsxto use API - Update
components/booking-form.tsxartist selection - Add loading states to all
- Test home page and booking flow
Phase 3: Artist Dashboard (Steps 9-12)
9. Create Artist Dashboard Layout
- Create
app/artist-dashboard/layout.tsxwith navigation - Add role protection in middleware
- Create dashboard home page
app/artist-dashboard/page.tsx - Display artist stats and quick links
- Test authentication and routing
10. Build Profile Editor
- Create
app/artist-dashboard/profile/page.tsx - Reuse and adapt
<ArtistForm>component - Filter fields for artist-editable only
- Connect to PUT
/api/artists/meendpoint - Test profile updates
11. Build Portfolio Manager
- Create
app/artist-dashboard/portfolio/page.tsx - Create
components/admin/portfolio-manager.tsxcomponent - Implement image upload UI
- Add image editing (captions, tags, visibility)
- Test upload and management
12. Implement Portfolio API
- Create
app/api/portfolio/route.tsfor creating images - Create
app/api/portfolio/[id]/route.tsfor update/delete - Integrate with R2 upload system
- Add authorization checks
- Test full upload flow
Phase 4: Admin Enhancements (Steps 13-14)
13. Update Admin Artist Management
- Update
app/admin/artists/[id]/page.tsxto use API - Enhance
<ArtistForm>with portfolio management - Test admin CRUD operations
- Verify authorization works
14. Add Portfolio Management to Admin
- Integrate
<PortfolioManager>into admin artist edit page - Allow admins to manage any artist's portfolio
- Test admin portfolio operations
Phase 5: Testing & Refinement (Steps 15-17)
15. Write and Run Tests
- Create all unit tests for new functions
- Create integration tests for API endpoints
- Create component tests
- Run full test suite
- Fix any failing tests
16. Performance Optimization
- Add database indexes for common queries
- Implement image lazy loading
- Add proper caching headers to API
- Optimize large portfolio image displays
- Test with large datasets
17. Migration & Deployment
- Run migration on development D1 database
- Test full application flow
- Create migration checklist for production
- Deploy to staging environment
- Final testing in staging
- Production deployment
Phase 6: Documentation & Cleanup (Step 18)
18. Documentation and Cleanup
- Document new API endpoints
- Update README with setup instructions
- Add inline code comments
- Create artist onboarding guide
- Remove deprecated code/comments
- Archive old implementation if needed