Ship a user profile page with drag-and-drop avatar upload that persists across sessions — users can update their display name, bio, and profile photo from a single responsive form backed by S3 presigned URLs.
sample-add-user-profile-page.html
docs/plans/sample-add-user-profile-page.html
Context
The app currently has no profile management — users see a generic avatar and cannot update personal details. This drives support tickets (“how do I change my name?”) and reduces engagement. The backend already has a users table with display_name and bio columns; we need to add avatar_url and build the frontend.
Steps
avatar_url column to the users table via migration
TEXT column avoids breaking existing rows.Verify
npx prisma migrate dev and confirm the column exists with SELECT avatar_url FROM users LIMIT 1.POST /api/upload/avatar
Verify
curl -X POST /api/upload/avatar -H "Authorization: Bearer $TOKEN" and confirm a presigned URL is returned with a 60-second TTL.ProfileForm.tsx React component with avatar drag-and-drop zone
Verify
sharp to 256×256px WebP
sharp is already a project dependency.Verify
ProfileForm.tsx
Verify
Verify
aria-live region.aria-describedby for format constraints.Acceptance Criteria
Verification
End-to-end: log in as a test user, navigate to /settings/profile, update display name and bio, upload a photo via drag-and-drop, reload the page, and confirm all fields persist. Repeat on a 375px mobile viewport. Run the Lighthouse accessibility audit and confirm no new violations. Verify the S3 bucket contains the resized WebP object.
Unresolved Questions
-
Should the profile update endpoint separate avatar metadata from user fields?
The current plan updates display_name, bio, and avatar_url in a single PATCH /api/users/me request. Evaluate whether avatar_url should be updated separately (via a callback after S3 upload confirms) to handle partial failures — e.g., S3 upload succeeds but the DB write fails. Recommend an approach and explain the trade-offs.
-
What file size and format limits should the upload enforce?
Define the file validation rules for avatar upload: max file size (in MB), accepted MIME types (JPEG, PNG, WebP, GIF?), and whether animated GIFs should be allowed or flattened to a single frame. Consider the sharp resize step and S3 storage costs. Output the validation config and error messages.