Skip to content

Latest commit

 

History

History
39 lines (28 loc) · 4.52 KB

VERIFIED.md

File metadata and controls

39 lines (28 loc) · 4.52 KB

Verified facts (current docs, checked 2026-07-08)

Findings from the kickoff "verify before scaffolding" research. Trust these over training data; re-verify only if reality contradicts them.

Payload ↔ Next.js

  • Payload 3.85.2 — all payload + @payloadcms/* packages pinned exactly (no ^/~), versions in lockstep.
  • Supported Next.js: >=15.2.9 <15.3 || >=15.3.9 <15.4 || >=15.4.11 <15.5 || >=16.2.6 <17. Use Next 16.2.x (16.2.10 current LTS). 15.5–16.1.x hard-blocked.
  • pnpm is Payload's recommended package manager. sharp must be added manually for upload image features. React-19 peer-dep warnings from admin deps are benign. After version changes: remove lockfile + node_modules, reinstall, pnpm dedupe.

Cloudinary (primary design confirmed viable)

  • type: private: original undeliverable unsigned, but derived versions are public by default → Strict Transformations must be ON.
  • With strict on, a named transformation flagged allowed_for_strict: true delivers on the fly, unsigned: image/private/t_preview/<public_id>. This is the Preview path.
  • f_auto cannot live inside a named transformation. Chain it: t_preview/f_auto, and allowlist that combined variant (or eager-generate). q_auto is fine inside the named transformation.
  • Fallback (type: authenticated) not needed for images; note it disallows all on-the-fly derivations (eager-only + always signed). Superseded for video: video Originals ship as type: authenticated with eager-generated derived assets and signed URLs throughout — see §5 of src/lib/cloudinary/README.md.
  • Original download: cloudinary.v2.utils.private_download_url(publicId, format, { expires_at, attachment: true }) — purpose-built, time-limited, API-endpoint URL (not CDN-cached). This is buildDownloadUrl's mechanism. Default type is private; expires_at is UNIX seconds (default 1h).
  • Upload AI: tags via categorization: 'google_tagging' (or imagga_tagging/aws_rek_tagging) + auto_tagging: <0–1 threshold> → land in response tags array. Caption via detection: 'captioning' → returned as a caption value in upload response (exact nested JSON path unconfirmed — inspect a live response defensively).

next-cloudinary (verified empirically 2026-07-08, v6.17.5)

  • CldImage requires a Client Component boundary in this version (uses useState internally) — the "may render in a Server Component" guidance did not hold; PreviewImage carries 'use client'.
  • strictTransformations restricts the URL to named transformations only and drops the default f_auto/q_auto and responsive width params. Plain namedTransformations: ['preview'] delivered a 636KB PNG (no format negotiation).
  • Without strictTransformations, CldImage injects c_limit,w_* and f_auto/q_auto as separate chained components → not on the strict allowlist → 401.
  • The fix: namedTransformations: ['preview/f_auto'] (slash inside the value) emits exactly the allowlisted chain t_preview/f_auto → 200, WebP, 113KB. This is a string-concatenation artifact, not a documented feature — re-verify on next-cloudinary upgrades.
  • CldImage always appends /v1/ and an ?_a= analytics param; both are harmless under strict mode, but the library logs a dev-console warning ("props [version] not supported with Strict Transformations") per image. Cosmetic.
  • Requires NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME (delivery URLs only — API secret stays server-side).

Payload without sharp (verified 2026-07-08)

  • sharp removed from payload.config.ts + deps: upload collections still accept files; Payload just skips local image processing (resizing, crop UI, dimension extraction).
  • Photo width/height are writable via the Local API update and are now populated from Cloudinary's upload response in syncCloudinaryOriginal.

Stripe

  • stripe npm v22.3.0, pins API version 2026-06-24.dahlia. Do not pass apiVersion — rely on SDK pin.
  • Classic hosted Checkout unchanged: mode: 'payment', line_items[].price_data{currency, unit_amount, product_data{name, images(max 8)}}, metadata, success_url with {CHECKOUT_SESSION_ID}, cancel_url. Don't set ui_mode (defaults to hosted).
  • Webhook in App Router: await req.text() is already raw — no bodyParser config. stripe.webhooks.constructEvent(body, sig, secret). Set export const runtime = 'nodejs' explicitly. Return 200 fast.
  • checkout.sessions.retrieve: payment_status ∈ {paid, unpaid, no_payment_required}; require === 'paid'. metadata set at creation is returned.