diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8ff2f5ec..3954780d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1 @@ -{ - ".": "2.6.1" -} +{".":"3.43.1"} diff --git a/CHANGELOG.md b/CHANGELOG.md index 637d9f62..5b8039ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,473 +5,331 @@ All notable changes to PicPeak will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [3.55.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.54.7-beta.0...v3.55.0-beta.0) (2026-05-27) +## [3.43.1](https://github.com/the-luap/picpeak/compare/v3.43.0...v3.43.1) (2026-05-07) + + +### Bug Fixes + +* **security:** backport 18 dependency CVE patches from beta (3.42.2 stable) ([74eacbc](https://github.com/the-luap/picpeak/commit/74eacbc78f7efd5c499ae1647b716d3234096c39)) +* **security:** patch 18 dependency CVEs (axios + transitives + nodemailer + i18next-http-backend) ([37bf894](https://github.com/the-luap/picpeak/commit/37bf894412b4da0f0507dd8f1384e6f101ce14b2)) + +## [3.43.0](https://github.com/the-luap/picpeak/compare/v3.42.1...v3.43.0) (2026-05-07) ### Features -* **lightbox:** multi-photo Web Share save-to-Photos on iOS ([#557](https://github.com/the-luap/picpeak/issues/557)) ([d5823c7](https://github.com/the-luap/picpeak/commit/d5823c79d9a187461c0126adcff7f4374cd0e8aa)) +* add admin dark mode and SEO/robots.txt settings ([9c2a0d2](https://github.com/the-luap/picpeak/commit/9c2a0d272a21dfcace2ec795034e2f1adcba47e0)) +* add bulk category editing for photos ([#157](https://github.com/the-luap/picpeak/issues/157)) ([eca36c7](https://github.com/the-luap/picpeak/commit/eca36c70a23f18f937a9f5bddeff855e18f364c3)) +* add category hero/cover photo selection ([#163](https://github.com/the-luap/picpeak/issues/163)) ([6c30e2c](https://github.com/the-luap/picpeak/commit/6c30e2c2edd19a24d4f30a9558690bb7e2331b32)) +* add configurable upload batch size for reverse proxy compatibility ([#208](https://github.com/the-luap/picpeak/issues/208)) ([02a46e0](https://github.com/the-luap/picpeak/commit/02a46e083d68cfdb355b5a4fe4a8da7d667050b9)) +* add COOKIE_SECURE=auto for mixed HTTPS/HTTP deployments ([#298](https://github.com/the-luap/picpeak/issues/298)) ([b1dfbe4](https://github.com/the-luap/picpeak/commit/b1dfbe4c2fe271d8087974d02cf724f04058bdc9)) +* add COOKIE_SECURE=auto for mixed HTTPS/HTTP deployments ([#298](https://github.com/the-luap/picpeak/issues/298)) ([15a8ab4](https://github.com/the-luap/picpeak/commit/15a8ab41fd1c94e3397d300b161cd1fdd459ea05)) +* add customizable event types with admin management ([f8881d5](https://github.com/the-luap/picpeak/commit/f8881d5bd62d449fb40917ec8c20f0eb16c1fdad)) +* add Dutch (nl) locale and fix missing translation keys across all locales ([b54a80d](https://github.com/the-luap/picpeak/commit/b54a80d251bcbb9a126e32eeaef522688bc810c6)) +* add Dutch locale and fix missing translation keys ([e32da68](https://github.com/the-luap/picpeak/commit/e32da68cbdfa430d62cbb1057ea418dc6b2f14fb)) +* add Gallery Premium and Gallery Story layouts (Beta) ([e179def](https://github.com/the-luap/picpeak/commit/e179def3cceefe5fd6acd5574f2986e4f9e223ef)) +* add hero image focal point picker with anchor positioning ([#162](https://github.com/the-luap/picpeak/issues/162)) ([734868a](https://github.com/the-luap/picpeak/commit/734868abc23731b0ac9ad73e799194df1e6aa6ab)) +* add justified layout modes and aspect-ratio-aware mosaic ([#146](https://github.com/the-luap/picpeak/issues/146)) ([608bbd5](https://github.com/the-luap/picpeak/commit/608bbd50e7b31d49c7516a00e96f284fa16e2777)) +* Add justified layout modes and aspect-ratio-aware mosaic ([#146](https://github.com/the-luap/picpeak/issues/146)) ([ef2ae00](https://github.com/the-luap/picpeak/commit/ef2ae00ff20b754c2f2ed797e18c146d12d7f31a)) +* add justified/rows layout mode to masonry gallery ([#146](https://github.com/the-luap/picpeak/issues/146)) ([e081b56](https://github.com/the-luap/picpeak/commit/e081b56a44bf9fdaa3dd225d5dd4dde35bfe83d3)) +* add justified/rows layout mode to masonry gallery ([#146](https://github.com/the-luap/picpeak/issues/146)) + security fixes ([cd1d504](https://github.com/the-luap/picpeak/commit/cd1d50474f673b759c2f9401fdbe209a84773e39)) +* add optional event date and expiration settings ([3079eaa](https://github.com/the-luap/picpeak/commit/3079eaa2e5d1728c2c0f315626cc253e4b08edc2)) +* add optional event date and expiration settings ([2151147](https://github.com/the-luap/picpeak/commit/2151147f2d3134448ff32130da44678e2942d73c)), closes [#118](https://github.com/the-luap/picpeak/issues/118) +* add original filename preservation and Lightroom export support ([a59f414](https://github.com/the-luap/picpeak/commit/a59f41463f960a3a74ce3933dc7db84ee3a2018d)) +* add original filename preservation and Lightroom export support ([9872ad3](https://github.com/the-luap/picpeak/commit/9872ad3aef6488b359c5499a6dc3d8bfbfa48fde)) +* add per-event custom logo upload with bug fixes ([85170b8](https://github.com/the-luap/picpeak/commit/85170b883f504d83f1d862abb3f4e46741074826)) +* add per-event hero logo customization options ([0790a1d](https://github.com/the-luap/picpeak/commit/0790a1ddad774af89827a0a392e9fae0a945bff2)) +* add per-gallery thumbnail scale setting ([#172](https://github.com/the-luap/picpeak/issues/172)) ([#251](https://github.com/the-luap/picpeak/issues/251)) ([ee46088](https://github.com/the-luap/picpeak/commit/ee46088985ebbbb81d16e5bac23be2060c94397f)) +* add photo cap per event and Portuguese (pt-BR) locale ([1fa222e](https://github.com/the-luap/picpeak/commit/1fa222e9c4c26e525c7899e368988c6b0b08da85)) +* add photo cap per event and Portuguese locale ([088de43](https://github.com/the-luap/picpeak/commit/088de43f09f974d444f50452ef1117315c289ebc)) +* add quilted layout, fix mosaic, and backfill photo dimensions ([#146](https://github.com/the-luap/picpeak/issues/146)) ([46ed1bc](https://github.com/the-luap/picpeak/commit/46ed1bc276867a25b27bf22cd9b9d7e879a6947b)) +* add thumbnail settings UI to admin panel ([3a30fea](https://github.com/the-luap/picpeak/commit/3a30fea862034d64fbc7188fc25292594a9319e2)) +* add thumbnail settings UI to admin settings page ([#206](https://github.com/the-luap/picpeak/issues/206)) ([7d6d2f5](https://github.com/the-luap/picpeak/commit/7d6d2f56883a4402f0d97c95b0432a8a783c8024)) +* add update instructions dialog, email notifications, and capture date sorting ([50c0990](https://github.com/the-luap/picpeak/commit/50c09904a9434f988ab32a07da5d24db0e02065e)), closes [#181](https://github.com/the-luap/picpeak/issues/181) +* add visual WYSIWYG email template editor ([#229](https://github.com/the-luap/picpeak/issues/229)) ([04a7ea8](https://github.com/the-luap/picpeak/commit/04a7ea80f95d6aeb474b145292e75f45fb85c66d)) +* **branding:** 8-token CI palette + force color mode + dark-mode consistency ([8050927](https://github.com/the-luap/picpeak/commit/80509276074b8125b6d676839afabb0b6f89206f)) +* **branding:** force color mode (dark or light) site-wide ([5a162fc](https://github.com/the-luap/picpeak/commit/5a162fc8bec47a49cb1bcaa92ff72e197e8d2e42)) +* **branding:** inline force color mode with auto-save + clearer palette help text ([67d7d8d](https://github.com/the-luap/picpeak/commit/67d7d8d3fa25ceab0eda02b291f2e220b222f84a)) +* **branding:** per-family generic fallback via meta.json ([dcff451](https://github.com/the-luap/picpeak/commit/dcff4515721482e06c2ef1c1eb34f9e12754c07c)) +* **branding:** preview each font in its own face in the picker dropdown ([b4f9b65](https://github.com/the-luap/picpeak/commit/b4f9b65f1df4c400f22b28f20e1304ec57279d33)) +* **branding:** self-hosted webfonts with filesystem scanner ([d04bf28](https://github.com/the-luap/picpeak/commit/d04bf288084144bf53ef0ba988fa32ed703d7351)) +* **branding:** self-hosted webfonts with filesystem scanner ([bac51fe](https://github.com/the-luap/picpeak/commit/bac51fe69a39f85381f445e8da6cd63cf5826fc4)) +* **cms:** add external URL toggle for imprint and privacy pages ([b2c8161](https://github.com/the-luap/picpeak/commit/b2c8161a43c2d0b09d6783e791b3f26862254824)) +* **cms:** add per-page external URL override — backend ([66423bb](https://github.com/the-luap/picpeak/commit/66423bb65e83b6204509c9a98d783ba8255c3364)) +* **cms:** admin UI for external imprint/privacy URL ([a4e3d10](https://github.com/the-luap/picpeak/commit/a4e3d10fb0c97ea07c4b08d16c0947945d8a7576)) +* **cms:** redirect legal links to external URL when configured ([c5bba50](https://github.com/the-luap/picpeak/commit/c5bba505ac92b5257f6bb1c069b8bc23ea6a5a1b)) +* configurable upload batch size for reverse proxy compatibility ([9b7495e](https://github.com/the-luap/picpeak/commit/9b7495e0054975e66c9b5006c24a9fae63969de4)) +* configurable upload batch size for reverse proxy compatibility ([4243363](https://github.com/the-luap/picpeak/commit/424336340bef8e1629490ade154f0ceebb2a71e1)) +* customisable 404 + gallery-not-found pages via CMS ([#324](https://github.com/the-luap/picpeak/issues/324)) ([4f77905](https://github.com/the-luap/picpeak/commit/4f77905b87bea474b3d2496350996deaad041230)) +* decouple hero header from gallery layouts ([#158](https://github.com/the-luap/picpeak/issues/158)) ([7b8d8bd](https://github.com/the-luap/picpeak/commit/7b8d8bd92ba7a96717bb4d821b38dddc395f701a)) +* draft mode, admin branding, and workflow improvements ([dc98206](https://github.com/the-luap/picpeak/commit/dc98206737d1ebe43637319ce8c5b6da2e44c05d)) +* draft mode, admin branding, and workflow improvements ([40332a7](https://github.com/the-luap/picpeak/commit/40332a71db6534097940d3f9362b0fe651dba6c7)) +* dynamic website title from branding settings ([d29aab7](https://github.com/the-luap/picpeak/commit/d29aab7c70c5777451666fb7d5c7a9729dab684a)) +* **email:** expand email palette to 8 tokens + Sync from Branding button ([47b6b39](https://github.com/the-luap/picpeak/commit/47b6b39f3a942aee93b970031d95a952cb769d09)) +* **events:** add Photos column to admin events list ([#384](https://github.com/the-luap/picpeak/issues/384)) ([d561db8](https://github.com/the-luap/picpeak/commit/d561db802b04db8fbb38819a22e840532e775ef0)) +* **events:** add Photos column to admin events list ([#384](https://github.com/the-luap/picpeak/issues/384)) ([ffb4318](https://github.com/the-luap/picpeak/commit/ffb4318a1f667e273cd59805673b125d2f17699b)) +* **events:** bulk delete with password confirmation ([#384](https://github.com/the-luap/picpeak/issues/384)) ([647aea2](https://github.com/the-luap/picpeak/commit/647aea21ae42fe0d089bf45568702617a25b98e4)) +* **events:** bulk delete with password confirmation ([#384](https://github.com/the-luap/picpeak/issues/384)) ([48d538f](https://github.com/the-luap/picpeak/commit/48d538f94fd39d9b85ec57c57301a8490b7d4f6d)) +* **events:** prefill admin email + admin picker on event creation ([3fe8e61](https://github.com/the-luap/picpeak/commit/3fe8e61bd1175e35dcb61604447e5d9c2e902ec5)) +* **events:** prefill admin email + admin picker on event creation ([ee56b67](https://github.com/the-luap/picpeak/commit/ee56b6762f5b2eb9ea42f4abe4dde4356e2e54e6)) +* **events:** Sync from Branding button in gallery theme customizer + clarified default inheritance ([bdbe7b8](https://github.com/the-luap/picpeak/commit/bdbe7b80a13b8b215ac544ba9105100e792eeda2)) +* **events:** tree view for external media folder picker ([cdd40ac](https://github.com/the-luap/picpeak/commit/cdd40acb4591d4eb8f80a79c69201556eab1bfd0)) +* **events:** tree view for external media folder picker ([f927b09](https://github.com/the-luap/picpeak/commit/f927b09c70f3b6a5c81c3726609a29680b96b6fc)) +* **frontend:** dedupe /public/settings via shared usePublicSettings hook ([#325](https://github.com/the-luap/picpeak/issues/325)) ([3d4ae4d](https://github.com/the-luap/picpeak/commit/3d4ae4d7e9f9995d93563e8092e05215362afb3b)) +* gallery layouts, bulk category editing, and hero header improvements ([7037106](https://github.com/the-luap/picpeak/commit/7037106bff62593bba600d898a781f79f07b459d)) +* gallery layouts, hero customization, bulk categories & event types ([d9e00dc](https://github.com/the-luap/picpeak/commit/d9e00dc0dbd7cef0ddb4665e5306c98aac3573e3)) +* gallery layouts, hero customization, event types, and UX improvements ([#146](https://github.com/the-luap/picpeak/issues/146), [#155](https://github.com/the-luap/picpeak/issues/155)-163, [#170](https://github.com/the-luap/picpeak/issues/170), [#171](https://github.com/the-luap/picpeak/issues/171)) ([4280444](https://github.com/the-luap/picpeak/commit/4280444d70e73db09e67e18ce25bac75cf499b75)) +* **gallery:** decouple header style from layout, add banner option ([1f1a856](https://github.com/the-luap/picpeak/commit/1f1a856083b1966ed4b32a23a14442f1727cecef)) +* **gallery:** decouple header style from layout, add banner option ([24d7277](https://github.com/the-luap/picpeak/commit/24d727752c442263a6469e0aefa666454a4c652f)) +* **gallery:** decouple header style from layout, add banner option ([aff29c9](https://github.com/the-luap/picpeak/commit/aff29c91bbb250debe74e2a512047ee40e157a34)) +* **gallery:** icon-only menu, accent Download CTA ([#386](https://github.com/the-luap/picpeak/issues/386)) ([876b35b](https://github.com/the-luap/picpeak/commit/876b35b4a512f70cfc19561e35ce9d915a599547)) +* **gallery:** icon-only menu, accent Download CTA, logo aligned ([#386](https://github.com/the-luap/picpeak/issues/386)) ([de8ad5f](https://github.com/the-luap/picpeak/commit/de8ad5fdd5ce1b9552ca8ca6e405d15c7372a4c8)) +* guest selections with per-person identity ([#292](https://github.com/the-luap/picpeak/issues/292)) ([3856ba2](https://github.com/the-luap/picpeak/commit/3856ba25bbce971b07bba4dad19e7bdceca98cab)) +* guest selections with per-person identity ([#292](https://github.com/the-luap/picpeak/issues/292)) ([ad4e5a7](https://github.com/the-luap/picpeak/commit/ad4e5a7506bc9217d1223101da0bc112047532a8)) +* **i18n:** add Brazilian Portuguese (pt-BR) locale ([375f512](https://github.com/the-luap/picpeak/commit/375f51285b5db9c0dfcc04761d24927282e57796)) +* **i18n:** improve pt locale with pt-BR phrasings, remove duplicate pt-BR file ([f25559c](https://github.com/the-luap/picpeak/commit/f25559c0e76776f7cfe8d187e1fea05e751bbafe)) +* improve gallery layouts with aspect-ratio-aware masonry and mosaic modes ([#146](https://github.com/the-luap/picpeak/issues/146)) ([aacfcd5](https://github.com/the-luap/picpeak/commit/aacfcd517ea5739e834cf84627b55b3449740a5c)) +* improve hero image UX and live preview ([#163](https://github.com/the-luap/picpeak/issues/163), [#158](https://github.com/the-luap/picpeak/issues/158)) ([d63f67a](https://github.com/the-luap/picpeak/commit/d63f67a2afba1b92610382aa1012428ccacb86bd)) +* multilingual email templates with translations table ([8c5996e](https://github.com/the-luap/picpeak/commit/8c5996e4ec43b2817d84cc040cfe52878ffb61d5)) +* multilingual email templates with translations table ([f50d7c0](https://github.com/the-luap/picpeak/commit/f50d7c0c51aa84a2182e450cd4b6a00777a8f9c0)) +* native multi-arch Docker images (Apple Silicon, ARM64 Linux) ([df30618](https://github.com/the-luap/picpeak/commit/df3061893d154152b75b8ab0d07e0b1e0078431d)) +* native S3 storage backend ([#328](https://github.com/the-luap/picpeak/issues/328)) + presigned download follow-up ([1b717ce](https://github.com/the-luap/picpeak/commit/1b717ce5ededa343d2fbb7e1c3493b4434743565)) +* new features and bug fixes for beta release ([151e1bf](https://github.com/the-luap/picpeak/commit/151e1bf50f206ae0571fa044c75b8bc9f0f40120)) +* optional customer phone field gated by global toggle ([#322](https://github.com/the-luap/picpeak/issues/322)) ([be6cb28](https://github.com/the-luap/picpeak/commit/be6cb28c8097d2277c1af2a32cf8bc88ebbc7136)) +* original filename in admin UI, update dialog, and security hardening ([3ea9d5b](https://github.com/the-luap/picpeak/commit/3ea9d5b1219980032cbee7a2564c0004948923f5)) +* original filename in admin UI, update dialog, security hardening, and bug fixes ([bcf2745](https://github.com/the-luap/picpeak/commit/bcf2745ab64acb968ae4bd0710b28e78c14f340c)) +* outbound webhooks for event/photo lifecycle ([#327](https://github.com/the-luap/picpeak/issues/327)) ([c488f48](https://github.com/the-luap/picpeak/commit/c488f481caacf0d63dafc47f509e8de2708bc30f)) +* per-event custom logos, customizable event types, and multiple bug fixes ([4c08160](https://github.com/the-luap/picpeak/commit/4c081601e02888d7ad289acb7847aee9d6f5703f)) +* photo visibility control with client access ([#172](https://github.com/the-luap/picpeak/issues/172)) ([4a93e4e](https://github.com/the-luap/picpeak/commit/4a93e4e8cbe1b7a23a8be706291a270ccdf5bb55)) +* photo visibility control with client access ([#172](https://github.com/the-luap/picpeak/issues/172)) ([e1b6e43](https://github.com/the-luap/picpeak/commit/e1b6e43e524211c913d3d29ade5fc029df12920f)) +* pre-generate watermarks for instant lightbox loading ([1be974a](https://github.com/the-luap/picpeak/commit/1be974afbb0b7a1bdbdd140327771907a5d3c2ae)), closes [#112](https://github.com/the-luap/picpeak/issues/112) +* pre-generated watermarks and mobile upload button improvements ([c6fdd38](https://github.com/the-luap/picpeak/commit/c6fdd38e842e1a8c0aa9cbab9fc791e6669e402d)) +* pre-zip download all and photo replacement by name ([#312](https://github.com/the-luap/picpeak/issues/312), [#313](https://github.com/the-luap/picpeak/issues/313)) ([d3f1206](https://github.com/the-luap/picpeak/commit/d3f12068164a6bfe6c4a3817ad2fc2e8ed7abf4f)) +* pre-zip download all and photo replacement by name ([#312](https://github.com/the-luap/picpeak/issues/312), [#313](https://github.com/the-luap/picpeak/issues/313)) ([e18afd3](https://github.com/the-luap/picpeak/commit/e18afd3e6b0b5a4cdb4873fb227d1b1d2bf35f21)) +* presigned download UI + S3 prefix walker auto-importer (follow-ups) ([446d80a](https://github.com/the-luap/picpeak/commit/446d80a4cc5eb0389994e29585b2a98dad373db2)) +* public v1 API + token management + OpenAPI docs ([#322](https://github.com/the-luap/picpeak/issues/322)) ([808b15b](https://github.com/the-luap/picpeak/commit/808b15bafbcdab6ea55aff7f0e507153f513a70a)) +* register Russian locale and add to language selector ([6f95b8c](https://github.com/the-luap/picpeak/commit/6f95b8c26cd794525e15e45d478f9ead0ec22555)) +* S3 storage + webhooks + settings dedupe + backup fixes ([06d54be](https://github.com/the-luap/picpeak/commit/06d54bec4d0afc4a1b9ba6f2449ed7d79f1d3e8f)) +* show original filename in admin UI ([#184](https://github.com/the-luap/picpeak/issues/184)) ([0891be1](https://github.com/the-luap/picpeak/commit/0891be197fdb7d92ade5a293b8db0bed26fa6e3a)) +* sort photos by capture date with configurable default sort ([#283](https://github.com/the-luap/picpeak/issues/283)) ([8805fa5](https://github.com/the-luap/picpeak/commit/8805fa53e61c6b3672a8f6dad14d2fd17998a451)) +* sort photos by capture date with configurable default sort ([#283](https://github.com/the-luap/picpeak/issues/283)) ([633d4a0](https://github.com/the-luap/picpeak/commit/633d4a0f301e355ee9f057347f2f8dee8c5b4163)) +* support Apple Silicon natively via multi-arch images ([c282a72](https://github.com/the-luap/picpeak/commit/c282a72bd35db062cec25770a42cf9c803388e44)) +* **theme:** expand color settings to 8-token CI palette + alt button ([114aab5](https://github.com/the-luap/picpeak/commit/114aab57771a4bba03a9e5c616c75a37c9b25969)) +* **upload:** async photo processing — backend (PR-B part 1) ([851744c](https://github.com/the-luap/picpeak/commit/851744c3c4df7deba8d946b6592fdb5042c52a26)) +* **upload:** async photo processing — frontend (PR-B part 2) ([3b827b8](https://github.com/the-luap/picpeak/commit/3b827b80d51269e1a7b9c693396f3cb7a9a48ffc)) +* **upload:** async photo processing + fix(auth): /auth/session symmetry (loop fix) ([907bcf1](https://github.com/the-luap/picpeak/commit/907bcf1eb2d44ded149a1caf39ee1cfe63fec994)) +* **upload:** two-state UI + temp dir cleanup (PR-A of async processing) ([86dfcc4](https://github.com/the-luap/picpeak/commit/86dfcc4f116a394e7e092ab3e01f3f1d030bb367)) +* visual WYSIWYG email template editor ([703c03f](https://github.com/the-luap/picpeak/commit/703c03fbee754a5291b57b885c5e82fbdd3e69e9)) +* warn about low thumbnail resolution when selecting beta themes ([ee3f6ae](https://github.com/the-luap/picpeak/commit/ee3f6ae13bf9c9fb3295286e84150e04bf9fbce4)) +* warn about low thumbnail resolution with beta themes ([aef9b4e](https://github.com/the-luap/picpeak/commit/aef9b4ed7fc443cbec8890c580759077e05e77b4)) +* **webhooks:** enrich event.* payloads with customer contact + share_token ([#341](https://github.com/the-luap/picpeak/issues/341)) ([7ea4801](https://github.com/the-luap/picpeak/commit/7ea4801544fd5cd8bca1907a71b5c4e96ee77649)) +* **webhooks:** enrich event.* payloads with customer contact + share_token ([#341](https://github.com/the-luap/picpeak/issues/341)) ([1e69d5f](https://github.com/the-luap/picpeak/commit/1e69d5ff71ac2d1d133b0e40637b437d7cc8bc4f)) ### Bug Fixes -* **events:** preserve branding inheritance when saving events with null color_theme ([d5a37df](https://github.com/the-luap/picpeak/commit/d5a37df2c41425511dc8a1f974088bebb768f0d5)) -* **lightbox+events:** Android download lag, multi-photo Web Share re-land, theme branding inheritance ([e016f51](https://github.com/the-luap/picpeak/commit/e016f510b6cc57a9ed1b59e2ee24fedd5d7097c3)) -* **lightbox:** eliminate download lag on Android by skipping the blob round-trip ([0479521](https://github.com/the-luap/picpeak/commit/04795219a0b66fdd1ef73748d803adfdfc0d676f)) - -## [3.54.7-beta.0](https://github.com/the-luap/picpeak/compare/v3.54.6-beta.0...v3.54.7-beta.0) (2026-05-26) - - -### Bug Fixes - -* **lightbox:** restrict Web Share save-to-Photos path to iOS ([#554](https://github.com/the-luap/picpeak/issues/554)) ([578397b](https://github.com/the-luap/picpeak/commit/578397bc6b27b56ccf3bf1f2f244e0e0053c493a)) -* **lightbox:** restrict Web Share save-to-Photos path to iOS ([#554](https://github.com/the-luap/picpeak/issues/554)) ([2a309c7](https://github.com/the-luap/picpeak/commit/2a309c75a74be3af3eb67758f8d65f801ef3019a)) - -## [3.54.6-beta.0](https://github.com/the-luap/picpeak/compare/v3.54.5-beta.0...v3.54.6-beta.0) (2026-05-25) - - -### Bug Fixes - -* **api/v1:** accept color_theme + create feedback row on event create ([#550](https://github.com/the-luap/picpeak/issues/550)) ([7ef0e40](https://github.com/the-luap/picpeak/commit/7ef0e40e7cee2ab6eeea4fe75c558e930e31241d)) -* **api/v1:** accept color_theme + create feedback row on event create ([#550](https://github.com/the-luap/picpeak/issues/550)) ([1b521e7](https://github.com/the-luap/picpeak/commit/1b521e761c3e2cc6c885d03ef746aa7e77e6f067)) - -## [3.54.5-beta.0](https://github.com/the-luap/picpeak/compare/v3.54.4-beta.0...v3.54.5-beta.0) (2026-05-22) - - -### Bug Fixes - -* **nginx:** honour outer X-Forwarded-Proto when behind a reverse proxy ([#547](https://github.com/the-luap/picpeak/issues/547)) ([b351d17](https://github.com/the-luap/picpeak/commit/b351d17ee99528dd4251e74dfc47cd1fe289d9c3)) -* **nginx:** honour outer X-Forwarded-Proto when behind a reverse proxy ([#547](https://github.com/the-luap/picpeak/issues/547)) ([5488de3](https://github.com/the-luap/picpeak/commit/5488de3383d33d8a037587dd9112d36ea035c465)) - -## [3.54.4-beta.0](https://github.com/the-luap/picpeak/compare/v3.54.3-beta.0...v3.54.4-beta.0) (2026-05-21) - - -### Bug Fixes - -* recover three orphaned commits from [#527](https://github.com/the-luap/picpeak/issues/527) (BRAND_TITLE runtime, Web Share, pan zoom) ([9607b46](https://github.com/the-luap/picpeak/commit/9607b4666c0abf22e54b43be3e87e3243db2cdbc)) - -## [3.54.3-beta.0](https://github.com/the-luap/picpeak/compare/v3.54.2-beta.0...v3.54.3-beta.0) (2026-05-21) - - -### Bug Fixes - -* **lightbox:** fill the heart icon when liked ([#538](https://github.com/the-luap/picpeak/issues/538) follow-up) ([3e39112](https://github.com/the-luap/picpeak/commit/3e39112a1276c194259d936dad813f3b0fc2dc3f)) -* **lightbox:** fill the heart icon when liked ([#538](https://github.com/the-luap/picpeak/issues/538) follow-up) ([600c29d](https://github.com/the-luap/picpeak/commit/600c29db8a75fa44e72da55bc5288908de614d9d)) - -## [3.54.2-beta.0](https://github.com/the-luap/picpeak/compare/v3.54.1-beta.0...v3.54.2-beta.0) (2026-05-20) - - -### Bug Fixes - -* **feedback:** three guest-mode bugs from [#538](https://github.com/the-luap/picpeak/issues/538) (filter, like state, count leak) ([c900be9](https://github.com/the-luap/picpeak/commit/c900be92dd490b21aabb10fd56b6fbc3da444ee0)) -* **feedback:** three guest-mode bugs reported in [#538](https://github.com/the-luap/picpeak/issues/538) ([5311588](https://github.com/the-luap/picpeak/commit/5311588baf3c6acfc971cb014a142d6b4b153aa1)) - -## [3.54.1-beta.0](https://github.com/the-luap/picpeak/compare/v3.54.0-beta.0...v3.54.1-beta.0) (2026-05-20) - - -### Bug Fixes - -* **public-site:** honor dark theme surface colors ([8b72721](https://github.com/the-luap/picpeak/commit/8b727218127db2a738ad5a4381358076c1575c8a)) - -## [3.54.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.53.0-beta.0...v3.54.0-beta.0) (2026-05-20) - - -### Features - -* **install:** skip legacy chain when modern bootstrap fingerprint detected ([#530](https://github.com/the-luap/picpeak/issues/530)) ([8f0108c](https://github.com/the-luap/picpeak/commit/8f0108ce233f457d6a0f4f3dbc3e1b0a7217e74e)) - - -### Bug Fixes - -* **install:** skip legacy chain on recovery-state DBs + schema-drift CI ([#530](https://github.com/the-luap/picpeak/issues/530)) ([a0ebc97](https://github.com/the-luap/picpeak/commit/a0ebc97cdd871041ff3cfdcc7276c413ac89d24f)) - -## [3.53.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.52.1-beta.0...v3.53.0-beta.0) (2026-05-19) - - -### Features - -* **events:** default Guest Feedback ON via admin setting ([#520](https://github.com/the-luap/picpeak/issues/520)) ([3465b55](https://github.com/the-luap/picpeak/commit/3465b55abc98e52cf58ba46b811f4ec115d53012)) - - -### Bug Fixes - -* **bug-batch-518:** lightbox comments toggle + further fixes ([633a2ae](https://github.com/the-luap/picpeak/commit/633a2ae72405ae1fc885cb710ed896476ffee467)) -* **header:** hide language name on mobile to free the title ([#523](https://github.com/the-luap/picpeak/issues/523)) ([4b4ecfd](https://github.com/the-luap/picpeak/commit/4b4ecfdf7143c8f353355ecd6d5ee14bbf50c9bb)) -* **lightbox:** hide comments toggle when allow_comments=false ([#518](https://github.com/the-luap/picpeak/issues/518)) ([d44e1ad](https://github.com/the-luap/picpeak/commit/d44e1adba7a444b03511e9402cd39d25fe5acafe)) -* **og:** brandable static title + wider crawler UA coverage ([#521](https://github.com/the-luap/picpeak/issues/521)) ([b960639](https://github.com/the-luap/picpeak/commit/b96063903513fcc4cbe0e72f59ccbc37d7b1c0ab)) - -## [3.52.1-beta.0](https://github.com/the-luap/picpeak/compare/v3.52.0-beta.0...v3.52.1-beta.0) (2026-05-18) - - -### Bug Fixes - -* **install:** self-chowning entrypoint kills fresh-install restart loop ([#484](https://github.com/the-luap/picpeak/issues/484)) ([42c5cda](https://github.com/the-luap/picpeak/commit/42c5cda38c0deeb4e61554e9e4a913bd5cd0b980)) - -## [3.52.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.51.5-beta.0...v3.52.0-beta.0) (2026-05-18) - - -### Features - -* **api/v1:** accept category_id on POST /events/:id/photos ([2d5a2ad](https://github.com/the-luap/picpeak/commit/2d5a2ad78a5f6c101315214399a9c158ff0549da)) -* **api/v1:** accept category_id on POST /events/:id/photos ([6901e26](https://github.com/the-luap/picpeak/commit/6901e2661ed74e69f19c52ce046ee911b818d463)) - - -### Bug Fixes - -* **api/v1:** scope category lookup to event_owned or global ([92bb9e1](https://github.com/the-luap/picpeak/commit/92bb9e1a12f77ce5e8c1286716198362b2bfdff2)) - -## [3.51.5-beta.0](https://github.com/the-luap/picpeak/compare/v3.51.4-beta.0...v3.51.5-beta.0) (2026-05-17) - - -### Bug Fixes - -* **email:** parse JSON-encoded language setting before using as locale ([ebc7da2](https://github.com/the-luap/picpeak/commit/ebc7da21bea90ff84f5351bef4fd3c2605d3a68f)) - -## [3.51.4-beta.0](https://github.com/the-luap/picpeak/compare/v3.51.3-beta.0...v3.51.4-beta.0) (2026-05-17) - - -### Bug Fixes - -* **categories:** strip diacritics from auto-generated slugs ([a747eb3](https://github.com/the-luap/picpeak/commit/a747eb351d1cf0ed269751cb685b504993d33dde)) - -## [3.51.3-beta.0](https://github.com/the-luap/picpeak/compare/v3.51.2-beta.0...v3.51.3-beta.0) (2026-05-16) - - -### Bug Fixes - -* **i18n:** settings page resets UI language to server default ([482e91b](https://github.com/the-luap/picpeak/commit/482e91bbf8b8deee361ffc8b031094fb99cc569d)) - -## [3.51.2-beta.0](https://github.com/the-luap/picpeak/compare/v3.51.1-beta.0...v3.51.2-beta.0) (2026-05-16) - - -### Bug Fixes - -* **i18n:** drive customer "Preferred language" select from SUPPORTED_LANGUAGES ([#510](https://github.com/the-luap/picpeak/issues/510)) ([51890e1](https://github.com/the-luap/picpeak/commit/51890e1aa5bacb5cfb5c9dc6e59770bd18406a66)) - -## [3.51.1-beta.0](https://github.com/the-luap/picpeak/compare/v3.51.0-beta.0...v3.51.1-beta.0) (2026-05-16) - - -### Bug Fixes - -* **install:** silence clean-install postgres log noise ([#484](https://github.com/the-luap/picpeak/issues/484)) ([99e60a2](https://github.com/the-luap/picpeak/commit/99e60a243321a06f659d811babbcda9ffef655c4)) -* **install:** silence clean-install postgres log noise ([#484](https://github.com/the-luap/picpeak/issues/484)) ([86b33d4](https://github.com/the-luap/picpeak/commit/86b33d4ddaf98e1f32473832b0f89565750174e5)) - -## [3.51.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.50.0-beta.0...v3.51.0-beta.0) (2026-05-14) - - -### Features - -* **downloads:** preserve original camera filenames on download (opt-in) ([#493](https://github.com/the-luap/picpeak/issues/493)) ([826e43e](https://github.com/the-luap/picpeak/commit/826e43ebac940782be234630c50bbd54a3250f98)) - -## [3.50.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.49.6-beta.0...v3.50.0-beta.0) (2026-05-14) - - -### Features - -* **lightbox:** medium-resolution preview tier ([#492](https://github.com/the-luap/picpeak/issues/492)) ([3083c74](https://github.com/the-luap/picpeak/commit/3083c748b92fe7800044125524d053f5eeb28d4a)) -* **lightbox:** medium-resolution preview tier ([#492](https://github.com/the-luap/picpeak/issues/492)) ([61f1d13](https://github.com/the-luap/picpeak/commit/61f1d132104f485cfde9bd874e1c0ffdc042c4af)) - -## [3.49.6-beta.0](https://github.com/the-luap/picpeak/compare/v3.49.5-beta.0...v3.49.6-beta.0) (2026-05-14) - - -### Bug Fixes - -* **install:** defer events.hero_photo_id FK to break circular reference ([#484](https://github.com/the-luap/picpeak/issues/484)) ([62b3ed6](https://github.com/the-luap/picpeak/commit/62b3ed636414d358c0c73712b732207fc6fa1200)) -* **install:** defer events.hero_photo_id FK to break circular reference ([#484](https://github.com/the-luap/picpeak/issues/484)) ([87834a7](https://github.com/the-luap/picpeak/commit/87834a7fff57a53bb1060ad7061dd6d279922f42)) - -## [3.49.5-beta.0](https://github.com/the-luap/picpeak/compare/v3.49.4-beta.0...v3.49.5-beta.0) (2026-05-14) - - -### Bug Fixes - -* **admin-users:** normalise date fields to ISO across DB drivers ([#485](https://github.com/the-luap/picpeak/issues/485)) ([d300426](https://github.com/the-luap/picpeak/commit/d3004263905edeffe59065e201f203a6768b4384)) -* **admin-users:** normalise date fields to ISO across DB drivers ([#485](https://github.com/the-luap/picpeak/issues/485)) ([b6b58d0](https://github.com/the-luap/picpeak/commit/b6b58d0659fc8caee68a65e112780a1122d55907)) - -## [3.49.4-beta.0](https://github.com/the-luap/picpeak/compare/v3.49.3-beta.0...v3.49.4-beta.0) (2026-05-14) - - -### Bug Fixes - -* **install:** drop racy migration step + add missing frontend container ([#484](https://github.com/the-luap/picpeak/issues/484)) ([d4155c4](https://github.com/the-luap/picpeak/commit/d4155c46117eb1db6255ebac0ea47e6fc3e99801)) -* **install:** silence pg healthcheck noise + drop legacy workers container ([#484](https://github.com/the-luap/picpeak/issues/484)) ([d39406b](https://github.com/the-luap/picpeak/commit/d39406b2414cdfcae84e8175d90821dd3a5287bb)) -* **install:** silence pg healthcheck noise + drop legacy workers container ([#484](https://github.com/the-luap/picpeak/issues/484)) ([0b0b1bb](https://github.com/the-luap/picpeak/commit/0b0b1bb2d529dbaae8e49891d8d5e8019b971838)) - -## [3.49.3-beta.0](https://github.com/the-luap/picpeak/compare/v3.49.2-beta.0...v3.49.3-beta.0) (2026-05-14) - - -### Bug Fixes - -* **promo-banner:** center by default + admin alignment selector ([#482](https://github.com/the-luap/picpeak/issues/482)) ([d1034ce](https://github.com/the-luap/picpeak/commit/d1034ce1c65c31b06005cfd0c047dba3251579ab)) -* **promo-banner:** center by default + admin alignment selector ([#482](https://github.com/the-luap/picpeak/issues/482)) ([a803491](https://github.com/the-luap/picpeak/commit/a803491cf477c0d62e23d6a019e0d252e2c537f8)) - -## [3.49.2-beta.0](https://github.com/the-luap/picpeak/compare/v3.49.1-beta.0...v3.49.2-beta.0) (2026-05-13) - - -### Bug Fixes - -* **ci:** pin TRIVY_PLATFORM per matrix arch (post-[#477](https://github.com/the-luap/picpeak/issues/477) follow-up) ([6750f5d](https://github.com/the-luap/picpeak/commit/6750f5d3b06f6312629e81c4c84100c572746b69)) -* **ci:** pin TRIVY_PLATFORM per matrix arch (post-[#477](https://github.com/the-luap/picpeak/issues/477) follow-up) ([c3256dc](https://github.com/the-luap/picpeak/commit/c3256dc6bf49a2352dfe38b804d757683bb3ac22)) - -## [3.49.1-beta.0](https://github.com/the-luap/picpeak/compare/v3.49.0-beta.0...v3.49.1-beta.0) (2026-05-13) - - -### Bug Fixes - -* **ci:** scan multi-arch images per-arch by digest, pin trivy-action ([#476](https://github.com/the-luap/picpeak/issues/476)) ([1144e9d](https://github.com/the-luap/picpeak/commit/1144e9d1625eb69d8e2a53b1a3aa1b515798fc80)) - -## [3.49.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.48.1-beta.0...v3.49.0-beta.0) (2026-05-13) - - -### Features - -* **og:** per-event opt-in to use hero photo as social-share preview ([#474](https://github.com/the-luap/picpeak/issues/474)) ([d856340](https://github.com/the-luap/picpeak/commit/d856340f0d230ad26539ba1088f739f03aaafc13)) -* **og:** per-event opt-in to use hero photo as social-share preview ([#474](https://github.com/the-luap/picpeak/issues/474)) ([0bc7e2a](https://github.com/the-luap/picpeak/commit/0bc7e2af171d1a4c6e91ba541d293b90c17c111b)) - -## [3.48.1-beta.0](https://github.com/the-luap/picpeak/compare/v3.48.0-beta.0...v3.48.1-beta.0) (2026-05-12) - - -### Bug Fixes - -* **customer-routes:** Cache-Control: no-store on customer endpoints ([#470](https://github.com/the-luap/picpeak/issues/470)) ([3122dd0](https://github.com/the-luap/picpeak/commit/3122dd08a8bc08deb937236aaa3f750119a979b9)) - -## [3.48.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.47.2-beta.0...v3.48.0-beta.0) (2026-05-12) - - -### Features - -* **customers:** "Manage galleries" dialog on customer detail page ([6d1af7a](https://github.com/the-luap/picpeak/commit/6d1af7a0113b6e3de44ab9bf2645591f4d6d68b4)) -* **customers:** "Manage galleries" dialog with immediate access revocation + section reorder + portal-flag revert ([9be9296](https://github.com/the-luap/picpeak/commit/9be9296eb58d7733d0b5f8ce6eb48e9832f65e7c)) -* **customers:** email customer when admin adds new gallery access ([c02c947](https://github.com/the-luap/picpeak/commit/c02c947463011de80d9af3e947fc6d1caadc3313)) -* **customers:** replace-assignments endpoint for a single customer ([5377b88](https://github.com/the-luap/picpeak/commit/5377b88e0e0c27ecde18c2a366fb7d06f279f2ec)) -* **gallery:** revoke customer-minted JWTs when assignment is removed ([55a5846](https://github.com/the-luap/picpeak/commit/55a5846f6f802a1bc1910bb046325fe272a1b584)) - - -### Bug Fixes - -* **customer:** don't log customer out on transient session-refresh errors ([9e418c7](https://github.com/the-luap/picpeak/commit/9e418c759ce508adf6025e0740468d8229938ffe)) +* add allow_user_uploads to gallery API responses ([691e3ab](https://github.com/the-luap/picpeak/commit/691e3aba09f2148afe902a0bb0139d062634e669)) +* add lightbox loading spinner and watermark cache invalidation ([050ed37](https://github.com/the-luap/picpeak/commit/050ed378199eb3b15c7c7f243792f68f858803f5)) +* add STORAGE_PATH to production docker-compose ([cdda709](https://github.com/the-luap/picpeak/commit/cdda70988664a177b351abc6a259ec39664d17ff)) +* address beta feedback - gallery layout fixes, Russian locale, email logo ([#249](https://github.com/the-luap/picpeak/issues/249)) ([486239a](https://github.com/the-luap/picpeak/commit/486239aeb9b5f56551d5aa90f0bad3008eedc3bb)) +* address bugs and feature requests from discussion [#317](https://github.com/the-luap/picpeak/issues/317) ([6cfff6f](https://github.com/the-luap/picpeak/commit/6cfff6f6a6dbdc5bc1e9fe4fbce5795cdb1855c6)) +* address Shannon security assessment findings (37 vulnerabilities) ([#254](https://github.com/the-luap/picpeak/issues/254)) ([23cd9cb](https://github.com/the-luap/picpeak/commit/23cd9cb680eb77b94a97266c3353dfc835f0cc69)) +* admin photo feedback filters have no effect ([#293](https://github.com/the-luap/picpeak/issues/293)) ([9ed8a2b](https://github.com/the-luap/picpeak/commit/9ed8a2b1994d139efd100c8fb97e6368655e5530)) +* **admin:** tab underlines use accent (not accent-dark) for proper highlight color ([565ae45](https://github.com/the-luap/picpeak/commit/565ae45ca71e46166c8bbfc0eb0b6da92d74f120)) +* apply password change fix to regular modal + longer toast delay ([#263](https://github.com/the-luap/picpeak/issues/263)) ([c63bc47](https://github.com/the-luap/picpeak/commit/c63bc47089b4b32c570bdeeb1f82bf722569875f)) +* apply password change redirect fix to regular modal too ([#263](https://github.com/the-luap/picpeak/issues/263)) ([147dc28](https://github.com/the-luap/picpeak/commit/147dc28440ca69ed970677fa221dfac00c8e2560)) +* apply sort direction in gallery and respect show_feedback_to_guests ([#302](https://github.com/the-luap/picpeak/issues/302), [#303](https://github.com/the-luap/picpeak/issues/303)) ([3716ff5](https://github.com/the-luap/picpeak/commit/3716ff50854766bde588fbd6b9027f8647e59150)) +* apply sort direction in gallery view and respect show_feedback_to_guests ([#302](https://github.com/the-luap/picpeak/issues/302), [#303](https://github.com/the-luap/picpeak/issues/303)) ([dffe057](https://github.com/the-luap/picpeak/commit/dffe057772c922ab6a213e25f171157e0c2badf8)) +* **auth:** /auth/session must enforce session timeout symmetrically ([#350](https://github.com/the-luap/picpeak/issues/350) recurrence) ([c8e09c2](https://github.com/the-luap/picpeak/commit/c8e09c2a2a7d0920901560317eecd773b83251c0)) +* **auth:** /auth/session must enforce session timeout symmetrically ([#350](https://github.com/the-luap/picpeak/issues/350) recurrence) ([b106da1](https://github.com/the-luap/picpeak/commit/b106da1ededa27fc8727f2c0e74a9182e6e9c895)) +* **auth:** /auth/session must reject tokens that adminAuth/galleryAuth would reject ([f905f7e](https://github.com/the-luap/picpeak/commit/f905f7e7336c756e73a8c650c9239b171697164a)) +* **auth:** /auth/session must verify issuer claim like adminAuth ([#350](https://github.com/the-luap/picpeak/issues/350)) ([83dedbc](https://github.com/the-luap/picpeak/commit/83dedbcd45e34a924594dd83f6e3561f776576fb)) +* **auth:** make /auth/session verify the issuer claim like adminAuth ([#350](https://github.com/the-luap/picpeak/issues/350)) ([88a6c6a](https://github.com/the-luap/picpeak/commit/88a6c6a7fba7e1419a021f4870518f0b76ac6494)) +* **backup:** cron schedule mapping + manifest format detection + bigint coerce ([ab4095f](https://github.com/the-luap/picpeak/commit/ab4095f5928b1476009cddfd3444d6f5b58b034d)) +* **backup:** incremental backups against S3 + jsonb stats parsing ([e232f9f](https://github.com/the-luap/picpeak/commit/e232f9f2cf54aeba1e16d769397428206a0f1801)) +* **branding:** admin sidebar uses accent-dark, primary buttons follow CI token ([fc2bce3](https://github.com/the-luap/picpeak/commit/fc2bce3a01f02b2d131ca4ce1c8e81fc9dc62755)) +* **branding:** comprehensive sweep — replace remaining primary-* legacy colors with accent tokens ([578a174](https://github.com/the-luap/picpeak/commit/578a1745b8d010eeeb261d3452fd192b1ec7bcf8)) +* **branding:** selected-state accent colors, force-mode actually flips galleries, compact color picker layout ([5b410ed](https://github.com/the-luap/picpeak/commit/5b410ed9f87daad8e96345a86897f2a9e9419802)) +* **branding:** working tooltips, high-contrast selected states, gallery chrome follows accent ([b19bb0c](https://github.com/the-luap/picpeak/commit/b19bb0c6208744f329cb3e99f4e26a83f191710a)) +* checkbox and toggle settings not persisting after page refresh ([808ed1d](https://github.com/the-luap/picpeak/commit/808ed1d2f1164d9fd1114586c68a1f925bf73ddf)), closes [#117](https://github.com/the-luap/picpeak/issues/117) +* **cms:** apply dark mode to CMS editor, public CMS, and admin modals ([d2a10f6](https://github.com/the-luap/picpeak/commit/d2a10f6523655488267d6f68835d7adb46dcf962)) +* **cms:** nl/pt/ru i18n + gate external_url in public response ([08d0462](https://github.com/the-luap/picpeak/commit/08d046276bf259e8511b01415141f51b8484f967)) +* **cms:** nl/pt/ru i18n + gate external_url in public response ([bce5c1f](https://github.com/the-luap/picpeak/commit/bce5c1f725043965c2499515f18e93e9578bd204)) +* correct invitation activation validation and add missing translations ([991aa98](https://github.com/the-luap/picpeak/commit/991aa98f98cffd1d7785c272726615325e2c0208)), closes [#129](https://github.com/the-luap/picpeak/issues/129) +* correct invitation email link URL path ([86fa104](https://github.com/the-luap/picpeak/commit/86fa1046d5439cb451feb164175c919c49ca219a)), closes [#129](https://github.com/the-luap/picpeak/issues/129) +* correct storage path resolution in multiple files ([#96](https://github.com/the-luap/picpeak/issues/96)) ([0e3674b](https://github.com/the-luap/picpeak/commit/0e3674b2b0325bbcee5aa2c9ff7781da92f612d1)) +* correct storage path resolution in multiple files ([#96](https://github.com/the-luap/picpeak/issues/96)) ([3ccb815](https://github.com/the-luap/picpeak/commit/3ccb8154eb40a432aa467fb06b3f216fd0d2c6b4)) +* database migration restart bug, lightbox loading spinner, and watermark cache invalidation ([7c58749](https://github.com/the-luap/picpeak/commit/7c5874980640ae8c3d1050ce24daeb0a2aeab7a3)) +* dedupe parallel admin 401 redirects to /admin/login ([038e84c](https://github.com/the-luap/picpeak/commit/038e84cae7f56a0a1af8c71b85881ca5d320c6e3)) +* discussion [#317](https://github.com/the-luap/picpeak/issues/317) issues and [#318](https://github.com/the-luap/picpeak/issues/318) archive crash ([2f2f405](https://github.com/the-luap/picpeak/commit/2f2f405d9bc2831b3bbe2ca7fbf726d61382dc38)) +* display welcome message in gallery and fix guest thumbnail URLs ([#306](https://github.com/the-luap/picpeak/issues/306), [#307](https://github.com/the-luap/picpeak/issues/307)) ([b05c36a](https://github.com/the-luap/picpeak/commit/b05c36ac810a557a2ac088ab7bec39bb76f9a2ae)) +* display welcome message in gallery and fix guest thumbnail URLs ([#306](https://github.com/the-luap/picpeak/issues/306), [#307](https://github.com/the-luap/picpeak/issues/307)) ([9323bef](https://github.com/the-luap/picpeak/commit/9323befdd99d64b85cca89af24ac1b7034d72eee)) +* docker compose v2 syntax and add missing ADMIN_PASSWORD to .env.example ([#189](https://github.com/the-luap/picpeak/issues/189)) ([0817443](https://github.com/the-luap/picpeak/commit/0817443e793e37c770c6a1968ecae4b9464107b0)) +* **docker:** install system ffmpeg on Alpine, drop broken bundled binary ([3ab8a64](https://github.com/the-luap/picpeak/commit/3ab8a64a24f1600e674f77d39139e33857b4dfc8)) +* **docker:** install system ffmpeg on Alpine, drop broken bundled binary ([96818c7](https://github.com/the-luap/picpeak/commit/96818c7ae8de0d8fd478cd901ea25a3272eee85d)) +* dynamic website title from branding settings ([4701edc](https://github.com/the-luap/picpeak/commit/4701edc12ecfab27cb2d1cfb0b4ed4fd53f56cc6)) +* **email:** render conditionals, localise password placeholders, fix caller/template variable drift ([0767203](https://github.com/the-luap/picpeak/commit/07672038d4ac31fc601adfb2338104223856ba71)) +* **email:** render conditionals, localise password placeholders, fix caller/template variable drift ([e8052ad](https://github.com/the-luap/picpeak/commit/e8052adf1d2f1717652ac5d6b8cd8bcc01787189)) +* event-specific custom CSS settings not being saved ([dadef81](https://github.com/the-luap/picpeak/commit/dadef81158972d28aa32812203500f77ed08a999)), closes [#136](https://github.com/the-luap/picpeak/issues/136) +* events search/counters ([#346](https://github.com/the-luap/picpeak/issues/346)), lazy gallery skeleton ([#321](https://github.com/the-luap/picpeak/issues/321)), smooth lightbox swipe ([#348](https://github.com/the-luap/picpeak/issues/348)) ([6229b38](https://github.com/the-luap/picpeak/commit/6229b38bac90cc0c538a72688efae3be77a3bb08)) +* events without expiration date incorrectly shown as expired ([c4f16eb](https://github.com/the-luap/picpeak/commit/c4f16eb76c909158abdb63aa4cc22f817f274dc5)) +* **events:** admin-set password on reset, full-URL gallery_link in all emails ([0d1f82d](https://github.com/the-luap/picpeak/commit/0d1f82d31a2f9e30bf193496ac203eaf8dfd856b)) +* **events:** admin-set password on reset, full-URL gallery_link in all emails ([ff50c74](https://github.com/the-luap/picpeak/commit/ff50c74e1912ccba60f7ccdbead92b76de91388b)) +* **events:** coerce expires_in_days to Number before addDays ([e5712d8](https://github.com/the-luap/picpeak/commit/e5712d8ffe2f0ed980e1df5e1263876af7202b76)) +* **events:** coerce expires_in_days to Number before addDays ([db29d0e](https://github.com/the-luap/picpeak/commit/db29d0e2788f63cc9eb0a43ec58313387acb0c0d)) +* **events:** match scrollbar to theme in external folder tree picker ([bd42ee1](https://github.com/the-luap/picpeak/commit/bd42ee1ce03b8f6e7b011b53f2c71453be931cc6)) +* **events:** server-side search/pagination to remove first-100 cap ([#346](https://github.com/the-luap/picpeak/issues/346)) ([a5b20ca](https://github.com/the-luap/picpeak/commit/a5b20ca3fe77df665d4a9744413d7ee4054858f0)) +* **events:** show customer phone in event details view ([#331](https://github.com/the-luap/picpeak/issues/331)) ([4c73d22](https://github.com/the-luap/picpeak/commit/4c73d228ed98b8ec05bec2824aee7ce066a184e1)) +* **events:** stop mapping branding_logo_position onto hero_logo_position ([af2b062](https://github.com/the-luap/picpeak/commit/af2b0628cb4f79a147366665d35c098012071216)) +* **events:** stop mapping branding_logo_position onto hero_logo_position ([ef1c875](https://github.com/the-luap/picpeak/commit/ef1c875f6ec1e02657006cb09cd0b1d868ec2fc0)) +* external media dimensions, theme race condition, email color customization ([dfae2c2](https://github.com/the-luap/picpeak/commit/dfae2c2bc6d86378c553cd847b439f7cb53a4f2a)) +* floor password_changed_at when comparing against JWT iat ([793e410](https://github.com/the-luap/picpeak/commit/793e410554b461522fbe24014dfd3baa915da2bb)) +* **fonts:** drop immutable Cache-Control to allow font replacement rollout ([5703fcb](https://github.com/the-luap/picpeak/commit/5703fcb80680155e3b637dd5fc15c430de963c40)) +* **gallery:** default controls to inline for every layout ([045e9ea](https://github.com/the-luap/picpeak/commit/045e9ea4861f33e3e82e31f978ac297c7f7824f6)) +* **gallery:** lazy-render skeleton grid for fast loads ([#321](https://github.com/the-luap/picpeak/issues/321) follow-up) ([d9d8137](https://github.com/the-luap/picpeak/commit/d9d81372b80f7d44dca54b7993f52c36574048c9)) +* **gallery:** preserve sidebar controlsStyle on banner migration ([05dadff](https://github.com/the-luap/picpeak/commit/05dadff4934ad9b055de8875846c2a7175e16f86)) +* **gallery:** single-finger swipe nav in mobile lightbox ([#332](https://github.com/the-luap/picpeak/issues/332)) ([4c8eba0](https://github.com/the-luap/picpeak/commit/4c8eba0cb43635d92a53d90c58b19007136c1c12)) +* **gallery:** use ref for swipe-start to avoid stale-closure miss ([#332](https://github.com/the-luap/picpeak/issues/332)) ([fcddfe0](https://github.com/the-luap/picpeak/commit/fcddfe094b2a01963f7b420afa886e7d5dae4390)) +* **gallery:** WCAG-safe Download button text + extract HeaderDownloadButton ([#401](https://github.com/the-luap/picpeak/issues/401) follow-ups) ([04e928d](https://github.com/the-luap/picpeak/commit/04e928d7621743d9d99797f0996f8c7aa50e7b2d)) +* **gallery:** WCAG-safe Download button text + extract HeaderDownloadButton ([#401](https://github.com/the-luap/picpeak/issues/401) follow-ups) ([0c80abd](https://github.com/the-luap/picpeak/commit/0c80abd57b806b9df01429a093c30c12c80c0601)) +* guest feedback flow bugs in Masonry grid and PhotoLightbox ([#292](https://github.com/the-luap/picpeak/issues/292)) ([54badef](https://github.com/the-luap/picpeak/commit/54badefc51b834d55530722f87c81a6ade33e35b)) +* guest feedback flow bugs in Masonry grid and PhotoLightbox ([#292](https://github.com/the-luap/picpeak/issues/292)) ([77f07e9](https://github.com/the-luap/picpeak/commit/77f07e9329e47f6ac5040f2e85d2710ebbea3ced)) +* handle null dates in dashboard and gallery pages ([c5a8ffc](https://github.com/the-luap/picpeak/commit/c5a8ffc08cd4c53c37fe4fb9cde8519a68f1f343)) +* hero header state and preview in admin theme editor ([#158](https://github.com/the-luap/picpeak/issues/158)) ([f554f46](https://github.com/the-luap/picpeak/commit/f554f463b3492346dba067c0980b52ef42dd5e70)) +* improve ghost button visibility in admin dark mode ([4912e2b](https://github.com/the-luap/picpeak/commit/4912e2bccf282134d5598a8ac80942ed46d0523c)) +* improve password validation errors and event list UX ([#170](https://github.com/the-luap/picpeak/issues/170), [#171](https://github.com/the-luap/picpeak/issues/171)) ([171abb3](https://github.com/the-luap/picpeak/commit/171abb31615484d77cf95a99cb5634afa0160adc)) +* improve photo serving, category filters, and upload chunking ([#155](https://github.com/the-luap/picpeak/issues/155), [#156](https://github.com/the-luap/picpeak/issues/156), [#161](https://github.com/the-luap/picpeak/issues/161)) ([fa4c838](https://github.com/the-luap/picpeak/commit/fa4c83812d87cfa63394e51186e320a072929d37)) +* increase upload limit to 1GB and fix category filters ([#155](https://github.com/the-luap/picpeak/issues/155), [#156](https://github.com/the-luap/picpeak/issues/156)) ([397d33a](https://github.com/the-luap/picpeak/commit/397d33a95a09e0b0986c3f6cf5965c544992a764)) +* issue [#203](https://github.com/the-luap/picpeak/issues/203) file type validation + security CVE fixes ([8017171](https://github.com/the-luap/picpeak/commit/80171713e0ffedda56f7cffb403b25a8d55634d1)) +* **lightbox:** mobile toolbar clipping + iOS safe-area + viewport-fit ([#336](https://github.com/the-luap/picpeak/issues/336)) ([42a7ae4](https://github.com/the-luap/picpeak/commit/42a7ae4be8fe7b12104ae036465c9c4117606378)) +* **lightbox:** smooth carousel swipe + drop instructional hint ([#348](https://github.com/the-luap/picpeak/issues/348)) ([743086d](https://github.com/the-luap/picpeak/commit/743086d3cb9100fb163bc9d04d968e5b611a1f99)) +* mobile lightbox + share previews + customer phone bug triage ([1e40677](https://github.com/the-luap/picpeak/commit/1e4067713ce9a808a7b49319bc262e5c9a6599c6)) +* mobile upload button not visible in gallery ([#113](https://github.com/the-luap/picpeak/issues/113)) ([cacaffa](https://github.com/the-luap/picpeak/commit/cacaffa5c39f67105c4cfb092ea62157121fb72e)) +* mobile upload button visibility in gallery ([2a2c23d](https://github.com/the-luap/picpeak/commit/2a2c23d11610e6c81684163eb4ea934a6d6104fb)), closes [#113](https://github.com/the-luap/picpeak/issues/113) +* mobile upload button visibility in gallery ([df7dbff](https://github.com/the-luap/picpeak/commit/df7dbffbffb180e62af0d2b58326f9de0f515439)), closes [#113](https://github.com/the-luap/picpeak/issues/113) +* mobile upload button visibility in gallery ([#113](https://github.com/the-luap/picpeak/issues/113)) ([05a5307](https://github.com/the-luap/picpeak/commit/05a5307e22dc45be4b75b2996ff9fac65dec399d)) +* mobile upload button visibility in gallery ([#113](https://github.com/the-luap/picpeak/issues/113)) ([6cb4342](https://github.com/the-luap/picpeak/commit/6cb43428d1e703267edeacda9ede050a8c4f8e0c)) +* **nginx:** proxy /fonts requests to backend ([e6c03e4](https://github.com/the-luap/picpeak/commit/e6c03e4b6e4ee2ccc3e3cd8b7a54c18f9685c2ba)) +* pin npm to v10 in backend Dockerfile ([ddefd3a](https://github.com/the-luap/picpeak/commit/ddefd3a95e5047d4a22aa4b6fef57dfb1c880967)) +* pin npm upgrade to v10 in backend Dockerfile ([978e447](https://github.com/the-luap/picpeak/commit/978e4473b5227ee61ad7d17487063eb3284bea36)) +* prevent backend crash on archive when admin_email is null ([#318](https://github.com/the-luap/picpeak/issues/318)) ([e4b0f96](https://github.com/the-luap/picpeak/commit/e4b0f961b75952b6907cc2291fa256215c09c80c)) +* prevent database migration restart failures ([83a4344](https://github.com/the-luap/picpeak/commit/83a4344a01de4f65c5024fdf2d177a04457ccd2f)), closes [#107](https://github.com/the-luap/picpeak/issues/107) +* remove non-functional watermark toggle from Feature Toggles ([d4a15db](https://github.com/the-luap/picpeak/commit/d4a15dbe74d0d70bbe6ff03362dc7337fb8f4c5c)) +* render minimal/none header styles, cap hero height, switch category hero images ([#158](https://github.com/the-luap/picpeak/issues/158), [#162](https://github.com/the-luap/picpeak/issues/162), [#163](https://github.com/the-luap/picpeak/issues/163)) ([bc6c48b](https://github.com/the-luap/picpeak/commit/bc6c48bb2429505c2de3641693a8ff4f623a4951)) +* resend gallery email fails for events without password ([6b3ead7](https://github.com/the-luap/picpeak/commit/6b3ead747b1395d8ea2b3d135a5ac24db05e2eb8)), closes [#137](https://github.com/the-luap/picpeak/issues/137) +* resolve admin invitation flow issues and improve STORAGE_PATH documentation ([41bf6ff](https://github.com/the-luap/picpeak/commit/41bf6ff884d5ef3181f95f3aa4a528434c23947a)) +* resolve code quality issues and add missing i18n keys ([#162](https://github.com/the-luap/picpeak/issues/162), [#163](https://github.com/the-luap/picpeak/issues/163)) ([329d224](https://github.com/the-luap/picpeak/commit/329d224846d3f4eefa31e42337f34047c267d578)) +* resolve code scanning security alerts (multer, tar, Node 22) ([85a07fc](https://github.com/the-luap/picpeak/commit/85a07fcca7ad935f4c0c300f5ffe2f3af8da1e5f)) +* resolve external media dimensions, gallery theme race condition, and add email color customization ([bbeedd1](https://github.com/the-luap/picpeak/commit/bbeedd1888561b6c57586b5f42bbfee3ffc69fd7)) +* resolve issues [#194](https://github.com/the-luap/picpeak/issues/194), [#195](https://github.com/the-luap/picpeak/issues/195), [#196](https://github.com/the-luap/picpeak/issues/196), [#197](https://github.com/the-luap/picpeak/issues/197) ([33af088](https://github.com/the-luap/picpeak/commit/33af0885607799e0071e2e74a582c7eb396c9b83)) +* resolve issues [#194](https://github.com/the-luap/picpeak/issues/194), [#195](https://github.com/the-luap/picpeak/issues/195), [#196](https://github.com/the-luap/picpeak/issues/196), [#197](https://github.com/the-luap/picpeak/issues/197) ([5ea4ef3](https://github.com/the-luap/picpeak/commit/5ea4ef3cf36b06f9e6c9108f80bfe2e9a6470898)) +* resolve issues [#194](https://github.com/the-luap/picpeak/issues/194), [#195](https://github.com/the-luap/picpeak/issues/195), [#196](https://github.com/the-luap/picpeak/issues/196), [#197](https://github.com/the-luap/picpeak/issues/197) ([33483cf](https://github.com/the-luap/picpeak/commit/33483cf32dfae57f8da51c0765353792239135f9)) +* resolve issues [#194](https://github.com/the-luap/picpeak/issues/194), [#195](https://github.com/the-luap/picpeak/issues/195), [#196](https://github.com/the-luap/picpeak/issues/196), [#197](https://github.com/the-luap/picpeak/issues/197) ([cd00bc1](https://github.com/the-luap/picpeak/commit/cd00bc13d4e02a86a0f1742ed1f11f064614b8da)) +* resolve JWT iat timing issue in password change ([#263](https://github.com/the-luap/picpeak/issues/263)) ([c031b1e](https://github.com/the-luap/picpeak/commit/c031b1e86333d90e8e0e0aa723572efa110f7fd1)) +* resolve mixed light/dark mode styling in admin UI ([#175](https://github.com/the-luap/picpeak/issues/175)) ([f8c8abd](https://github.com/the-luap/picpeak/commit/f8c8abd70bbae35d6cd519894624ade33b5115a8)) +* resolve password change redirect loop ([#263](https://github.com/the-luap/picpeak/issues/263)) and file watcher crash ([#269](https://github.com/the-luap/picpeak/issues/269)) ([b23c51b](https://github.com/the-luap/picpeak/commit/b23c51b386270dee4d911902b728dfacb1ff1bf9)) +* resolve password change redirect loop and file watcher crash ([835bdf5](https://github.com/the-luap/picpeak/commit/835bdf5abb40c7b143c5cdafb507c317a7c349bf)), closes [#269](https://github.com/the-luap/picpeak/issues/269) +* resolve redirect loop after mandatory password change ([#263](https://github.com/the-luap/picpeak/issues/263)) ([07fc5e6](https://github.com/the-luap/picpeak/commit/07fc5e6519cd84f2214479d5f31bc35a495bfe4b)) +* resolve redirect loop after mandatory password change ([#263](https://github.com/the-luap/picpeak/issues/263)) ([3c8d344](https://github.com/the-luap/picpeak/commit/3c8d344ddd23974c9cf0f5f63edd6cd07817fee9)) +* respect allowed_file_types setting for upload validation ([#203](https://github.com/the-luap/picpeak/issues/203)) ([fe07a14](https://github.com/the-luap/picpeak/commit/fe07a148f1d998c0be00377c1f8b4eca3908305c)) +* respect optional email settings in event creation ([831ea6a](https://github.com/the-luap/picpeak/commit/831ea6a3bccfae4ec00ce1f619967b91b85150ce)) +* respect optional email settings in event creation ([#217](https://github.com/the-luap/picpeak/issues/217)) ([9c44a0e](https://github.com/the-luap/picpeak/commit/9c44a0ebfa527fa133512eb7f2f03335a2377aaa)) +* restore aspect-ratio layouts and improve hero image quality ([#180](https://github.com/the-luap/picpeak/issues/180)) ([3974ba5](https://github.com/the-luap/picpeak/commit/3974ba5de5a6605ad906608d3e4d61620a215059)) +* restore aspect-ratio layouts and improve hero image quality ([#180](https://github.com/the-luap/picpeak/issues/180)) ([5cef7fd](https://github.com/the-luap/picpeak/commit/5cef7fdd188389512bc4b55ae61536c8b1219eb8)) +* revert /api prefix in adminPhotos.js to avoid double-prefix ([094276d](https://github.com/the-luap/picpeak/commit/094276d3cc7117eee30e4bcbce487e54f0eacb29)) +* revert /api prefix in adminPhotos.js to avoid double-prefix ([#307](https://github.com/the-luap/picpeak/issues/307)) ([ceb2a09](https://github.com/the-luap/picpeak/commit/ceb2a09f483b4754fda232c5c1f7acb8971aac10)) +* **security:** invalidate tokens on password change, enforce session timeout, fix role update ([85a60a2](https://github.com/the-luap/picpeak/commit/85a60a2dc7526aa6b673e2a04e9fdfba7de7117f)) +* **security:** invalidate tokens on password change, enforce session timeout, fix role update ([f362239](https://github.com/the-luap/picpeak/commit/f3622396e77ce5d0b0741e439fc554a1dccaca50)) +* **security:** resolve all npm audit vulnerabilities ([4272618](https://github.com/the-luap/picpeak/commit/4272618b3f7fcb06aaca14fb724a6a7733251f24)) +* **security:** resolve Docker image CVEs for code scanning alerts ([cbecb93](https://github.com/the-luap/picpeak/commit/cbecb9323cf4b80c800326de14f6df73f60147c1)) +* **security:** token invalidation on password change, session timeout enforcement ([0a3a537](https://github.com/the-luap/picpeak/commit/0a3a53763c9f3caef9fdceccf9fdbfdefe9bd8bf)) +* **security:** token invalidation on password change, session timeout enforcement ([7ca9631](https://github.com/the-luap/picpeak/commit/7ca96315e254eef58d8ecc505f95a5186d2fa2da)) +* set JWT iat after password_changed_at to prevent token rejection ([#263](https://github.com/the-luap/picpeak/issues/263)) ([b1d1667](https://github.com/the-luap/picpeak/commit/b1d16670d56e19f7b35e7f2f12f3611fdb3fab58)) +* **share:** OG/Twitter-card metadata for gallery share URLs ([#333](https://github.com/the-luap/picpeak/issues/333)) ([5275621](https://github.com/the-luap/picpeak/commit/5275621fcd38f1ec09b54595163ecd5e63614b1a)) +* shorten Save button label on email template editor ([7250c42](https://github.com/the-luap/picpeak/commit/7250c427b905ffa3e8696dff607450f5a0b801b8)) +* show upload button in mobile topbar instead of sidebar ([ae181cf](https://github.com/the-luap/picpeak/commit/ae181cf92fc9c1e85cad7a7b843a4d83cec636ac)), closes [#113](https://github.com/the-luap/picpeak/issues/113) +* sync backend package-lock.json for security deps ([bb81fa5](https://github.com/the-luap/picpeak/commit/bb81fa5f4b5f1bd927a02470ce80a13c4f53443f)) +* sync backend package-lock.json with security dep updates ([03e1989](https://github.com/the-luap/picpeak/commit/03e19893b3532a27aa59e7b834d53c6a2b52b7cd)) +* sync header_style DB column with theme editor selections ([#158](https://github.com/the-luap/picpeak/issues/158)) ([2288309](https://github.com/the-luap/picpeak/commit/228830939553fd32c250704bb89a8ce233324d25)) +* sync header_style DB column with theme editor selections ([#158](https://github.com/the-luap/picpeak/issues/158)) ([a19e7c4](https://github.com/the-luap/picpeak/commit/a19e7c40a200ff822c947a83349ed07ccf4e1b01)) +* theme picker buttons no longer submit the parent form ([#326](https://github.com/the-luap/picpeak/issues/326)) ([2eead52](https://github.com/the-luap/picpeak/commit/2eead523193ccb7f23eb767097ad9698e8312833)) +* theme save without Live Preview, Branding default on new events, gallery loading flicker ([#323](https://github.com/the-luap/picpeak/issues/323), [#321](https://github.com/the-luap/picpeak/issues/321)) ([822be9a](https://github.com/the-luap/picpeak/commit/822be9a9b2716f1832a4cb6fccd53602e3cbab51)) +* theme-preset match loop ignores extra fields like logoUrl ([#323](https://github.com/the-luap/picpeak/issues/323)) ([b63a877](https://github.com/the-luap/picpeak/commit/b63a8774c4b44733b903736b2ca5a472a884055e)) +* **theme:** centralise force-mode enforcement inside ThemeContext so every gallery flips ([21188f4](https://github.com/the-luap/picpeak/commit/21188f48d76dd29bc1251bcc6faf9d6d96c805b5)) +* **theme:** kill initial white frame + theme-aware skeleton tiles ([#358](https://github.com/the-luap/picpeak/issues/358) follow-up) ([f529c9e](https://github.com/the-luap/picpeak/commit/f529c9e3d72f0e3496951dfa5d160afda9a1ac51)) +* **theme:** kill initial white frame + theme-aware skeleton tiles ([#358](https://github.com/the-luap/picpeak/issues/358) follow-up) ([1a530ae](https://github.com/the-luap/picpeak/commit/1a530aeaa2d61b34d9721a555b71631c7101c58e)) +* **theme:** pre-React bootstrap to kill white-flash on dark galleries ([#358](https://github.com/the-luap/picpeak/issues/358)) ([07b41e6](https://github.com/the-luap/picpeak/commit/07b41e691d2e8a71f775c667d805a2f9adc10590)) +* **theme:** pre-React bootstrap to kill white-flash on dark galleries ([#358](https://github.com/the-luap/picpeak/issues/358)) ([f81a872](https://github.com/the-luap/picpeak/commit/f81a8728e67b313ac43f55c94fb635abf9beca05)) +* update dependencies to resolve code scanning security alerts ([1f524f2](https://github.com/the-luap/picpeak/commit/1f524f23580d2e2a21dbba28cb46aed76e85c475)) +* update docker-compose to docker compose and add ADMIN_PASSWORD to .env.example ([#189](https://github.com/the-luap/picpeak/issues/189)) ([a4c6248](https://github.com/the-luap/picpeak/commit/a4c624802b2926a16adcf0472a3041562f9b2f48)) +* update packages to fix security vulnerabilities ([8097a0c](https://github.com/the-luap/picpeak/commit/8097a0cb530bd8003597cde81606231efadb0bf5)) +* update security policy with private reporting channels ([308e086](https://github.com/the-luap/picpeak/commit/308e08626383bab213ce3eb5563608dff6168ef4)) +* update security policy with private reporting channels ([7f77362](https://github.com/the-luap/picpeak/commit/7f7736282f534adf4b9d5331d841a1f0bff7341c)) +* update security policy with proper contact email and private reporting ([67b0f32](https://github.com/the-luap/picpeak/commit/67b0f32456d0216e4c685a104c680fa5a5fd578f)), closes [#223](https://github.com/the-luap/picpeak/issues/223) +* use actual photo aspect ratios in masonry columns mode ([#146](https://github.com/the-luap/picpeak/issues/146)) ([8711f96](https://github.com/the-luap/picpeak/commit/8711f967a15f5d57f6ad01bfdbd8d33f9ee96abc)) +* use CSS Columns for gap-free mosaic layout ([#146](https://github.com/the-luap/picpeak/issues/146)) ([821d329](https://github.com/the-luap/picpeak/commit/821d3296ea4b6bde499e5497d258f15ab8dd1dbc)) +* use photo dimensions for mosaic aspect ratios ([#146](https://github.com/the-luap/picpeak/issues/146)) ([27ff51e](https://github.com/the-luap/picpeak/commit/27ff51e7a1217848859b47940bc88caa6f1fb20f)) +* video upload media type, select all, and dimension repair ([#203](https://github.com/the-luap/picpeak/issues/203), [#220](https://github.com/the-luap/picpeak/issues/220), [#180](https://github.com/the-luap/picpeak/issues/180)) ([fc75bcd](https://github.com/the-luap/picpeak/commit/fc75bcdfc38673d6e4dd1cd943cfb4638d3a306c)) +* video upload, select all, and dimension repair ([#203](https://github.com/the-luap/picpeak/issues/203), [#220](https://github.com/the-luap/picpeak/issues/220), [#180](https://github.com/the-luap/picpeak/issues/180)) ([a0bb080](https://github.com/the-luap/picpeak/commit/a0bb0805868e742f323b64312c3c5ef8ec408f68)) +* wire admin photo feedback filters into grid query ([#293](https://github.com/the-luap/picpeak/issues/293)) ([d4b4dc6](https://github.com/the-luap/picpeak/commit/d4b4dc628f28a303ff1c80ba6d8e5e768217ba51)) +* wrap email preview with full styled header/footer template ([9a6d2e8](https://github.com/the-luap/picpeak/commit/9a6d2e8e3a3fab8d7969a8a42e94934c38d88392)) +* wrap email preview with full styled header/footer template ([fc0911a](https://github.com/the-luap/picpeak/commit/fc0911acf8b7c8a18d71bb4267f1086acd1e0ca1)), closes [#229](https://github.com/the-luap/picpeak/issues/229) +* wrap test email with standard email template ([#252](https://github.com/the-luap/picpeak/issues/252)) ([954a011](https://github.com/the-luap/picpeak/commit/954a0118bae5770c74f1e811e03b8fc702c70db2)) ### Reverts -* **customer-portal:** make the global flag UI-only, drop the kill-switch middleware ([3f44193](https://github.com/the-luap/picpeak/commit/3f4419356a4f30509052a6d00b71485af2c17f85)) - -## [3.47.2-beta.0](https://github.com/the-luap/picpeak/compare/v3.47.1-beta.0...v3.47.2-beta.0) (2026-05-11) - - -### Bug Fixes - -* **activity-log:** smart feature_flags_updated rendering + 33 missing activity types ([4703fd5](https://github.com/the-luap/picpeak/commit/4703fd574f57bfab327ffefec5986bb08b240c95)) - -## [3.47.1-beta.0](https://github.com/the-luap/picpeak/compare/v3.47.0-beta.0...v3.47.1-beta.0) (2026-05-11) - - -### Bug Fixes - -* **features:** customer-portal card uses 'Clients' to match sidebar wording ([441cc41](https://github.com/the-luap/picpeak/commit/441cc419377055a5872f71afb19036cc5c932b58)) -* **features:** customer-portal card uses 'Clients' to match sidebar wording ([dec2f5d](https://github.com/the-luap/picpeak/commit/dec2f5d3d2224b0d66f02bb9a562b4ddeaac77df)) - -## [3.47.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.46.3-beta.0...v3.47.0-beta.0) (2026-05-11) - - -### Features - -* **email-templates:** categorise + link to feature flags ([84c06af](https://github.com/the-luap/picpeak/commit/84c06affb73687529e35dbbac15801deb41dc4f2)) -* **email-templates:** categorise + sub-categorise + link to feature flags ([2cae3fe](https://github.com/the-luap/picpeak/commit/2cae3fe47deb667af5991ae1a90e3b5698693119)) -* **email-templates:** group Templates UI by category + Feature off chip ([5ec26fc](https://github.com/the-luap/picpeak/commit/5ec26fc9981028163cab122e229c83cdbbf35828)) -* **email-templates:** group Templates UI by category with core sub-sections ([53eecb6](https://github.com/the-luap/picpeak/commit/53eecb6f83ff75f1f3c75d68cee5e46d114ac8d1)) -* **email-templates:** seed missing locale translations + post-075 templates ([e3150e4](https://github.com/the-luap/picpeak/commit/e3150e42130cacf19dc7beadb8c86c76c0fff340)) -* **email-templates:** seed missing nl/pt/ru/fr translations ([358f7ee](https://github.com/the-luap/picpeak/commit/358f7ee99e2941ad179d5859178b35a80886542f)) - - -### Bug Fixes - -* **email-templates:** backfill subcategory + customer password reset translations ([2343a16](https://github.com/the-luap/picpeak/commit/2343a162df070cd5bd6abdc331bc5ca4aa283132)) - -## [3.46.3-beta.0](https://github.com/the-luap/picpeak/compare/v3.46.2-beta.0...v3.46.3-beta.0) (2026-05-11) - - -### Bug Fixes - -* **branding:** socials + promo round-trip from DB to form ([#460](https://github.com/the-luap/picpeak/issues/460)) ([bd2288e](https://github.com/the-luap/picpeak/commit/bd2288e6a01786cec0649b3326189e9737db359e)) -* **branding:** socials + promo round-trip from DB to form ([#460](https://github.com/the-luap/picpeak/issues/460)) ([ae64a6a](https://github.com/the-luap/picpeak/commit/ae64a6acbc119f78394e65cee7bf49910e1c7013)) - -## [3.46.2-beta.0](https://github.com/the-luap/picpeak/compare/v3.46.1-beta.0...v3.46.2-beta.0) (2026-05-11) - - -### Bug Fixes - -* **customer-portal:** post-merge fixes for event save, theme fonts, and customer→gallery handoff ([9776d8a](https://github.com/the-luap/picpeak/commit/9776d8a6fcccb5e19e7c652b7e47557213d85731)) -* **events:** CustomerAccountPicker hooks order crashed /admin/events/new ([2a7ae07](https://github.com/the-luap/picpeak/commit/2a7ae0702dfc56e69bf845ded19888c29519414a)) - -## [3.46.1-beta.0](https://github.com/the-luap/picpeak/compare/v3.46.0-beta.0...v3.46.1-beta.0) (2026-05-11) - - -### Bug Fixes - -* **import:** capture photo dimensions in fileWatcher + s3AutoImporter ([#447](https://github.com/the-luap/picpeak/issues/447)) ([5b14854](https://github.com/the-luap/picpeak/commit/5b148542e6f2396ce47e3b6c301f186f9af9adec)) - -## [3.46.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.45.1-beta.0...v3.46.0-beta.0) (2026-05-11) - - -### Features - -* **branding:** Customer dashboard header toggles in Branding page ([b252cb6](https://github.com/the-luap/picpeak/commit/b252cb67eb3645224a279fbbe9c14871438473f8)) -* customer accounts ([#354](https://github.com/the-luap/picpeak/issues/354)) — recurring logins, profile, password reset, branded customer surface ([fe52953](https://github.com/the-luap/picpeak/commit/fe5295373b0bfeec1e81086206ffab7ce1b91094)) -* **customers:** customer portal ([#354](https://github.com/the-luap/picpeak/issues/354)) on top of feature-flags reorg ([087ef45](https://github.com/the-luap/picpeak/commit/087ef45942a8a51d09af2cd8ec85aca330f6cf7f)) - - -### Bug Fixes - -* **auth:** restore COOKIE_SECURE='auto' default for production ([adfa29e](https://github.com/the-luap/picpeak/commit/adfa29e91eeea52aa672e38269c389a5178d9e5a)) -* **customer:** unwrap /customer/* from RequireFeature gate ([da08a58](https://github.com/the-luap/picpeak/commit/da08a5828ab855365a2a2a6f4854b09eb409907a)) -* **server:** drop missing requireCustomerPortal middleware import ([4fa7225](https://github.com/the-luap/picpeak/commit/4fa72257329942a6b598fa90c83c6bca7586fe33)) -* **server:** mount /api/admin/feature-flags route ([f048011](https://github.com/the-luap/picpeak/commit/f048011324bfa4cee8f89b0131b68dd520446ca2)) - -## [3.45.1-beta.0](https://github.com/the-luap/picpeak/compare/v3.45.0-beta.0...v3.45.1-beta.0) (2026-05-10) - - -### Bug Fixes - -* **create-event:** branding-default theme survives eventTypes refetch ([d62c529](https://github.com/the-luap/picpeak/commit/d62c529b0278a9ac790b22f46f49004df71112ea)) -* **create-event:** branding-default theme survives eventTypes refetch ([#323](https://github.com/the-luap/picpeak/issues/323)-B) ([37d487d](https://github.com/the-luap/picpeak/commit/37d487db86fe9fc11facff6d2c0bb9a24e6f6277)) - -## [3.45.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.44.2-beta.0...v3.45.0-beta.0) (2026-05-10) - - -### Features - -* **footer:** hideable legal links + socials + promo banner ([#441](https://github.com/the-luap/picpeak/issues/441) + [#440](https://github.com/the-luap/picpeak/issues/440)) ([f3505c2](https://github.com/the-luap/picpeak/commit/f3505c2631cc5b4ae13a0f0d593a1ddd95fefdcb)) - -## [3.44.2-beta.0](https://github.com/the-luap/picpeak/compare/v3.44.1-beta.0...v3.44.2-beta.0) (2026-05-10) - - -### Bug Fixes - -* **events:** clamp page state when totalPages drops below current page ([#442](https://github.com/the-luap/picpeak/issues/442)) ([b4e30a4](https://github.com/the-luap/picpeak/commit/b4e30a4293c77e6dc34e955741ee113b9d530718)) -* **events:** clamp page state when totalPages drops below current page ([#442](https://github.com/the-luap/picpeak/issues/442)) ([9c4a96f](https://github.com/the-luap/picpeak/commit/9c4a96fe977b7a0907f5dea99491385195b76184)) - -## [3.44.1-beta.0](https://github.com/the-luap/picpeak/compare/v3.44.0-beta.0...v3.44.1-beta.0) (2026-05-10) - - -### Bug Fixes - -* **events:** admins can clear expiration on edit even when 'Require expiration' is ON ([#426](https://github.com/the-luap/picpeak/issues/426)) ([3fd8af3](https://github.com/the-luap/picpeak/commit/3fd8af3d56b54f81cc20b75109cc212d23fc84c1)) -* **events:** admins can clear expiration on edit even when "Require expiration" is ON ([#426](https://github.com/the-luap/picpeak/issues/426)) ([e544561](https://github.com/the-luap/picpeak/commit/e54456135cc8605fad949a955261cecc3f986355)) - -## [3.44.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.43.3-beta.0...v3.44.0-beta.0) (2026-05-10) - - -### Features - -* **settings:** Features tab + sidebar reorg with feature-flag gating ([c3798e1](https://github.com/the-luap/picpeak/commit/c3798e19c8f928eac0ca1d7694d1ecfd78a1e437)) -* **settings:** Features tab + sidebar reorg with feature-flag gating ([15e3336](https://github.com/the-luap/picpeak/commit/15e333681fe4ce94afa8e5b477b339b179d0195a)) - -## [3.43.3-beta.0](https://github.com/the-luap/picpeak/compare/v3.43.2-beta.0...v3.43.3-beta.0) (2026-05-09) - - -### Bug Fixes - -* **gallery:** serve thumbnails / photos / hero via storage abstraction ([#432](https://github.com/the-luap/picpeak/issues/432)) ([d3007b0](https://github.com/the-luap/picpeak/commit/d3007b0dd29d37a46ce26e8b4eb15908e0f8e3d2)) - -## [3.43.2-beta.0](https://github.com/the-luap/picpeak/compare/v3.43.1-beta.0...v3.43.2-beta.0) (2026-05-09) +* **branding:** per-option font preview (defer to follow-up) ([f410207](https://github.com/the-luap/picpeak/commit/f410207b2d7ddf1c9525603c7dcbb7cdfee1729b)) ### Documentation -* **contributing:** update branch reference from main to beta ([ed37caf](https://github.com/the-luap/picpeak/commit/ed37caf3d898d9b2db985e6c6ff203457fd4aa38)) +* add API_URL environment variable to .env.example files ([3e69579](https://github.com/the-luap/picpeak/commit/3e69579f5a171b31a253b2a42bb033bf1b97387d)) +* add Buy Me a Coffee badge + Support section ([46bc894](https://github.com/the-luap/picpeak/commit/46bc894d917bd55dbd9bafaa64fd38db21488b81)) +* add External Media Library section to deployment guide ([#270](https://github.com/the-luap/picpeak/issues/270)) ([2e1c71c](https://github.com/the-luap/picpeak/commit/2e1c71c1ab073e488ac93e35337a2d3955dfef3d)) +* add External Media Library section to deployment guide ([#270](https://github.com/the-luap/picpeak/issues/270)) ([f6ca713](https://github.com/the-luap/picpeak/commit/f6ca713a6edc8ba371db790daba05ecb85ea4872)) +* clarify file system photo import requires existing event ([#269](https://github.com/the-luap/picpeak/issues/269)) ([5295516](https://github.com/the-luap/picpeak/commit/5295516b67a1d9f035564c5f9a724f25f8d21c78)) +* clarify file system photo import requires existing event ([#269](https://github.com/the-luap/picpeak/issues/269)) ([ee0baaf](https://github.com/the-luap/picpeak/commit/ee0baafc59f3588a26172aa8835c12dcaec35d10)) +* emphasize importance of STORAGE_PATH in env example ([3397807](https://github.com/the-luap/picpeak/commit/3397807670784e02cbe34a7a60db43c95d64f19c)) +* **fonts:** cache rollout, stale-list note, meta.json ([bd0e052](https://github.com/the-luap/picpeak/commit/bd0e052b1a1847718151a16117dacc6c42a2178e)) +* move documentation to docs.picpeak.app, drop in-repo copies ([02ed5d4](https://github.com/the-luap/picpeak/commit/02ed5d400736f966283a138dedde2455448067ff)) +* move documentation to docs.picpeak.app, drop in-repo copies ([0faf9b3](https://github.com/the-luap/picpeak/commit/0faf9b32816f5f94aa584d2336cdb1e0b7082239)) +* **readme:** add Contributors section with @Luca-Timo and @Rekoo-PS ([c60ab74](https://github.com/the-luap/picpeak/commit/c60ab74ae2daabc4b11fea1f1b2df728294b03c8)) +* **readme:** add Contributors section with @Luca-Timo and @Rekoo-PS ([dbe0a30](https://github.com/the-luap/picpeak/commit/dbe0a3055bd2c71981cb7d9cf43c2b22b9e3276c)) +* rewrite README — shorter, cleaner ([62643f2](https://github.com/the-luap/picpeak/commit/62643f241b51dc1620e30a8c8767f52428c0314c)) +* rewrite README — shorter, cleaner, less AI-sounding ([64f6061](https://github.com/the-luap/picpeak/commit/64f606152fde2db9034fa9ffa08cc58623edf646)) -## [3.43.1-beta.0](https://github.com/the-luap/picpeak/compare/v3.43.0-beta.0...v3.43.1-beta.0) (2026-05-09) +## [3.42.1](https://github.com/the-luap/picpeak/compare/v2.6.5...v3.42.1) (2026-05-07) +Stable release promoting the entire `beta` channel to `main`. Brings ~300 commits of features, fixes, and infrastructure improvements that have been baked on the beta channel since v2.6.5. Highlights below; full per-version notes follow in the beta history. -### Bug Fixes +### Major themes since v2.6.5 -* **event:** correct updating client access ([d00f6fa](https://github.com/the-luap/picpeak/commit/d00f6fa7de59bdbd30efe9ce824e795cf05616f4)) -* **event:** ensure client share token is generated only when necessary ([916580a](https://github.com/the-luap/picpeak/commit/916580adefd464417729e418aa1727b67566fea3)) +* **Multi-administrator support with RBAC** — super admin / admin / editor roles, fine-grained permissions +* **Async upload pipeline** — bytes-on-wire returns 202; sharp/ffmpeg/EXIF/watermark/webhooks happen in a background worker pool +* **Self-hosted webfonts** — filesystem-driven scanner, GDPR-compliant, replaces Google Fonts CDN +* **8-token CI palette + force color mode** — full theme customization across admin and public site +* **Native multi-arch Docker images** — Apple Silicon and ARM64 Linux supported natively +* **Native S3 storage backend** — S3 + S3-compatible providers +* **Comprehensive video support** — upload, stream, and play MP4/WebM/MOV alongside photos +* **Outbound webhooks** — event/photo lifecycle push API with HMAC signatures +* **Gallery layout system** — decoupled header style from layout, banner option, theme-aware skeletons, and lazy-loaded folder picker +* **Multilingual email templates** — translations table for EN/DE/NL/PT/RU +* **Bulk operations** — bulk delete with password confirmation, bulk archive +* **Photo dimensions backfill** — true masonry layout with portrait/landscape sizing +* **Customer client access** — separate review/visibility area before the gallery is shared with guests +* **Image security** — devtools detection, watermarking, right-click prevention, secure thumbnails -## [3.43.0-beta.0](https://github.com/the-luap/picpeak/compare/v3.42.7-beta.0...v3.43.0-beta.0) (2026-05-09) +### Bug fixes (highlights from beta) - -### Features - -* **localization:** add French translations for fit options in thumbnails ([2c12885](https://github.com/the-luap/picpeak/commit/2c1288583fe787c1514c3cace0e2d92a212bb3a3)) -* **localization:** add i18next configuration and CLI commands for localization management ([74e87b9](https://github.com/the-luap/picpeak/commit/74e87b968b3152603dbfca72fae06372b7c7f519)) -* **localization:** add i18next extraction helper & refactor backup configuration component to tsx ([e7228b0](https://github.com/the-luap/picpeak/commit/e7228b07805a40aa67ccb7e3592848218eabbca2)) -* **localization:** add missing translations ([86ee6c8](https://github.com/the-luap/picpeak/commit/86ee6c80aa1f26b2ad47775337ebed301193e662)) -* **localization:** improve English translations for clarity and consistency ([46b99c6](https://github.com/the-luap/picpeak/commit/46b99c629215832e66d9215a210fd6eaf8c89fb4)) -* **localization:** update thumbnail settings and add fit options translations ([5fc427c](https://github.com/the-luap/picpeak/commit/5fc427c74b5cdda6ce1568006d9a94abdc692b3b)) -* **translations:** add French language support and improve localization handling ([a5db4bd](https://github.com/the-luap/picpeak/commit/a5db4bd46e6a5cc84c9563588f90d3461c277528)) - - -### Documentation - -* **localization:** enhance French language support and improve i18next configuration ([d1bc5e0](https://github.com/the-luap/picpeak/commit/d1bc5e030f55c15bf09f37b97f8e1608578a2395)) - -## [Unreleased] - -### Bug Fixes - -* **event:** fix updating client access ([ee85e1d](https://github.com/the-luap/picpeak/commit/ee85e1d)) - -### Features - -* **i18n:** add French (fr) language support with full translation coverage -* **i18n:** add i18next configuration with language detection and namespace setup -* **i18n:** add CLI commands for localization management (extraction, validation) -* **i18n:** add `i18nextExtractionHelper` developer script for auditing missing translation keys -* **i18n:** complete and restructure translation files for EN, DE, NL, PT, RU with consistent key naming - -### Code Refactoring - -* **admin:** convert `BackupConfiguration`, `BackupDashboard`, and `BackupManagement` from JSX to TSX with full i18n support -* **admin:** remove stale `.d.ts` declaration files replaced by TSX components -* **i18n:** clean up `useLocalizedTimeAgo` hook and update `useLocalizedDate` - -## [3.42.7-beta.0](https://github.com/the-luap/picpeak/compare/v3.42.6-beta.0...v3.42.7-beta.0) (2026-05-09) - - -### Bug Fixes - -* **auth:** default COOKIE_SECURE to 'auto' in production + first-install UX ([#427](https://github.com/the-luap/picpeak/issues/427)) ([e1c9382](https://github.com/the-luap/picpeak/commit/e1c93823c4a3095dd2afa618f393a061806f18a3)) - -## [3.42.6-beta.0](https://github.com/the-luap/picpeak/compare/v3.42.5-beta.0...v3.42.6-beta.0) (2026-05-09) - - -### Bug Fixes - -* **external-media:** pre-generate thumbnails so reference-mode galleries load fast ([#423](https://github.com/the-luap/picpeak/issues/423)) ([e2ffd9f](https://github.com/the-luap/picpeak/commit/e2ffd9f93d228f9e16408fe424c65b26db67ac8e)) -* **external-media:** pre-generate thumbnails so reference-mode galleries load fast ([#423](https://github.com/the-luap/picpeak/issues/423)) ([f3d0f16](https://github.com/the-luap/picpeak/commit/f3d0f161c9e554a5149e6b4eafdb0ac42bebf277)) - -## [3.42.5-beta.0](https://github.com/the-luap/picpeak/compare/v3.42.4-beta.0...v3.42.5-beta.0) (2026-05-08) - - -### Bug Fixes - -* **admin:** test email always sends, regardless of update availability ([#418](https://github.com/the-luap/picpeak/issues/418)) ([9326a42](https://github.com/the-luap/picpeak/commit/9326a427b32458dfdaa01530bac66cda84ed7b72)) - -## [3.42.4-beta.0](https://github.com/the-luap/picpeak/compare/v3.42.3-beta.0...v3.42.4-beta.0) (2026-05-08) - - -### Bug Fixes - -* **events:** typed-DELETE confirmation for bulk delete ([#417](https://github.com/the-luap/picpeak/issues/417)) ([e165ee5](https://github.com/the-luap/picpeak/commit/e165ee5d9fa805c704a64f91c9514bf0ab75b5b8)) -* **events:** typed-DELETE confirmation for bulk delete ([#417](https://github.com/the-luap/picpeak/issues/417)) ([99e420b](https://github.com/the-luap/picpeak/commit/99e420b1b9783a1d6b4eb892c09d0af3340bf314)) - -## [3.42.3-beta.0](https://github.com/the-luap/picpeak/compare/v3.42.2-beta.0...v3.42.3-beta.0) (2026-05-07) - - -### Bug Fixes - -* **create-event:** re-apply Branding theme on stale→fresh settings ([#323](https://github.com/the-luap/picpeak/issues/323)-B) ([401abf7](https://github.com/the-luap/picpeak/commit/401abf7a27cb73dd7fb8399f4c05644c95767093)) -* **security:** scan triage cleanup — drop dead deps, harden Docker/nginx/postMessage ([7abfeb9](https://github.com/the-luap/picpeak/commit/7abfeb91cc7bbb9b6853146dbfe16b8d9835bcb3)) -* **security:** scan triage cleanup — drop dead deps, harden Docker/nginx/postMessage ([6b6191a](https://github.com/the-luap/picpeak/commit/6b6191a4260650e21c45f6153cac1b142bf8483a)) - -## [3.42.2-beta.0](https://github.com/the-luap/picpeak/compare/v3.42.1-beta.0...v3.42.2-beta.0) (2026-05-07) - - -### Bug Fixes - -* **security:** patch 18 dependency CVEs (axios + transitives + nodemailer + i18next-http-backend) ([b7d6ca0](https://github.com/the-luap/picpeak/commit/b7d6ca0b65e652b50d957380f93ed16e151e94a8)) -* **security:** patch 18 dependency CVEs (axios + transitives) ([523f499](https://github.com/the-luap/picpeak/commit/523f49916bea44697d40f61e0b6e44b83decc4b9)) +* `/auth/session` symmetry fixes for the admin-login redirect-loop family (#350, #355, #363, #398) +* Email template renderer: handle `{{#if}}` conditionals, fix CSS leak in plain-text fallback, gate publish-from-draft password placeholder, gate `external_url` in public response +* Customer email caller/template variable drift across gallery_created, expiration_warning, archive_complete, gallery_expired +* Full-URL `gallery_link` in all email types (was path-only in 3 sites) +* ffmpeg/ffprobe installed via apk for Alpine compatibility (was glibc-bundled binary) +* Theme-aware skeleton tiles, dark theme white-flash on first paint +* Admin events search and counters not bounded to first 100 records (#346) +* Login redirect loop with stale admin cookies (#350) — three rounds of asymmetry fixes ## [3.42.1-beta.0](https://github.com/the-luap/picpeak/compare/v3.42.0-beta.0...v3.42.1-beta.0) (2026-05-07) @@ -2099,3 +1957,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.1.15] - Previous Release Initial stable release with core functionality. + +--- + +# Pre-3.x history (main 2.x channel) + +## [2.6.5](https://github.com/the-luap/picpeak/compare/v2.6.4...v2.6.5) (2026-04-08) + + +### Documentation + +* rewrite README — shorter, cleaner ([62643f2](https://github.com/the-luap/picpeak/commit/62643f241b51dc1620e30a8c8767f52428c0314c)) +* rewrite README — shorter, cleaner, less AI-sounding ([64f6061](https://github.com/the-luap/picpeak/commit/64f606152fde2db9034fa9ffa08cc58623edf646)) + +## [2.6.4](https://github.com/the-luap/picpeak/compare/v2.6.3...v2.6.4) (2026-04-08) + + +### Bug Fixes + +* sync backend package-lock.json for security deps ([bb81fa5](https://github.com/the-luap/picpeak/commit/bb81fa5f4b5f1bd927a02470ce80a13c4f53443f)) +* sync backend package-lock.json with security dep updates ([03e1989](https://github.com/the-luap/picpeak/commit/03e19893b3532a27aa59e7b834d53c6a2b52b7cd)) + +## [2.6.3](https://github.com/the-luap/picpeak/compare/v2.6.2...v2.6.3) (2026-04-07) + + +### Documentation + +* add External Media Library section to deployment guide ([#270](https://github.com/the-luap/picpeak/issues/270)) ([2e1c71c](https://github.com/the-luap/picpeak/commit/2e1c71c1ab073e488ac93e35337a2d3955dfef3d)) +* add External Media Library section to deployment guide ([#270](https://github.com/the-luap/picpeak/issues/270)) ([f6ca713](https://github.com/the-luap/picpeak/commit/f6ca713a6edc8ba371db790daba05ecb85ea4872)) + +## [2.6.2](https://github.com/the-luap/picpeak/compare/v2.6.1...v2.6.2) (2026-03-16) + + +### Bug Fixes + +* **security:** invalidate tokens on password change, enforce session timeout, fix role update ([85a60a2](https://github.com/the-luap/picpeak/commit/85a60a2dc7526aa6b673e2a04e9fdfba7de7117f)) +* **security:** token invalidation on password change, session timeout enforcement ([0a3a537](https://github.com/the-luap/picpeak/commit/0a3a53763c9f3caef9fdceccf9fdbfdefe9bd8bf)) + +## [2.6.1](https://github.com/the-luap/picpeak/compare/v2.6.0...v2.6.1) (2026-03-11) diff --git a/DEPLOYMENT_GUIDE.md b/DEPLOYMENT_GUIDE.md new file mode 100644 index 00000000..d1dc0d21 --- /dev/null +++ b/DEPLOYMENT_GUIDE.md @@ -0,0 +1,888 @@ +# 🚀 PicPeak Deployment Guide + +This guide covers multiple deployment options for PicPeak, from simple local setups to production-ready configurations. + +## 📋 Table of Contents + +- [Quick Start](#-quick-start) +- [Prerequisites](#prerequisites) +- [Configuration](#-configuration) +- [Deployment](#-deployment) +- [First Login](#-first-login) +- [Release Channels](#-release-channels) +- [Reverse Proxy Setup](#-reverse-proxy-setup) +- [External Media Library](#-external-media-library) +- [Maintenance](#-maintenance) +- [Troubleshooting](#-troubleshooting) + +## 🚀 Quick Start + +### Option 1: Automated Setup Script (Easiest) + +For the simplest installation, use our unified setup script: + +```bash +curl -fsSL https://raw.githubusercontent.com/the-luap/picpeak/main/scripts/picpeak-setup.sh -o picpeak-setup.sh && \ +chmod +x picpeak-setup.sh && \ +sudo ./picpeak-setup.sh +``` + +This script handles Docker/Native installation choice, OS detection, dependencies, database setup, and optional SSL. + +👉 **See [SIMPLE_SETUP.md](./SIMPLE_SETUP.md) for detailed instructions.** + +### Option 2: Docker with Pre-built Images (Recommended) + +```bash +# Clone repository for configuration files +git clone https://github.com/the-luap/picpeak.git +cd picpeak + +# Copy and configure environment +cp .env.example .env +nano .env # Edit with your values + +# Create required directories +mkdir -p events/active events/archived data logs backup storage +chmod -R 755 events data logs backup storage + +# Deploy using pre-built images +docker compose -f docker-compose.production.yml up -d + +# Check logs +docker compose -f docker-compose.production.yml logs -f +``` + +**Available image tags:** +| Channel | Tags | Description | +|---------|------|-------------| +| Stable | `stable`, `latest`, `v2.3.0` | Production-ready releases | +| Beta | `beta`, `v2.3.0-beta.1` | Early access to new features | +| Branch | `main`, `beta` | Latest from each branch | + +To select a channel, set `PICPEAK_CHANNEL` in your `.env` file (see [Release Channels](#release-channels) section) + +### Option 3: Build from Source + +```bash +git clone https://github.com/the-luap/picpeak.git +cd picpeak +cp .env.example .env +nano .env # Edit with your values + +mkdir -p events/active events/archived data logs backup storage +chmod -R 755 events data logs backup storage + +docker compose build +docker compose up -d +``` + +## Prerequisites + +- Docker and Docker Compose installed +- Domain name (for production) +- SMTP server credentials for emails +- At least 2GB RAM and 20GB storage + +## 🔧 Configuration + +### Essential Environment Variables + +Generate secure values: +```bash +# JWT Secret +openssl rand -base64 64 + +# Database Password (avoid $ character - see warning below) +openssl rand -base64 32 | tr -d '$' + +# Redis Password (avoid $ character - see warning below) +openssl rand -base64 32 | tr -d '$' +``` + +⚠️ **PASSWORD WARNING**: Docker Compose interprets `$` as variable substitution. Either: +- Avoid `$` in passwords (recommended - use the commands above) +- Escape `$` as `$$` (e.g., `Pass$$word` instead of `Pass$word`) +- Quote the entire value: `DB_PASSWORD='Pass$word'` (less reliable) + +### Public Landing Page + +- `npm run migrate` now seeds three general settings: `general_public_site_enabled`, `general_public_site_html`, and `general_public_site_custom_css` so existing installs stay disabled by default. +- Configure the feature from **Admin → CMS Pages**. The landing page panel exposes the toggle, HTML editor, optional CSS overrides, preview, and a reset-to-default action. +- All HTML and CSS submitted through the UI is sanitized server-side. Scripts, inline event handlers, disallowed attributes, `@import` rules, and `javascript:` URLs are stripped before content is cached or rendered. +- Resetting via the UI (or calling `POST /api/admin/settings/public-site/reset`) restores the bundled template and clears custom CSS. +- The landing page response is cached in-memory. Override the default 60s cache window by setting `PUBLIC_SITE_CACHE_TTL_MS` (milliseconds) in your environment if you need faster cache busting. +- When the toggle is off PicPeak continues to serve the SPA/login redirect at `/`, preserving legacy behaviour until you explicitly enable the feature. + +### Backend Configuration (.env) +Update `.env` with: +- `JWT_SECRET` - Authentication secret (REQUIRED - generate a secure random value) +- `DB_PASSWORD` - PostgreSQL password +- `REDIS_PASSWORD` - Redis password +- `SMTP_*` - Email configuration +- **URL Configuration** (for backend CORS): + - `FRONTEND_URL` - Frontend origin (use full URL with scheme, no trailing slash) + - Example (Docker): `http://localhost:3000` +- `ADMIN_URL` - Admin origin (same as `FRONTEND_URL` for Docker; full URL, no trailing slash) + - Example (Docker): `http://localhost:3000` + + Notes: + - Do not include trailing `/` (e.g., use `http://host:3000`, not `http://host:3000/`). + - Always include the scheme (`http://` or `https://`). + - The backend compares origins strictly for CORS; malformed values will cause login requests to fail with 500. + +#### Authentication Security +- Configure login attempt thresholds from **Admin → Settings → Security**. Defaults are 5 failed attempts per IP within 15 minutes, resulting in a 30 minute lockout. + +#### External Database Example +To use an external PostgreSQL instead of the bundled container, set the following in `.env` and ensure the `postgres` service is disabled or removed: + +```env +DB_HOST=db.example.com +DB_PORT=5432 +DB_USER=picpeak +DB_PASSWORD=change_me +DB_NAME=picpeak_prod +``` + +Compose uses these values via `env_file: .env`. The backend service also defaults `DB_HOST=${DB_HOST:-postgres}` so if you don’t set `DB_HOST` it will use the bundled `postgres` container. + +### Frontend Configuration (frontend/.env) +Create `frontend/.env` from `frontend/.env.example`: +```bash +cp frontend/.env.example frontend/.env +``` + +Update `frontend/.env` with: +- `VITE_API_URL` - Backend API URL + - Docker (pre-built images) and production behind reverse proxy: `/api` (recommended; avoids CORS and matches the frontend Nginx proxy in the image) + - Local dev (Vite): `http://localhost:3001` or `/api` if proxying through a dev proxy + +Note: When using pre-built frontend images, runtime container env does not change the already-built JS. Prefer the default `/api` and let the frontend Nginx proxy forward to the backend. + +⚠️ **IMPORTANT PORT CONFIGURATION**: +- The frontend runs on port **3000** in Docker (exposed via nginx) +- The backend API runs on port **3001** +- The frontend `.env` file MUST point to the correct backend port (3001) +- Default `.env.example` is configured for Docker deployment + +### Email Configuration Examples + +#### Gmail +```env +SMTP_HOST=smtp.gmail.com +SMTP_PORT=587 +SMTP_SECURE=false +SMTP_USER=your-email@gmail.com +SMTP_PASS=your-app-specific-password +``` + +#### SendGrid +```env +SMTP_HOST=smtp.sendgrid.net +SMTP_PORT=587 +SMTP_SECURE=false +SMTP_USER=apikey +SMTP_PASS=your-sendgrid-api-key +``` + +## 📦 Deployment + +### Using Pre-built Images (Fastest) + +```bash +# Pull latest images from GitHub Container Registry +docker pull ghcr.io/the-luap/picpeak/backend:latest +docker pull ghcr.io/the-luap/picpeak/frontend:latest + +# Start services using production compose file +docker compose -f docker-compose.production.yml up -d + +# View running containers +docker compose ps +``` + +### Building from Source (For Customization) + +```bash +# Build images locally +docker compose build + +# Or build with no cache for clean build +docker compose build --no-cache + +# Start all services +docker compose up -d + +# View running containers +docker compose ps +``` + +### Access Points + +By default, services are exposed on: +- Frontend (UI + Admin): http://localhost:3000 (admin at `/admin`) +- Backend/API: http://localhost:3001 (API only; no UI routes) +- PostgreSQL: localhost:5432 (if needed) +- Redis: localhost:6379 (if needed) + +### Initial Admin Setup + +When deploying for the first time, an admin account is automatically created with a secure, randomly generated password. This password is displayed in the Docker logs during initialization and **must be changed** on first login. + +#### Finding the Auto-Generated Admin Password + +The admin password is automatically generated during the first startup and displayed in the backend container logs. Here's how to find it: + +**Option 1: Search Docker logs for admin password** (recommended) +```bash +# Find the auto-generated admin password in logs +docker compose logs backend | grep "Admin password" +``` + +You should see output like: +``` +✅ Admin password generated: BraveTiger6231! +``` + +**Option 2: View the complete initialization logs** +```bash +# View the complete admin setup logs +docker compose logs backend | grep -A 10 "Admin user created" +``` + +**Option 3: Check the saved credentials file** +```bash +# The password is also saved in the backend container +docker exec picpeak-backend cat data/ADMIN_CREDENTIALS.txt +``` + +**Option 4: Use the helper script** +```bash +# Show current admin username and email (password is hidden) +docker exec picpeak-backend node scripts/show-admin-credentials.js + +# Reset the admin password to a new random password (displays new password in console) +docker exec picpeak-backend node scripts/show-admin-credentials.js --reset +``` + +> **Note:** When using `--reset`, the new password will be displayed in the console output. Save it immediately - it will not be shown again! + +#### Important Security Notes + +- **Login requires the email address**, not username +- When resetting password, the new password is displayed once in the console - save it immediately +- **Password change is MANDATORY** on first login - the system will force you to change it +- If you lose the password before first login, use the `--reset` option to generate a new one +- New password requirements: minimum 12 characters, mixed case, numbers, and special characters + +## 🔐 First Login + +After deployment, you must complete the first login process which includes mandatory password change for security. + +### Step 1: Locate Your Admin Password + +1. **Find the auto-generated password** from the credentials file: + ```bash + # Docker deployment + docker compose exec backend cat /app/data/ADMIN_CREDENTIALS.txt + + # Or directly from the host (if you have access) + cat data/ADMIN_CREDENTIALS.txt + ``` + +2. **Note the admin email** (default: `admin@example.com` unless customized) + +### Step 2: Access Admin Panel + +1. Navigate to your frontend domain and open the admin section: + - `http://your-domain.com/admin` (behind reverse proxy) + - `http://localhost:3000/admin` (Docker local) + + The backend at `:3001` serves API only and does not serve the admin UI. +2. Login using: + - **Email**: `admin@example.com` (or your custom admin email) + - **Password**: The auto-generated password from the logs + +### Step 3: Mandatory Password Change + +Upon first login, the system will **automatically redirect** you to change your password: + +1. **You cannot skip this step** - it's enforced for security +2. Enter the current auto-generated password +3. Create a new secure password meeting these requirements: + - Minimum 12 characters + - At least one uppercase letter + - At least one lowercase letter + - At least one number + - At least one special character (!@#$%^&*) + +### Security Best Practices for New Password + +- **Use a unique password** not used elsewhere +- **Consider a password manager** for generation and storage +- **Include mixed characters**: `MySecureP@ssw0rd2024!` +- **Avoid personal information** (names, dates, etc.) +- **Save securely** - you cannot recover this password easily + +### If You Lose Access + +If you lose your admin credentials after the first login, you'll need to manually reset the password in the database or create a new admin user through the database. + +**Note**: The credentials file (`ADMIN_CREDENTIALS.txt`) is only created during initial deployment and contains the first admin password. After changing the password, this file becomes outdated but is kept for reference. If you need to regenerate the password and file during a reinstall, re-run the installer with the `--force-admin-password-reset` flag: + +```bash +# Native reinstall example +sudo ./picpeak-setup.sh --native --force-admin-password-reset + +# Docker reinstall example +sudo ./picpeak-setup.sh --docker --force-admin-password-reset +``` + +The flag calls `scripts/reset-admin-password.js` in non-interactive mode, writes a fresh random password into `data/ADMIN_CREDENTIALS.txt`, and prints the new credentials at the end of the installer run. + +#### Configuring Admin Email + +By default, the admin email is `admin@example.com`. To use a different email address, set it in your `.env` file before first deployment: + +```env +# .env +ADMIN_EMAIL=your-email@yourdomain.com +``` + +**Note**: This only works on first deployment. To change the admin email after deployment, you'll need to update it in the database or create a new admin user through the admin panel. + +## 🔄 Release Channels + +PicPeak offers two release channels for different needs: + +### Stable Channel (Recommended) +- Production-ready releases +- Thoroughly tested before release +- Docker tags: `stable`, `latest`, or specific version like `v2.3.0` + +### Beta Channel +- Early access to new features +- May contain bugs or incomplete functionality +- Docker tags: `beta` or specific version like `v2.3.0-beta.1` + +### Configuring Your Channel + +Set the `PICPEAK_CHANNEL` environment variable in your `.env` file: + +```bash +# For stable releases (default) +PICPEAK_CHANNEL=stable + +# For beta releases +PICPEAK_CHANNEL=beta + +# For a specific version +PICPEAK_CHANNEL=v2.3.0 +``` + +The `docker-compose.production.yml` uses this variable for both backend and frontend images: +```yaml +image: ghcr.io/the-luap/picpeak/backend:${PICPEAK_CHANNEL:-stable} +``` + +### Switching Channels + +To switch between channels: + +```bash +# Edit your .env file +nano .env +# Change PICPEAK_CHANNEL=stable to PICPEAK_CHANNEL=beta (or vice versa) + +# Pull the new images and restart +docker compose -f docker-compose.production.yml pull +docker compose -f docker-compose.production.yml up -d +``` + +### Update Notifications + +The admin dashboard automatically notifies you when updates are available for your channel. This feature: +- Checks GitHub releases hourly (cached to avoid rate limits) +- Shows updates relevant to your current channel (stable or beta) +- Can be disabled by setting `UPDATE_CHECK_ENABLED=false` in your `.env` + +## 🔒 Reverse Proxy Setup + +For production deployments, you should use a reverse proxy for SSL/HTTPS. The application exposes ports directly, allowing you to use any reverse proxy solution. + +### Routing Schema + +PicPeak consists of two services that need to be routed correctly: + +| Path | Service | Port | Description | +|------|---------|------|-------------| +| `/api/*` | Backend | 3001 | All API endpoints | +| `/photos/*` | Backend | 3001 | Protected photo files | +| `/thumbnails/*` | Backend | 3001 | Protected thumbnail files | +| `/uploads/*` | Backend | 3001 | Upload files | +| `/*` (everything else) | Frontend | 3000 | React SPA (including `/admin/*`, `/gallery/*`) | + +> **Important:** The `/admin/*` routes are served by the frontend (React SPA), NOT the backend. The backend only handles `/api/admin/*` requests. + +### Option 1: Nginx + +Install nginx and create `/etc/nginx/sites-available/picpeak`: + +```nginx +server { + listen 80; + server_name your-domain.com; + return 301 https://$server_name$request_uri; +} + +server { + listen 443 ssl http2; + server_name your-domain.com; + + ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; + + # Backend: API endpoints + location /api/ { + proxy_pass http://localhost:3001; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # Backend: Protected media files + location ~ ^/(photos|thumbnails|uploads)/ { + proxy_pass http://localhost:3001; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # Frontend: Everything else (React SPA) + location / { + proxy_pass http://localhost:3000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} +``` + +Enable the site: +```bash +sudo ln -s /etc/nginx/sites-available/picpeak /etc/nginx/sites-enabled/ +sudo nginx -t +sudo systemctl reload nginx +``` + +### Option 2: Traefik + +Add labels to `docker-compose.override.yml`: + +```yaml +version: '3.8' + +services: + frontend: + labels: + - "traefik.enable=true" + - "traefik.http.routers.picpeak.rule=Host(`your-domain.com`)" + - "traefik.http.routers.picpeak.entrypoints=websecure" + - "traefik.http.routers.picpeak.tls.certresolver=letsencrypt" + - "traefik.http.services.picpeak.loadbalancer.server.port=80" + + backend: + labels: + - "traefik.enable=true" + # API endpoints + - "traefik.http.routers.picpeak-api.rule=Host(`your-domain.com`) && PathPrefix(`/api`)" + - "traefik.http.routers.picpeak-api.entrypoints=websecure" + - "traefik.http.routers.picpeak-api.tls.certresolver=letsencrypt" + - "traefik.http.services.picpeak-api.loadbalancer.server.port=3001" + # Protected media files + - "traefik.http.routers.picpeak-media.rule=Host(`your-domain.com`) && (PathPrefix(`/photos`) || PathPrefix(`/thumbnails`) || PathPrefix(`/uploads`))" + - "traefik.http.routers.picpeak-media.entrypoints=websecure" + - "traefik.http.routers.picpeak-media.tls.certresolver=letsencrypt" + - "traefik.http.services.picpeak-media.loadbalancer.server.port=3001" +``` + +### Option 3: Caddy + +Create a `Caddyfile`: + +```caddyfile +your-domain.com { + # Backend: API endpoints + handle /api/* { + reverse_proxy localhost:3001 + } + + # Backend: Protected media files + handle /photos/* { + reverse_proxy localhost:3001 + } + + handle /thumbnails/* { + reverse_proxy localhost:3001 + } + + handle /uploads/* { + reverse_proxy localhost:3001 + } + + # Frontend: Everything else (React SPA including /admin/*, /gallery/*) + handle { + reverse_proxy localhost:3000 + } +} +``` + +### SSL Certificates + +For any reverse proxy, you can use Let's Encrypt: + +```bash +# With Certbot +sudo certbot certonly --webroot -w /var/www/certbot -d your-domain.com + +# Or use your reverse proxy's built-in ACME support +``` + +## 📂 External Media Library + +The External Media Library allows events to reference photos stored directly on your host filesystem instead of uploading them through the admin UI. This is useful for photographers who already have organized photo libraries and want to share them without re-uploading. + +### How It Works + +- **Managed mode** (default): Photos are uploaded through the admin UI and stored inside PicPeak's storage directory. +- **Reference mode**: Photos remain on your host filesystem. PicPeak reads them directly and generates thumbnails on demand. + +Each event can use either mode. Reference mode events point to a folder under the configured external media root. + +### Configuration + +Add the following to your `.env` file: + +```bash +# Path where your photo library is stored on the host +EXTERNAL_MEDIA_ROOT=/path/to/your/photos +``` + +Then mount this path into the backend container in your `docker-compose.yml` or `docker-compose.production.yml`: + +```yaml +services: + backend: + environment: + - EXTERNAL_MEDIA_ROOT=/external-media + volumes: + - /path/to/your/photos:/external-media:ro # read-only is recommended +``` + +> **Permissions**: Ensure the container user (`PUID`/`PGID`) has read access to the mounted directory. If thumbnails fail to generate, this is usually a permissions issue. + +### Folder Structure + +Organize your photos with subdirectories for each event. Within each event folder, use `individual/` and `collages/` subdirectories to classify photos: + +``` +/path/to/your/photos/ +├── wedding-smith-2026/ +│ ├── individual/ +│ │ ├── IMG_0001.jpg +│ │ ├── IMG_0002.jpg +│ │ └── ... +│ └── collages/ +│ ├── group-photo.jpg +│ └── ... +├── corporate-event/ +│ ├── individual/ +│ │ └── ... +│ └── collages/ +│ └── ... +``` + +Supported file formats: `.jpg`, `.jpeg`, `.png`, `.webp` + +### Usage + +1. **Create an event** in the admin panel as usual (name, date, email, etc.). + +2. **Switch source mode** to "Reference external folder" in the event details under Source Mode. + +3. **Browse and select** the external folder using the folder picker that appears. Navigate to the event's directory. + +4. **Import photos** by clicking "Import from External Folder" in the Photos tab. PicPeak will: + - Recursively scan the selected folder + - Classify photos by subfolder name (`individual/` or `collages/`) + - Deduplicate by filename (keeps the largest file if duplicates exist) + - Extract image dimensions for gallery layout + - Register the photos in the database + +5. **Thumbnails** are generated on demand when a guest first views the gallery. There is no upfront processing delay. + +### Limitations + +- **Images only** — video files are not supported for external media. +- **Read-only** — PicPeak does not modify or delete files in the external media directory. +- **No automatic sync** — If you add new photos to the external folder, you need to re-import from the admin UI. +- **Backup caveat** — External media originals are excluded from PicPeak's built-in backup system. Only thumbnails and database records are backed up. You are responsible for backing up the source files separately. + +### Troubleshooting + +| Problem | Solution | +|---------|----------| +| Folder picker shows empty directory | Check that the volume is mounted correctly and `EXTERNAL_MEDIA_ROOT` matches the container path | +| "Permission denied" errors | Ensure `PUID`/`PGID` in `.env` match the owner of the external media files on the host | +| Thumbnails not generating | Verify the backend container can read the files: `docker exec picpeak-backend ls /external-media/your-folder/` | +| Import finds 0 photos | Only `.jpg`, `.jpeg`, `.png`, `.webp` files are supported. Check file extensions. | + +## 🔧 Maintenance + +### Viewing Logs + +```bash +# All services +docker compose logs -f + +# Specific service +docker compose logs -f backend +docker compose logs -f frontend +``` + +### Backup + +#### Manual Backup +```bash +# Database backup +docker exec picpeak-postgres pg_dump -U picpeak picpeak_prod > backup/db_$(date +%Y%m%d_%H%M%S).sql + +# Files backup +tar -czf backup/photos_$(date +%Y%m%d_%H%M%S).tar.gz events/ +``` + +#### Automated Backup +The application includes a built-in backup service. Configure it in the admin panel: +1. Login to admin panel +2. Go to Settings → Backup +3. Configure destination and schedule +4. Enable backup service + +### Updates + +#### Method 1: Using Pre-built Images (Recommended) + +```bash +# Pull latest changes (for configuration updates) +git pull + +# Pull latest images from GitHub Container Registry +docker compose -f docker-compose.production.yml pull + +# Restart with new images +docker compose -f docker-compose.production.yml down +docker compose -f docker-compose.production.yml up -d + +# Verify services are healthy +docker compose -f docker-compose.production.yml ps +``` + +#### Method 2: Building from Source + +```bash +# Pull latest changes +git pull + +# Rebuild and restart +docker compose down +docker compose build --no-cache +docker compose up -d + +# Verify services are healthy +docker compose ps +``` + +#### Specific Version or Channel Updates + +To use a specific version or switch channels, update your `.env` file: + +```bash +# Edit .env to change the channel or pin to a specific version +nano .env + +# Options for PICPEAK_CHANNEL: +# - stable (recommended, production-ready) +# - beta (early access to new features) +# - v2.3.0 (pin to specific stable version) +# - v2.3.0-beta.1 (pin to specific beta version) + +# Then pull and restart +docker compose -f docker-compose.production.yml pull +docker compose -f docker-compose.production.yml up -d +``` + +The admin dashboard will notify you when updates are available for your configured channel. + +### Database Migrations + +Migrations run automatically on startup, but you can run them manually: + +```bash +docker exec picpeak-backend npm run migrate +``` + +## 🚨 Troubleshooting + +### Common Issues + +#### 502 Bad Gateway / Login Failures +**This is the most common deployment issue!** Usually caused by misconfigured URLs or network problems: + +1. **CORS Configuration Errors**: + ```bash + # WRONG - Missing port will cause CORS errors + FRONTEND_URL=http://10.0.252.12 + + # CORRECT - Include the port you're accessing from + FRONTEND_URL=http://10.0.252.12:3000 + ``` + + The backend validates Origin headers against `FRONTEND_URL` for CORS. If they don't match exactly, you'll get 500 errors on login. + +2. **After Container Restarts**: + - Nginx may have cached old container IPs + - Solution: `docker restart picpeak-frontend` + - Always wait 30-60 seconds for health checks + +3. **Backend Not Starting After Migrations**: + - The logs may only show migrations completed + - Check if server is actually running: `docker exec picpeak-backend ps aux | grep node` + - Should see `node server.js` process + +4. **Login After Fresh Install**: + - Check backend logs for auto-generated admin password: `docker compose logs backend | grep "Admin password"` + - Email: `admin@example.com` (or your custom admin email from .env) + - Password: Auto-generated and shown in logs (e.g., `BraveTiger6231!`) + - Remember: Password MUST be changed on first login + +5. **Complete Fix Sequence**: + ```bash + # 1. Fix your .env file URLs + # 2. Full restart + docker-compose down + docker-compose up -d + + # 3. Wait for healthy status + sleep 60 + docker ps # All should show (healthy) + + # 4. Test backend directly + curl http://localhost:3001/health + + # 5. Test through frontend + curl http://localhost:3000/api/public/settings + ``` + +#### Port Already in Use +```bash +# Check what's using the port +sudo lsof -i :3000 +sudo lsof -i :3001 + +# Change ports in .env +FRONTEND_PORT=3002 +BACKEND_PORT=3003 +``` + +#### Docker Compose Variable Substitution Errors +If you see warnings like: +``` +WARN[0000] The "fgbf" variable is not set. Defaulting to a blank string. +``` + +This means your password contains `$` which Docker Compose interprets as a variable. Solutions: +1. **Best**: Generate passwords without `$`: `openssl rand -base64 32 | tr -d '$'` +2. **Alternative**: Escape `$` as `$$` in your .env file +3. **Example**: `DB_PASSWORD=Pass@#$$fgbf` instead of `DB_PASSWORD=Pass@#$fgbf` + +#### Permission Errors +```bash +# Fix ownership +sudo chown -R 1000:1000 events data logs backup storage +chmod -R 755 events data logs backup storage +``` + +#### Database Connection Issues +```bash +# Check if database is running +docker compose ps +docker compose logs postgres + +# Test connection +docker exec picpeak-postgres pg_isready +``` + +#### Email Not Sending +- Verify SMTP settings in .env +- Check email queue: `docker exec picpeak-backend psql -U picpeak -d picpeak_prod -c "SELECT * FROM email_queue ORDER BY created_at DESC LIMIT 10;"` +- For Gmail, use app-specific password +- Check logs: `docker compose logs backend | grep email` + +### Health Checks + +```bash +# Backend health +curl http://localhost:3001/api/health + +# Frontend health +curl http://localhost:3000 + +# Database health +docker exec picpeak-postgres pg_isready +``` + +### Useful Commands + +```bash +# Enter backend container +docker exec -it picpeak-backend sh + +# Enter database +docker exec -it picpeak-postgres psql -U picpeak picpeak_prod + +# Reset admin password +docker exec picpeak-backend node scripts/show-admin-credentials.js --reset + +# Check disk usage +df -h +du -sh events/ storage/ backup/ + +# View running processes +docker compose top +``` + +## Security Recommendations + +1. **Use HTTPS**: Always use a reverse proxy with SSL in production +2. **Firewall**: Only expose necessary ports (80, 443) +3. **Secure passwords**: Use strong, unique passwords for all services +4. **Regular updates**: Keep Docker images and system packages updated +5. **Backup strategy**: Set up automated backups and test restoration +6. **Monitor logs**: Regularly check logs for suspicious activity +7. **Rate limiting**: The app includes built-in rate limiting, configure as needed + +## Support + +For issues and questions: +- Check logs first: `docker compose logs` +- Review documentation in the repository +- Check existing issues on GitHub +- Create a new issue with: + - Error messages + - Log output + - Environment details (without secrets) + - Steps to reproduce diff --git a/README.md b/README.md index b8c9b78e..2d0ffa85 100644 --- a/README.md +++ b/README.md @@ -1,478 +1,152 @@ -# 📸 PicPeak - Open Source Photo Sharing for Events +# PicPeak
-
+
+ **Self-hosted photo sharing for event photographers.**
+
[](https://opensource.org/licenses/MIT)
[](https://www.docker.com/)
[](https://nodejs.org/)
[](https://reactjs.org/)
- [](https://buymeacoffee.com/theluap)
- [Homepage](https://www.picpeak.app) · [Live Demo](https://demo.picpeak.app) · [Documentation](https://docs.picpeak.app) · [Support the project ☕](https://buymeacoffee.com/theluap)
+ [Live Demo](https://demo.picpeak.app) · [Deployment Guide](DEPLOYMENT_GUIDE.md) · [Homepage](https://www.picpeak.app)
+
+
+
-
-### 📊 **Analytics & Insights**
-Track gallery performance, view statistics, and monitor user engagement.
-
-
-
-### 📁 **Event Management**
-Organize and manage your photo galleries with intuitive event management tools.
-
-
-
-### ✨ **Key Interface Highlights**
-
-
-
-
-
-
- Made with ❤️ by photographers, for photographers
-
- Homepage •
- Live Demo •
- GitHub •
- Documentation •
- Support
+ Homepage · Live Demo · Docs · Issues