Document testimonials collection and Live Preview in the README
Adds the testimonials row to the collections table, PAYLOAD_PREVIEW_SECRET/ NEXT_PUBLIC_PAYLOAD_URL to the env vars section, and a new Live Preview section covering /api/preview, the 3 Live-Preview-aware components, and the next/headers RSC-boundary gotcha hit while building it.
This commit is contained in:
@@ -28,8 +28,13 @@ since Coolify builds with `--no-cache` and a failed build only surfaces there
|
||||
otherwise.
|
||||
|
||||
**Environment variables:** `PAYLOAD_URL` (defaults to `https://payload.mk360.de`
|
||||
if unset, see `app/lib/payload.ts`). Set in Coolify's app settings for
|
||||
production, not in a committed `.env` — this app has no other secrets.
|
||||
if unset, see `app/lib/payload.ts`). `PAYLOAD_PREVIEW_SECRET` (no safe
|
||||
default — required for Live Preview, see below; must match the value set on
|
||||
the Payload backend). `NEXT_PUBLIC_PAYLOAD_URL` (optional, defaults to the
|
||||
same `https://payload.mk360.de` — only needed if the client-side Live
|
||||
Preview components should ever point somewhere else). Set in Coolify's app
|
||||
settings for production, not in a committed `.env` — this app has no other
|
||||
secrets.
|
||||
|
||||
## Pages
|
||||
|
||||
@@ -79,13 +84,16 @@ admin-gated in the Payload admin UI at `payload.mk360.de/admin`.
|
||||
| `shipping-settings` | Delivery-time disclosure shown on `/shop`, homepage spotlight, ToDo-Karten, `/cart`, `/checkout`, `/versand` (Art. 246a §1 Abs.1 Nr.8 EGBGB requires this visible before checkout) | `handlingDaysMin`/`handlingDaysMax` (processing time before it ships), `transitDaysMin`/`transitDaysMax` (carrier time) — the app derives the combined total itself. One row per tenant. |
|
||||
| `payment-methods` | `/checkout` payment selection | `title`, `icons` (array — e.g. 3 logos for "Kreditkarte"), `active`, `sortOrder` |
|
||||
| `werkzeuge-cards` | Homepage "Meine Werkzeuge" 3-card grid | `title`, `description`, `icon`, `ctaLabel`, `ctaHref`, `sortOrder` |
|
||||
| `testimonials` | Customer testimonial grids on `/todo-cards`, `/newsletter`, `/challenge` | `quote`, `name`, `role`, `avatar`, `page` (`todo-cards`/`newsletter`/`challenge` — which page's grid this appears in), `sortOrder`. The single-quote "photo band" testimonials on `/not-found` and `/bestellbestaetigung` are a different shape (no avatar/role) and stay hardcoded, not part of this collection. |
|
||||
| `media` | Shared upload collection backing every `image`/`icon`/`thumbnail`/`attachment` field above | `alt` (required for images), `title` (optional display name for download links) |
|
||||
|
||||
All of the above (except `media`, `users`, `tenants`) are grouped in the
|
||||
Payload admin sidebar under **Commerce** (`products`, `shipping-methods`,
|
||||
`shipping-settings`, `payment-methods`, `trust-badges`, `cart-trust-badges`)
|
||||
or **Content** (`posts`, `categories`, `legal-pages`, `werkzeuge-cards`);
|
||||
`media`/`users`/`tenants` sit under **Platform**.
|
||||
or **Content** (`posts`, `categories`, `legal-pages`, `werkzeuge-cards`,
|
||||
`testimonials`); `media`/`users`/`tenants` sit under **Platform** — `users`
|
||||
and `tenants` are hidden from non-super-admins' nav entirely (see the infra
|
||||
README's Payload CMS section for the access-control details).
|
||||
|
||||
Editorial changes (prices, copy, images, toggling a shipping/payment method
|
||||
on or off) all happen in the Payload admin UI — no code deploy needed. Adding
|
||||
@@ -93,6 +101,45 @@ a *new field* to any collection above requires editing the collection file in
|
||||
`docker/payload/src/collections/` and a migration, which does need a deploy
|
||||
of the Payload service.
|
||||
|
||||
### Live Preview
|
||||
|
||||
`posts`, `legal-pages`, and `testimonials` support Payload's Live Preview —
|
||||
opening a document in the Payload admin shows this app's real rendered page
|
||||
in an iframe, updating as you type, no save required.
|
||||
|
||||
- **`app/api/preview/route.ts`** — validates `PAYLOAD_PREVIEW_SECRET`
|
||||
(matching value required on the Payload side too, or this route 401s) and
|
||||
a `path`, enables Next.js Draft Mode, then redirects into the real page.
|
||||
This is the link Payload's `livePreview.url` resolvers point at (see
|
||||
`docker/payload/src/lib/previewUrl.ts` in the infra repo) — never the page
|
||||
directly.
|
||||
- Each supported page checks `draftMode().isEnabled` and renders a
|
||||
`"use client"` Live-Preview-aware component instead of the plain static
|
||||
one only when it's `true` — ordinary visitors are never in Draft Mode, so
|
||||
they always get the plain version with zero extra client JS:
|
||||
- `app/components/LiveRichText.tsx` — the 4 legal pages' body content
|
||||
(their headings/sidebars are hardcoded per page, not CMS-sourced, so
|
||||
`content` is the only field worth live-previewing there)
|
||||
- `app/blog/[slug]/components/LivePostContent.tsx` — title/excerpt/
|
||||
thumbnail/body of a blog post (the author bio card, "Weiterlesen" card,
|
||||
and Footer stay static — they either aren't post-specific or are about
|
||||
a *different* post, not the one open in the admin)
|
||||
- `app/components/LiveTestimonialsGrid.tsx` — the one testimonial
|
||||
currently open in the admin, merged by `id` into the rest of that
|
||||
page's already-fetched grid (Live Preview is inherently single-document,
|
||||
but this page renders several at once)
|
||||
- All three use `@payloadcms/live-preview-react`'s `useLivePreview` hook and
|
||||
reuse the same mapping functions (`mapPayloadPost`, `mapPayloadTestimonial`,
|
||||
exported from `app/lib/payload.ts`) the plain server-side fetchers use, so
|
||||
the two code paths can't silently drift apart.
|
||||
- `app/lib/payload.ts` deliberately never imports `next/headers` itself —
|
||||
callers (the Server Component pages) call `draftMode()` themselves and
|
||||
pass the result in as a plain `{ draft: boolean }` option. Importing
|
||||
`next/headers` anywhere in that module breaks the production build the
|
||||
moment a `"use client"` component (which also needs this file's mapping
|
||||
functions/types) tries to bundle it — a real RSC-boundary regression hit
|
||||
once already when adding this feature.
|
||||
|
||||
## Cart & checkout — demo status
|
||||
|
||||
- **Cart** (`app/lib/cart.ts`) is entirely client-side, stored in
|
||||
|
||||
Reference in New Issue
Block a user