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
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)
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>
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>
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>
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.
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.
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