Template Sections
Update the UIs of existing sections while keeping the ecommerce boilerplate composable and data-aware.
What is a section?
A section is a reusable slice of a page. Each section:
- Receives a
Sectionobject with atypestring and aconfigpayload from JSON or CMS. - Renders independently (server or client) and can fetch its own data.
- Is mapped to
section.typein both JSON mocks and CMS responses.
Files live in app/_components/sections/ (e.g., HeroSection.tsx, ProductsSection.tsx, BannerSection.tsx, etc.).
Scope: You cannot add new sections or modify core plumbing. Changes must stay within existing section UIs (styling, layout, copy handling, states).
Anatomy of a section
- Signature: Every section component accepts
{ section: Section }. - Config-driven props: All styling/content comes from
section.config(titles, images, limits, filters, CTAs). Avoid hardcoded copy. - Data awareness: Sections can call hooks/fetchers for live data (e.g.,
useProductsQueryinProductsSection,getFileUrlfor assets). Provide graceful fallbacks for empty/error states. - Client vs server: Add
"use client"only when needed (hooks, state, effects). Many presentational sections can stay server components.
Example: HeroSection.tsx reads section.config.image, title, description, and primaryCta and uses helpers like getFileUrl/templateUrl to resolve assets and links.
Where sections are registered
- Build/local rendering:
app/page.tsxbuilds aSectionComponentMapand callsrenderSectionswithpageItemsfromdata/pages/index.json. - CMS-driven rendering:
lib/usePage.tsxswitches onsection.typewhen rendering pages likeabout/page.tsxandcontact/page.tsx.
For a section to render in all contexts, it must be added to both maps.
Updating an existing section (UI-only checklist)
- Stay within the file: Edit the section component in
app/_components/sections/*.tsx. Do not add new section files or modify registries. - Keep the contract: Do not change
section.typeor howsection.configis read; only adjust rendering (markup, classes, layout). - Respect data hooks: If the section fetches data (e.g.,
ProductsSectionusesuseProductsQuery), leave data flow intact and only update presentation or states. - Handle states: Preserve/clarify loading, empty, and error handling. If adding UI polish, ensure these states still work.
- Test locally: Use existing mocks in
data/pages/*.jsonor CMS data withBUILD_MODE=trueto verify UI changes.
Common patterns from existing sections
- Media-heavy:
BannerSectionandHeroSectionresolve images withgetFileUrland provide clickable CTAs viatemplateUrl. - List/data-driven:
ProductsSection,ProductCategoriesSection,ToursSection,CmsPostsSection, andGallerySectionfetch or render collections, handle loading placeholders, empty states, and errors. - Form/contact:
ContactSectionandFormSectionread fields fromconfigand use shared UI components. - Personalization:
LastViewedProductsSectionreads from cart/context to personalize content.
Use these as references for states, fallbacks, and config shapes.
Data contracts
Sectiontype (seetypes/sections.ts):type: stringconfig?: any(shape is section-specific; document the keys you expect)- Optional metadata:
content,contentType,contentTypeId,order,name
- Page JSON (
data/pages/*.json) usespageItems: Section[]. CMS responses mirror this shape (section.type,section.config).
Document expected config fields in PRs or code comments near the section to keep designers and CMS authors aligned.
Testing a section
- Local mock: Add the section to a
data/pages/*.jsonpage and runyarn devwithBUILD_MODEunset. Verify rendering, responsiveness, and accessibility. - Builder/CMS: Set
BUILD_MODE=trueand load the page via the builder to ensure the section works with live data and params. - Quality checks: Run
yarn lintand ensure the section handles loading, empty, and error states without crashing.