193 lines
8.2 KiB
Markdown
193 lines
8.2 KiB
Markdown
|
|
# Payload Schema — Product Collection (Final)
|
||
|
|
|
||
|
|
## Purpose
|
||
|
|
Single source of truth for the Product collection in Payload. This is the version that will be implemented in code. All product detail pages (system-rendered layout and project-local HTML templates) depend on this schema.
|
||
|
|
|
||
|
|
## Collection Slug
|
||
|
|
`products`
|
||
|
|
|
||
|
|
## Localization
|
||
|
|
- Locales: `en`, `zh`
|
||
|
|
- Each locale can be edited and published independently.
|
||
|
|
- Fields marked **localized** below use Payload field-level localization.
|
||
|
|
- Fields marked **shared** are global and the same across locales.
|
||
|
|
|
||
|
|
## Access Control
|
||
|
|
- Public read: only documents with `status = published`.
|
||
|
|
- Write: authenticated editors and above.
|
||
|
|
- Admin-only fields: `seo.noIndex`, `template`, `firmware.showOnProductPage`, `firmware.showInDownloadsCenter`.
|
||
|
|
|
||
|
|
## Status Workflow
|
||
|
|
- `draft`
|
||
|
|
- `review`
|
||
|
|
- `published`
|
||
|
|
- `archived`
|
||
|
|
|
||
|
|
## Fields
|
||
|
|
|
||
|
|
### 1. Identity
|
||
|
|
|
||
|
|
- `slug` — **localized** — text, required, unique per locale, URL-safe.
|
||
|
|
- `model` — **shared** — text, required. The marketing model name, for example `DMP-A10`.
|
||
|
|
- `status` — **shared** — select, required, one of `draft | review | published | archived`.
|
||
|
|
- `order` — **shared** — number, default 0. Used for manual ordering inside category listings.
|
||
|
|
- `category` — **shared** — relationship to `productCategories`, required.
|
||
|
|
|
||
|
|
### 2. Template Selection
|
||
|
|
|
||
|
|
- `template` — **shared** — select, required, options dynamically enumerated from valid directories under `webroot/Products/`. If no templates exist, the UI falls back to the default system-rendered layout.
|
||
|
|
- `templateEnabled` — **shared** — checkbox, default false. When true, the product detail route injects the HTML template into the middle content region. When false, the default system-rendered layout is used even if a template is selected.
|
||
|
|
|
||
|
|
### 3. Marketing Copy (localized)
|
||
|
|
|
||
|
|
- `name` — **localized** — text, required. Display name shown in cards and headings.
|
||
|
|
- `tagline` — **localized** — text. One-line descriptor used in product cards and hero.
|
||
|
|
- `summary` — **localized** — rich text. Short paragraph used on overview pages.
|
||
|
|
- `overview` — **localized** — rich text. Longer intro used in the system-rendered layout.
|
||
|
|
|
||
|
|
### 4. Media
|
||
|
|
|
||
|
|
- `heroImage` — **shared** — upload, required. Used in the top of default-rendered product pages and as card image.
|
||
|
|
- `cardImage` — **shared** — upload, optional. Optional override for the featured product card. Horizontal composition preferred to align with homepage visual spec.
|
||
|
|
- `gallery` — **shared** — array of uploads, optional. Ordered product imagery.
|
||
|
|
- `lifestyleImage` — **shared** — upload, optional. Used for lifestyle placement in listings or cross-links.
|
||
|
|
- `heroVideo` — **shared** — group, optional.
|
||
|
|
- `src` — upload or URL.
|
||
|
|
- `poster` — upload.
|
||
|
|
|
||
|
|
### 5. Key Features (localized content, shared structure)
|
||
|
|
|
||
|
|
`keyFeatures` — array, 0 to 8 items.
|
||
|
|
Per item:
|
||
|
|
- `icon` — **shared** — upload, optional.
|
||
|
|
- `image` — **shared** — upload, optional.
|
||
|
|
- `title` — **localized** — text, required.
|
||
|
|
- `description` — **localized** — rich text.
|
||
|
|
|
||
|
|
### 6. Technology Highlights (localized)
|
||
|
|
|
||
|
|
`technologyHighlights` — **localized** — rich text with blocks.
|
||
|
|
Allowed blocks:
|
||
|
|
- `textBlock`
|
||
|
|
- `imageTextBlock`
|
||
|
|
- `quoteBlock`
|
||
|
|
|
||
|
|
### 7. Specifications
|
||
|
|
|
||
|
|
`specifications` — array of spec groups.
|
||
|
|
Per group:
|
||
|
|
- `groupName` — **localized** — text, required.
|
||
|
|
- `order` — **shared** — number, default 0.
|
||
|
|
- `items` — array.
|
||
|
|
- `label` — **localized** — text, required.
|
||
|
|
- `value` — **localized** — text, required.
|
||
|
|
- `note` — **localized** — text, optional.
|
||
|
|
|
||
|
|
### 8. Firmware (display is opt-in)
|
||
|
|
|
||
|
|
`firmware` — group.
|
||
|
|
- `showOnProductPage` — **shared** — checkbox, default false. Controls whether firmware is displayed on the product detail page.
|
||
|
|
- `showInDownloadsCenter` — **shared** — checkbox, default false. Controls whether this product's firmware appears in the site-wide Downloads center.
|
||
|
|
- `displayLabel` — **localized** — text, optional. Overrides the default section title on the product page.
|
||
|
|
- `items` — relationship to `downloads`, filtered to `type = firmware`, multi-select, ordered.
|
||
|
|
- `notes` — **localized** — rich text, optional. Release notes or compatibility notes rendered above the list.
|
||
|
|
|
||
|
|
UI rules:
|
||
|
|
- The two visibility toggles are independent. Either can be on or off without affecting the other.
|
||
|
|
- `items` and `notes` are edited independently of the toggles; disabling both toggles hides firmware from public UI but preserves data.
|
||
|
|
- Payload UI should clearly show current visibility status on each product record.
|
||
|
|
|
||
|
|
### 9. Downloads (non-firmware)
|
||
|
|
|
||
|
|
`downloads` — group.
|
||
|
|
- `manuals` — relationship to `downloads`, filtered to `type = manual`, multi-select.
|
||
|
|
- `software` — relationship to `downloads`, filtered to `type = software`, multi-select.
|
||
|
|
- `other` — relationship to `downloads`, filtered to `type = other`, multi-select.
|
||
|
|
|
||
|
|
These are always available on the product page when entries exist. The firmware module is separated because its visibility is opt-in.
|
||
|
|
|
||
|
|
### 10. Relations
|
||
|
|
|
||
|
|
- `relatedProducts` — relationship to `products`, multi-select, up to 4.
|
||
|
|
- `accessories` — relationship to `products`, multi-select, optional.
|
||
|
|
- `featuredDealers` — relationship to `dealers`, multi-select, optional.
|
||
|
|
|
||
|
|
### 11. Awards and Reviews (optional on detail page)
|
||
|
|
|
||
|
|
`awards` — array, optional.
|
||
|
|
Per item:
|
||
|
|
- `logo` — **shared** — upload.
|
||
|
|
- `label` — **localized** — text.
|
||
|
|
- `year` — **shared** — number.
|
||
|
|
- `url` — **shared** — URL, optional.
|
||
|
|
|
||
|
|
`reviews` — array, optional.
|
||
|
|
Per item:
|
||
|
|
- `sourceLogo` — **shared** — upload, optional.
|
||
|
|
- `sourceName` — **localized** — text.
|
||
|
|
- `quote` — **localized** — text, required.
|
||
|
|
- `url` — **shared** — URL, optional.
|
||
|
|
|
||
|
|
### 12. SEO
|
||
|
|
|
||
|
|
`seo` — group, **localized**.
|
||
|
|
- `title` — text, max 70 chars.
|
||
|
|
- `description` — textarea, max 160 chars.
|
||
|
|
- `ogImage` — upload.
|
||
|
|
- `canonical` — text, optional.
|
||
|
|
- `noIndex` — checkbox, admin-only, default false.
|
||
|
|
|
||
|
|
### 13. Timestamps (auto)
|
||
|
|
|
||
|
|
- `createdAt`
|
||
|
|
- `updatedAt`
|
||
|
|
- `publishedAt`
|
||
|
|
|
||
|
|
## Hooks
|
||
|
|
|
||
|
|
- `beforeValidate`:
|
||
|
|
- Normalize `slug` (lowercase, trim, ASCII fallback, dashes).
|
||
|
|
- `beforeChange`:
|
||
|
|
- Auto-set `publishedAt` when `status` transitions to `published` for the first time.
|
||
|
|
- If `template` refers to a non-existent directory, reject with a validation error.
|
||
|
|
- `afterChange`:
|
||
|
|
- Trigger on-demand revalidation for `/en/products`, `/zh/products`, `/en/products/<slug>`, `/zh/products/<slug>`.
|
||
|
|
- Trigger revalidation for Homepage if the product is part of `Homepage.featuredProducts`.
|
||
|
|
|
||
|
|
## Admin UI Layout (recommended tabs)
|
||
|
|
1. `Overview` — identity, status, template, name, tagline, summary, category, order.
|
||
|
|
2. `Content` — overview, keyFeatures, technologyHighlights, specifications.
|
||
|
|
3. `Media` — heroImage, cardImage, gallery, lifestyleImage, heroVideo.
|
||
|
|
4. `Firmware` — firmware group.
|
||
|
|
5. `Downloads` — downloads group.
|
||
|
|
6. `Relations` — relatedProducts, accessories, featuredDealers.
|
||
|
|
7. `Recognition` — awards, reviews.
|
||
|
|
8. `SEO` — seo group.
|
||
|
|
|
||
|
|
## Rendering Rules (summary)
|
||
|
|
- If `templateEnabled` is true and `template` resolves to a valid directory, render:
|
||
|
|
- Header (from main layout)
|
||
|
|
- Breadcrumb (from main layout)
|
||
|
|
- Optional hero block (from CMS)
|
||
|
|
- **Middle content region** populated by `webroot/Products/<template>/<locale>/index.html`
|
||
|
|
- Firmware module (only if `firmware.showOnProductPage`)
|
||
|
|
- Related downloads, related products, recognition (if present)
|
||
|
|
- Footer (from main layout)
|
||
|
|
- Otherwise, render the default system-rendered layout using the structured fields above.
|
||
|
|
- The site-wide Downloads center lists firmware entries only for products with `firmware.showInDownloadsCenter = true`.
|
||
|
|
|
||
|
|
## Validation Rules
|
||
|
|
- `slug` must be unique per locale.
|
||
|
|
- `model` required.
|
||
|
|
- `category` required.
|
||
|
|
- `heroImage` required.
|
||
|
|
- `template` required; must reference an existing directory.
|
||
|
|
- `firmware.items` must all have `type = firmware`.
|
||
|
|
- `awards[].year` must be between 1990 and current year + 1.
|
||
|
|
- At least one locale must have `status = published` before the product is publicly visible.
|
||
|
|
|
||
|
|
## Open Items
|
||
|
|
- Whether `status` should be a per-locale field to allow a product to go live in EN before ZH.
|
||
|
|
- Whether `templateEnabled` toggle is visible to all editors or admin-only.
|
||
|
|
- Whether recognition (awards, reviews) should also live at brand level, not just per product.
|