4.2 KiB
| id | title | status | assignee | created_date | updated_date | labels | dependencies | priority | |||
|---|---|---|---|---|---|---|---|---|---|---|---|
| TASK-12 | Fix store page images blocked by Cloudflare Access | Done | 2026-02-13 20:03 | 2026-02-13 22:01 |
|
high |
Description
Store page images not loading because Directus CMS (katheryn-cms.jeffemmett.com) is behind Cloudflare Access (Zero Trust). The Next.js image optimizer gets a 302 redirect to a login page instead of the actual image. Also the artwork detail page was a client component making browser-side API calls to Directus, which were also blocked.
Acceptance Criteria
- #1 Store listing page images load correctly
- #2 Artwork detail page images load correctly
- #3 Detail page data fetching happens server-side (not browser)
- #4 Cart functionality still works on detail page
Implementation Notes
Root Cause
Directus CMS (katheryn-cms.jeffemmett.com) is behind Cloudflare Access (Zero Trust). The Next.js image optimizer gets a 302 redirect to a Cloudflare login page instead of the actual image. Additionally, Next.js has SSRF protection that blocks fetching from private IPs (Docker internal network resolves to 192.168.x.x).
Fix Applied (commits 41d784e → 2523a30)
Solution: API Route Proxy
Created /api/assets/[id] route that proxies Directus assets server-side:
- Browser fetches
/api/assets/[id]?width=...&format=webp(same-origin) - API route fetches from
DIRECTUS_INTERNAL_URL(http://katheryn-cms:8055) on Docker internal network - Bypasses Cloudflare Access (internal network) and SSRF protection (same-origin URL)
- Directus handles image transformations (width, quality, format)
- Response cached with
Cache-Control: public, max-age=31536000, immutable
Other changes
getAssetUrl()now returns/api/assets/[id]?params(local path, no token needed)- Directus SDK client uses
DIRECTUS_INTERNAL_URLfor server-side API calls - Store detail page converted from client to server component
- Added
images.localPatternsfor/api/assets/**in next.config.ts - Added
/app/.next/cacheas tmpfs for read-only container
Files changed
frontend/src/app/api/assets/[id]/route.ts- NEW: asset proxy API routefrontend/src/lib/directus.ts- simplified getAssetUrl, internal SDK URLfrontend/next.config.ts- localPatterns configfrontend/Dockerfile- cleaned up unnecessary build argsfrontend/docker-compose.yml- cache tmpfs, cleaned up env varsfrontend/src/app/store/[slug]/page.tsx- server componentfrontend/src/app/store/[slug]/artwork-detail-client.tsx- NEW: client component
Automatic Inventory Management (da77476)
After fixing images, also fixed store data filtering:
- Store was showing 656 items (all artworks with any USD/GBP price)
- Investigated Directus data: 2,324 total artworks, 639 with USD price (imported catalog), only 19 with GBP price (real store items)
- USD-only items are imported historical catalog data (missing images, dimensions, creation dates, internal notes)
- Added
forSalefilter togetArtworks()using compound Directus_andfilter - Store-ready criteria: name (not empty) + image (uploaded) + price_gbp (> 0) + status published
- Artworks auto-appear when fields populated, auto-move to sold section on status change
- Related works on detail page also filtered to store-ready items only
Commits: 9489418, 4744709, da77476
2026-02-13: Additional fix — removed search: '' from localPatterns in next.config.ts. This was blocking Next.js image optimizer from accepting /api/assets URLs with query params (width, quality, format), returning 400 "url parameter is not allowed". Commit 09567ce, deployed to staging.
Session 2026-02-13: Fixed PayPal MULTI_CURRENCY_ORDER error (hardcoded GBP throughout checkout). Added PayPal client ID as Docker build arg. Added custom favicons across all deployed sites: KT monogram (katheryn-staging), no-dollar symbol (nofi.lol), retro gamepad (games.jeffemmett.com), CT monogram (cynthia-poetry). Added katheryn-website to auto-deploy webhook. All four sites rebuilt and deployed.