The views.edit.default override replaced Payload's <Form> wrapper, so
useField had no form-state context — every field returned undefined
and setValue threw "N is not a function" during autosave.
Flatten the collection into a single ui field that renders
ProductPreviewEditor, with every real field marked admin.hidden:true.
The panel now lives inside Payload's default form, so useField gets
real values and autosave works.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
React 19 does not reconcile children of contentEditable elements
after mount, so fields whose useField value arrives async (on most
paths under the tabs wrapper) stayed visually empty even though the
form state had the right value.
Drive textContent from a useLayoutEffect keyed on value, skip updates
while the element has focus (user typing), and let commit() write back
on blur. Same fix applied to PriceEditable.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Overriding admin.components.views.edit.default makes /admin/collections/
products/:id and /create render the product-detail panel directly —
text fields are contentEditable, the image is click-to-upload, and
price is inline-editable in the checkout-price-line. Fields that don't
fit the public template (slug, name, currency, availability, SEO,
isPublished, sortOrder, stripeID) live in a collapsible "Réglages
avancés" drawer below the panel.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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 <noreply@anthropic.com>
New "Édition visuelle" tab on the product edit view renders the
product panel with each text field wrapped in a contentEditable
InlineEditable that calls useField.setValue on blur. Combined with
the collection's existing autosave, changes persist automatically
without a manual save.
- InlineEditable: contentEditable wrapper backed by useField
- ProductPanelInfo: presentational product-panel JSX
- ProductPreviewEditor: default-exported custom view component
registered at admin.components.views.edit.livePreview
- Image is read-only; slug/price/SEO still edited via default form tab
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Previous run generated the initial migration without STRIPE_SECRET_KEY
set, so the stripe plugin's sync was disabled and the stripeID/skipSync
columns were omitted. Prod then crashed on queries referencing
products.stripe_i_d. Regenerated with a placeholder key so the plugin
contributes its fields to the schema.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Payload's postgresAdapter `push: true` only runs in dev. Prod needs
committed migrations; the container now runs `payload migrate` before
starting Next.js so the schema is created on first deploy.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Astro import.meta.env doesn't see K8s configmap env vars.
Fall back to process.env which works in SSR Node runtime.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Migrate from SSG to SSR with @astrojs/node adapter so Sanity CMS
changes are reflected immediately without rebuild. Separate ports
for Astro SSR (4321) and Fastify API (3000) in production.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add @adminjs/upload for image management (JPEG/PNG/WebP, max 5MB)
- Auto-compute imagePath, ogImage, slug, seoTitle, seoDescription
- Stripe price auto-sync on product create/edit
- Serve uploads via Fastify + nginx /uploads/ location
- Add imageKey/imageMime fields to schema
- Hide technical fields from admin edit form
- Add uploads/ and SQLite DB to .gitignore
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AdminJS requires this Babel plugin during the Astro build step.
Without it, Rollup fails to process .adminjs/entry.js.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Docker Compose app creates its own isolated network, so the
fastify container cannot reach the PostgreSQL database managed
separately by Coolify. Adding the external 'coolify' network
allows inter-container communication.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>