From 7962975dbdc955325980f02097f1b5594017d7a4 Mon Sep 17 00:00:00 2001 From: ordinarthur <@arthurbarre.js@gmail.com> Date: Tue, 21 Apr 2026 13:00:29 +0200 Subject: [PATCH] fix(admin): unblock product create page Two bugs compounded to render /admin/collections/products/create blank: 1. Dockerfile's STRIPE_SECRET_KEY build-time placeholder was too short (11 chars) to pass the regex that gates Stripe plugin sync. Build produced an importMap missing plugin-stripe components like LinkToDoc, warning at runtime and failing to render. 2. With autosave enabled, Payload creates a blank draft on page load. Plugin-stripe's beforeValidate hook fired against empty data, calling Stripe products.create with no name, throwing a 500 that aborted the page render. Fix: use a 20+ char placeholder in the Dockerfile so the build-time importMap mirrors runtime, and add a beforeValidate hook that sets skipSync=true whenever productDisplayName is empty so Stripe sync waits until the product has content. Co-Authored-By: Claude Opus 4.7 --- nextjs/Dockerfile | 2 +- nextjs/src/app/(payload)/admin/importMap.js | 2 ++ nextjs/src/collections/Products.ts | 10 ++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/nextjs/Dockerfile b/nextjs/Dockerfile index a857173..6298bea 100644 --- a/nextjs/Dockerfile +++ b/nextjs/Dockerfile @@ -24,7 +24,7 @@ COPY . . ENV NEXT_TELEMETRY_DISABLED=1 ENV PAYLOAD_SECRET=build-time-placeholder ENV DATABASE_URL=postgres://placeholder:placeholder@localhost:5432/placeholder -ENV STRIPE_SECRET_KEY=sk_test_placeholder +ENV STRIPE_SECRET_KEY=sk_test_abcdefghijklmnopqrstuvwxyz1234567890 ENV NEXT_PUBLIC_SERVER_URL=https://rebours.studio RUN pnpm build diff --git a/nextjs/src/app/(payload)/admin/importMap.js b/nextjs/src/app/(payload)/admin/importMap.js index 3c0c901..e3acbb9 100644 --- a/nextjs/src/app/(payload)/admin/importMap.js +++ b/nextjs/src/app/(payload)/admin/importMap.js @@ -1,8 +1,10 @@ +import { LinkToDoc as LinkToDoc_2e9be70cd13299dd4a11a5bd739a5a3c } from '@payloadcms/plugin-stripe/client' import { default as default_7060fcf8de405c49f267d6b95f29dcb7 } from '@/components/admin/ProductPreviewEditor' import { CollectionCards as CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1 } from '@payloadcms/next/rsc' /** @type import('payload').ImportMap */ export const importMap = { + "@payloadcms/plugin-stripe/client#LinkToDoc": LinkToDoc_2e9be70cd13299dd4a11a5bd739a5a3c, "@/components/admin/ProductPreviewEditor#default": default_7060fcf8de405c49f267d6b95f29dcb7, "@payloadcms/next/rsc#CollectionCards": CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1 } diff --git a/nextjs/src/collections/Products.ts b/nextjs/src/collections/Products.ts index b395ef9..6abb464 100644 --- a/nextjs/src/collections/Products.ts +++ b/nextjs/src/collections/Products.ts @@ -28,6 +28,16 @@ export const Products: CollectionConfig = { access: { read: () => true, }, + hooks: { + beforeValidate: [ + ({ data }) => { + if (!data?.productDisplayName) { + return { ...data, skipSync: true } + } + return data + }, + ], + }, versions: { drafts: { autosave: { interval: 800 },