- Fix admin video upload missing media_type/mime_type and video processing (#203)
- Fix Gallery-Premium Select All using atomic callbacks instead of stale closure loop (#220)
- Add photo dimension repair endpoint and admin UI (#180)
- Add E2E tests for all three fixes
Users behind Cloudflare Tunnel and other reverse proxies cannot upload
batches >100MB. The upload chunking previously used a hardcoded 500MB
limit. This adds a configurable `max_upload_batch_size_mb` setting
(default 95MB) to the admin General settings, leaving headroom below
Cloudflare's 100MB limit.
- #194: Send full date format object instead of just format string to prevent JSON parse errors
- #195: Remove non-functional forgot password link, fix README port 3005 -> 3000
- #196: Use ADMIN_PASSWORD env var in migration, update existing user in create-admin script instead of failing
- #197: Convert camelCase filter keys to snake_case in photo export to match backend PhotoFilterBuilder
- Replace deprecated docker-compose (v1) with docker compose (v2) in README
- Add missing ADMIN_PASSWORD to .env.example so new users don't get a
blank-string warning and can actually log in after first setup
When expires_at is null (no expiration), the status logic defaulted
days to 0, causing all non-expiring events to display as "Expired".
Now returns "Active" immediately when there is no expiration date.
Surface the existing original_filename from the database in the admin
photo grid hover overlay and photo viewer sidebar, so photographers can
correlate uploaded images with their Lightroom/disk originals. Only shown
when it differs from the system-generated filename. Gallery guests remain
unaffected.
- Disable production source maps and hide nginx version
- Reduce JSON body limit from 10gb to 50mb (uploads use multer, not JSON)
- Strip database info and error details from health endpoint
- Mask reCAPTCHA secret key in admin settings API responses
- Whitelist sort/order query parameters in events and photos endpoints
- Stop reflecting arbitrary origins in static file CORS headers
- Align nginx security headers with backend Helmet CSP, remove deprecated X-XSS-Protection
- Strip EXIF metadata from generated thumbnails and hero images
- Bind postgres/redis dev ports to localhost in docker-compose configs
- Add safeExec utility (spawn with shell:false) to prevent command injection
- Convert all exec/execAsync calls in backup, restore, and database backup
services to use safe spawn-based helpers
- Add Update Instructions Dialog with environment-specific commands (Docker/Git/Standalone)
- Add email notification settings for new version alerts
- Add "Sort by Capture Date" option using EXIF metadata extraction
- Fix E2E tests by loading environment variables via dotenv
- Add test-images/ and backend/*.db to .gitignore
Closes#181
- Fix masonry/mosaic layout regression where tiles displayed uniform heights
instead of respecting image aspect ratios. Changed from fixed 150-500px
height constraints to dynamic constraints based on column width.
- Add hero image optimization pipeline generating 1920x1080 images for
full-width hero sections instead of using low-quality thumbnails.
- New /hero/:photoId endpoint serves optimized hero images with watermark
support and automatic generation/caching.
- Add hero_url field to photos API response for frontend consumption.
- Migration 069 adds hero_path column to photos table.
- Update hero photo help text to mention category override capability
- Add hint in category manager about default hero photo fallback
- Add placeholder text in gallery preview for hero section
- Ensure live preview updates correctly for header/divider style changes
Admin Dark Mode:
- Add AdminDarkModeContext with light/dark/system preference
- Update all admin components with Tailwind dark: classes
- Add dark mode toggle in admin header
- Persist preference in localStorage
SEO Settings:
- Add robots.txt configuration in Settings > SEO tab
- Block AI crawlers (GPTBot, ChatGPT-User, etc.) with toggle
- Custom robots.txt rules management
- Add RobotsMetaTags component for gallery pages
- Backend service for dynamic robots.txt generation
- Database migration for SEO settings storage
UI/UX Improvements:
- Consistent dark mode styling across all admin pages
- Update gallery components with themed CSS classes
- Fix input, card, and button styling for dark mode
Update ghost button variant to use proper dark mode colors:
- Add dark:hover:bg-neutral-700 for hover state
- Add dark:text-neutral-300 for better icon/text visibility
- Fixes too-dark edit and view gallery buttons in Events table
- Update .card class to use explicit Tailwind colors instead of CSS
variables, preventing gallery theme from affecting admin UI
- Add .card-themed and .input-themed classes for gallery components
that need to use theme CSS variables
- Add dark mode support to CardHeader and CardFooter components
- Update .input class to use explicit colors for proper light/dark mode
- Update dark mode selectors for consistency (.dark .class)
- Show specific failing password requirement instead of generic error
when password validation fails on AcceptInvitePage (#170)
- Add inline Edit and View Gallery buttons to events table (#171)
- Make event table rows clickable to navigate to details (#171)
- Keep context menu for less common actions (Archive, Delete)
- Add responsive design: inline buttons hidden on mobile
- Add Gallery Premium layout: elegant light theme with masonry grid,
hero section, sticky navigation, and integrated lightbox
- Add Gallery Story layout: cinematic dark theme with scene-based
sections, carousels, and gold accents
- Implement full-page layout support: bypass standard header/footer/
sidebar for immersive experience
- Add logout button to both layouts for authenticated galleries
- Mark both layouts as (Beta) in theme editor and layout selectors
- Fix hero title color visibility in Gallery Premium layout
- Add distinct rendering branches for minimal and none header styles in
GalleryLayout (grid and non-grid), skipping the colored banner/wave
divider for both
- Cap hero section height at 700px via max-h to prevent it dominating
ultra-wide viewports
- Watch selectedCategoryId in GalleryView and swap the hero photo to
the category's hero_photo_id when filtering, reverting to the event
default when cleared
- Add minimal/none preview branches in GalleryPreview so the admin
theme editor shows visually distinct previews for all four styles
- Remove unused AdminPhoto import that was blocking the build
- Add Playwright e2e tests covering all four header styles, hero max
height, and category hero switching