feat: base64 uploads, reusable forms, Discord roles, and UX improvements #66

Merged
naomi merged 8 commits from fix/base64 into main 2026-02-20 20:32:52 -08:00

8 Commits

Author SHA1 Message Date
hikari 309a20f694 fix: rename form output bindings to avoid DOM event conflicts
Node.js CI / CI (pull_request) Successful in 1m22s
Security Scan and Upload / Security & DefectDojo Upload (pull_request) Successful in 1m26s
Renamed @Output() properties in all form components from 'save' and
'cancel' to 'formSubmit' and 'formCancel' to resolve ESLint rule
@angular-eslint/no-output-native which prohibits output bindings
named after standard DOM events.

Updated all template bindings in detail components and admin
suggestions to use the new output names.

- Renamed save → formSubmit in all 6 form components
- Renamed cancel → formCancel in all 6 form components
- Updated bindings in 6 detail components
- Updated bindings in admin suggestions component
2026-02-20 20:26:32 -08:00
hikari 536cf6e7f9 feat: auto-assign Discord role to library members
Node.js CI / CI (pull_request) Failing after 35s
Security Scan and Upload / Security & DefectDojo Upload (pull_request) Successful in 1m9s
Implemented automatic Discord role assignment for users who are
members of the NHCarrigan server. This happens on every login:

- Check if user is in Discord server (ID: 1354624415861833870)
- Fetch user's current roles via Discord API
- Assign library member role if they don't have it yet
- Graceful error handling without blocking login

Uses Discord Bot API with proper permissions to manage roles.
Similar pattern to badge refresh on login.

Environment variables added:
- DISCORD_BOT_TOKEN: Bot token for Discord API calls
- LIBRARY_ROLE_ID: Role ID to assign (1474616681023279236)
2026-02-20 20:14:56 -08:00
hikari e6b6131134 fix: allow static assets to be served correctly
Fixed the not-found handler to exclude /assets routes, allowing static assets
like images to be served with correct MIME types instead of being caught by
the SPA fallback handler.

Changes:
- Updated setNotFoundHandler to check for /assets prefix
- Assets are now served directly by fastify-static with correct content-type
- Only non-API, non-asset routes fall through to index.html

This fixes the default cover image not displaying because it was being served
as text/html instead of image/jpeg.

Co-Authored-By: Naomi Carrigan <commits@nhcarrigan.com>
2026-02-20 19:45:37 -08:00
hikari d74a342f63 feat: add default cover image for all media types
Added a beautiful default cover image featuring Naomi reading in her cozy
library, which will be displayed whenever a media item doesn't have a cover
image provided.

Changes:
- Added default-cover.jpg to frontend public/assets directory
- Updated all list components (games, books, music, shows, manga, art) to
  always display an image using the default as fallback
- Updated all detail components to always show cover section with default
  fallback
- Removed conditional rendering of cover images - now always visible
- Properly handles different property names (coverImage, coverArt, imageUrl)

Benefits:
- Consistent visual appearance across all media types
- No more empty spaces where cover images would be
- Better UX with uniform card layouts
- Beautiful placeholder that matches the library theme

Co-Authored-By: Naomi Carrigan <commits@nhcarrigan.com>
2026-02-20 19:40:46 -08:00
hikari b781034fce feat: add reusable form components and inline editing for all media types
Created reusable form components for all media types (Game, Book, Music, Show,
Manga, Art) to provide a consistent editing experience across the application.

Changes:
- Created 6 new form components in shared folder for all media types
- Each form component supports both 'add' and 'edit' modes
- Forms include all fields: title, author/artist/platform, status, dates,
  rating, time spent, notes, cover images, tags, and links
- Added inline editing to all detail views using form components
- Detail views now show edit form inline instead of navigating away
- Integrated form components into admin suggestions workflow
- Admins can now review and edit all suggestion details before accepting
- Added scroll-to-top functionality when clicking edit in all list views
- Ensures edit form is visible when opened from paginated lists

Benefits:
- Consistent UX across all media types
- Better editing experience with inline forms
- Improved admin suggestion workflow with full editing capabilities
- No route navigation for edits (better for SEO and UX)
- All forms follow the same styling and interaction patterns

Co-Authored-By: Naomi Carrigan <commits@nhcarrigan.com>
2026-02-20 19:29:05 -08:00
hikari f40f917bc5 feat: implement tiered rate limiting with admin bypass
Update rate limiting to be more lenient for authenticated users and bypass limits entirely for admin users:

- Unauthenticated users: 100 requests/minute (original limit)
- Authenticated users: 500 requests/minute (5x increase)
- Admin users: No rate limits (completely bypassed via allowList)

This allows the admin to interact with the library without restrictions whilst still protecting against abuse from unauthenticated users. Authenticated users get a much more generous limit for better user experience.

Uses @fastify/rate-limit's allowList and dynamic max options to implement the tiered system.
2026-02-20 18:35:21 -08:00
hikari 1fd2086afe docs: add comprehensive CLAUDE.md project documentation
Add detailed project documentation for AI assistants covering:
- Git commit guidelines and user permissions
- Project structure and technology stack
- Database schema with all models
- Authentication flow with Discord OAuth
- Image upload handling (base64 and regular URLs)
- Development workflow and scripts
- CI/CD pipeline configuration
- Configuration standards (TypeScript, ESLint, Jest)
- Secrets management with 1Password CLI
- Security features and API route structure
- Code style conventions and common gotchas
- Deployment instructions

This documentation will help AI assistants understand the project architecture, follow established patterns, and work effectively within the codebase.
2026-02-20 18:32:05 -08:00
hikari 3668a67a62 fix: resolve base64 image upload issues
This resolves issue #65 by addressing multiple problems that were preventing base64-encoded cover images from being uploaded:

1. Increased Fastify body limit from 1MB to 10MB to accommodate base64-encoded images
2. Removed duplicate coverImage string length validation that was blocking base64 data URLs
3. Fixed base64 size calculation to properly extract and measure just the base64 data portion
4. Updated validateDataUrl regex to allow whitespace in base64 strings
5. Added proper error handling with 400 status codes and helpful error messages instead of 500 errors

Users can now successfully upload cover images as base64 data URLs up to 5MB (decoded size) and will receive clear validation error messages if uploads fail.

Closes #65
2026-02-20 18:28:24 -08:00