4.2 KiB
Product Templates
Intent
Product detail pages support customizable templates. Editors should be able to pick a template per product. The site pulls template options by enumerating the directories under webroot/Products/.
This lets product marketing teams build visually distinct product pages without rebuilding the platform each time, while still staying inside the brand visual system.
Template Directory Structure
Each template lives under:
webroot/Products/<template-id>/
Each template directory must contain exactly three subdirectories:
webroot/Products/<template-id>/
assets/
zh/
index.html
en/
index.html
Folder Roles
assets/— shared static resources for this template (images, videos, stylesheets, scripts).zh/index.html— Chinese version of the rendered product page for this template.en/index.html— English version of the rendered product page for this template.
Rules
- The three folders
assets,zh,enare required. - A template is considered valid only if both
zh/index.htmlanden/index.htmlexist. - Asset references inside
index.htmlshould use paths relative to the template root, for example./assets/hero.jpg. - Template IDs are the directory names; they are used as the value stored in CMS.
- Template IDs should be URL-safe (letters, digits, dashes, underscores).
Template Discovery Rule
The build / CMS layer must enumerate webroot/Products/* inside this project and produce a list of valid template IDs. Product content entries in Payload reference one of these template IDs through a template field.
Validation
- If a product references a template ID that no longer exists, the build should fail loudly rather than silently fall back.
- If a template directory is missing
assets,zh/index.html, oren/index.html, it must not be exposed as a selectable option.
CMS Field
Each Product record in Payload has a template field:
- Type: select
- Source: dynamic enumeration of valid template directories under
webroot/Products/ - Required: true
If the template list is empty, product pages fall back to the default system-rendered product layout.
Rendering Strategy
When rendering a product detail page:
- Look up the product entry in Payload by slug.
- Read the
templatefield. - If a matching template exists in
webroot/Products/<template-id>/<locale>/index.html, inject that HTML into the central product-body region inside the Next.js product route. - Serve template assets from
/products-tmp/<template-id>/assets/....
Chrome Rules
- Header, footer, language switch, and breadcrumb are always rendered by the main Next.js layout.
- The template only owns the middle content region of the product detail page.
- Templates do not need to include header or footer markup.
- Templates must not override global navigation, language switch, cookie banner, or footer.
SEO
- Page metadata (title, description, OG image, canonical, hreflang) comes from Payload, not from the template HTML.
- Any
<head>content inside the template HTML is ignored. h1tags inside the template should stay unique per product.
Content Ownership
- Template HTML and assets: created by design / marketing team.
- Template selection: owned in CMS per product.
- Product metadata (title, slug, hero image, summary, downloads, videos, reviews, SEO, related products): always managed in CMS, never hardcoded inside the template.
- Product detail pages must continue to render CMS-managed downloads, videos, and reviews outside the template-owned middle body region.
Naming Guidance
template-idshould describe the layout intent, not a specific product. Good examples:editorial-01,immersive-hero,split-feature. Avoid product-specific names likea10-page.
Workflow
- Designer or marketing team adds a new template directory into this project's
webroot/Products/. - Build pipeline enumerates available templates and updates the CMS select options.
- Editor picks the template on a Product entry.
- Page publishes with the selected template.
Open Questions
- Whether templates can depend on external CDN assets, or must be fully self-contained within
assets/. - Whether templates support a lightweight preview environment in CMS.