Commit Graph

6 Commits

Author SHA1 Message Date
Arnaud 8df292dfee fix: photo thumbnails always used localhost:9000 in production
getPublicUrl() runs in the browser (called from client components rendering
recipe thumbnails), but read the plain STORAGE_PUBLIC_URL env var — never
inlined into the client bundle, so every browser fell back to the hardcoded
localhost:9000 default regardless of the real deployed storage domain,
tripping CSP img-src and mixed-content blocks in production. Added a
NEXT_PUBLIC_STORAGE_PUBLIC_URL build arg (Dockerfile, compose.prod.yml) wired
from the same STORAGE_PUBLIC_URL value, and getPublicUrl() now reads that.

Verified locally: building with a fake public storage domain set shows it
correctly inlined into the client JS chunk (previously only the localhost
fallback ever appeared there).
2026-07-12 13:53:15 +02:00
Arnaud 77f43ee673 fix: publish MinIO port in prod so the browser can actually reach it
minio had no ports: mapping at all in compose.prod.yml — only reachable
inside the docker network, never by the browser. No STORAGE_PUBLIC_URL
value could have fixed uploads without this: the browser's direct PUT
to a presigned URL has no route to the container regardless of what
hostname the URL uses. Published on STORAGE_PORT (default 9000),
mirroring how `web` is exposed via WEB_PORT for the Traefik LXC to
route to.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-12 12:52:34 +02:00
Arnaud ccc41a2018 fix: MinIO CORS blocking browser uploads, changelog admin-only
- MinIO had no CORS config at all, so the browser's direct PUT to a
  presigned URL (cross-origin: app on :3001/:3000, storage on :9000)
  was blocked outright. Added MINIO_API_CORS_ALLOW_ORIGIN — "*" in
  dev, the app's own origin in prod. Verified end-to-end: photo
  upload now succeeds with zero console errors.
- Removed the public /changelog page and its account-menu link —
  changelog is admin-only now (/admin/changelog).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-12 12:33:53 +02:00
Arnaud 2682eba2be fix: presigned upload URLs, card badge alignment, filter menu UX, floating save
- Presigned upload URLs were signed against STORAGE_ENDPOINT (the
  internal docker hostname, e.g. http://minio:9000) instead of a
  browser-reachable URL — uploads/edits with photos were broken in
  prod. Now signed with a separate client bound to STORAGE_PUBLIC_URL,
  which also needed threading through as a Docker build arg (CSP
  headers are computed at build time) and into compose.prod.yml/
  .env.production (gitignored, not committed).
- recipe-form.tsx used the wrong i18n namespace for the visibility
  label (t("recipeForm") instead of t_recipe("recipe")), causing
  MISSING_MESSAGE in French.
- Compact recipe-list view: batch-cook rows showed no dish count, and
  the date/difficulty columns shifted per-row depending on whether a
  difficulty badge was present — reserved a fixed-width slot for it.
- All three card icon badges (batch-cook, favorite, visibility) now
  share the same muted color instead of the batch badge standing out.
- Recipes filter dropdown: clicking a filter option closed the whole
  menu, and the tag text input couldn't be typed into (the menu's
  roving-focus/type-ahead handling was intercepting keystrokes) — menu
  items now stay open on click, and the tag input stops event
  propagation so it behaves like a normal text field.
- Recipe form: added a floating save/cancel bar so long recipes don't
  require scrolling back down to save.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-12 10:53:12 +02:00
Arnaud 8e83cc0dc7 fix: wait for minio-init before starting web
web only depended on minio being healthy, not on minio-init having
created the upload bucket — a race on cold deploys, and likely why
the deploy tool flagged minio-init's exit(0) as an anomaly (it wasn't
wired into the dependency graph the way migrate is).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-12 01:44:59 +02:00
Arnaud 68f0f490b9 chore: move docker/ compose files and infra to repo root
Moved compose.yml, compose.prod.yml, DEPLOY.md, traefik/, and cron/ out
of docker/ into the repo root (docker/ removed). Updated every reference:

- Dockerfile: COPY paths for the cron stage
- .dockerignore: dropped the now-unneeded docker/!docker-cron
  exclude+exception pair (cron/ is just a normal top-level dir now, no
  special-casing needed)
- compose.prod.yml: build context ".." -> "." (Dockerfile and compose
  files are now siblings, not one level apart)
- CLAUDE.md, DEPLOY.md, compose.yml, traefik/epicure.yml,
  cron/run-digest.sh, weekly-digest route.ts: path references in comments/
  docs

Verified: both compose files validate, and all three Dockerfile targets
(runner/cron/migrator) build clean via a local --no-cache docker build
from the new layout.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-11 20:25:38 +02:00