Page:
Layout Template System Guidelines
Pages
Abstract layout template
Carousel Feedback Component Guideline
Category Highlight Section Guidelines
Footer component config guideline
Footer component guideline config
Guidelines for Component Design
Header component guideline config
Homepage Category Highlight Component Guidelines setup
Layout Template System Guidelines
Product Card config Guideline
VtBrand usage guideline
VtFeedbackCard component guideline
Table of Contents
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Guidelines
- We have defined 3 example pages which should be recreatable by our layout template system.
- Our starting point is the next.js-starter template provided by medusa.
- The starter template uses medusa ui .
- Our Layout Template System should use medusa ui as base.
- Custom Components should be built on top of medusa ui. If medusa ui does not provide a specific component, an independent custom component can be implemented.
- To look into how different medusa patterns work, there are tutorials and resources for building a custom storefront.
- Do not work destructively! This means guaranteeing that the new system can still represent the starter template design
Layout System
The Layout System is comprised of following modules:
- Data Layer: json data file
- This file defines which component should be rendered where and how by parameters.
- This should be the only file to edit.
- A configloader.ts loads the json by filesystem.
- It is abstracted as LayoutComponentNodes and LayoutContext
- Dynamic Render System
- The Render System should be based on medusa next.js starter routes, components and templates.
- Additional components and templates should be put into /vibentec/ subfolders
- Each renderable component has to be added to the ComponentMap
- Shared dynamic Components
- Each of the 3 example pages has to be analyzed and components have to be extracted so any of those different pages can be rendered by those same components.
- This should never result in 3 different templates or components for the same ui-component or layouting block. (e.g. menu or button)
- If the differences are great, try to manage differences by creating reusable sub-components first.
- Rules for Creating Custom Components
- When creating a custom component, avoid creating singular components; instead, group related elements together to limit the length of the JSON file.
- Components should be designed to allow flexible layout adjustments of the elements.
- Once created, register the component in the
component-map.tsxfile. Set the key as the component's name, then map it back to the component you created for initialization when the JSON file uses that component.
Goal
- Only the Json File is responsible for layout and design for the pages
- Dynamic Render System uses json-file to build layout and page using shared dynamic components.
Layout Template System Guidelines
This guide explains how to configure and use the JSON‑driven layout and page template system so UI components render only on the routes you intend.
Concepts
layout: global UI rendered around all pages (header, nav,PropsChildren, footer).pages: route‑specific UI, configured per page key (e.g.,Home,Product).DynamicLayoutRenderer: reads nodes and renders mapped React components.componentMap: maps JSON keys to components and determines howconfigandchildrenare passed.
Files
- Design JSON:
config/nam.mds-starter-design.json - Loader functions:
src/vibentec/configloader.ts:13–28 - Component map:
src/vibentec/component-map.tsx:76–112 - Renderer:
src/vibentec/renderer.tsx:8–28 - App layout usage:
src/app/[countryCode]/(main)/layout.tsx:34–45 - Page usage (Home):
src/app/[countryCode]/(main)/page.tsx:27–42 - Page usage (Product):
src/app/[countryCode]/(main)/products/[handle]/page.tsx:102–121
JSON Schema
Structure of the design file:
{
"layout": [
{ "Header": { "config": { "sticky": true }, "children": [/* ... */] } },
{ "PropsChildren": {} },
{ "Footer": { "config": { /* footer columns */ } } }
],
"pages": {
"Home": [
{ "Hero": { "config": { "variant": "default", "className": "bg-custom-gradient" } } },
{ "VtFeaturedProducts": { "config": { "title": "best-seller" } } },
{ "FreeShippingPriceNudge": { "config": { "variant": "popup" } } }
],
"Product": [
{ "VtFeaturedProducts": { "config": { "title": "best-seller" } } }
]
}
}
See: config/nam.mds-starter-design.json:2–18, 188–236.
Render Flow
- App layout loads
layoutvialoadLayoutConfigand renders it once for all routes:src/app/[countryCode]/(main)/layout.tsx:34–45. - Each page loads its array via
loadPageConfig("Key")and renders it where needed.
Example: Home
- Loads and renders
pages["Home"]with a layout context containingregionandcountryCode:src/app/[countryCode]/(main)/page.tsx:27–42.
Example: Product
- Renders
ProductTemplate, then appendspages["Product"]below:src/app/[countryCode]/(main)/products/[handle]/page.tsx:115–121.
Configuring Components
- Components accept a
configobject and optionalchildrenarrays. - Map of available keys is defined in
componentMap:src/vibentec/component-map.tsx:76–112. - Two mapping strategies:
configOnly(Component): passesconfigprops directly (e.g., banners likeCartMismatchBanner).nodesContextRenderer(Component): passes bothnodesand renderingcontext(most layout templates).
VtFeaturedProducts
- Place it under a page key to control visibility.
config.titlecan be a collectionhandleortitleto filter rails.- Uses
regionandcountryCodefrom the page context.
Example:
{
"pages": {
"Home": [
{ "VtFeaturedProducts": { "config": { "title": "best-seller" } } }
],
"Product": [
{ "VtFeaturedProducts": { "config": { "title": "best-seller" } } }
]
}
}
Hero
- Configure variant and class names under the
Homepage to show only on the front page.
PropsChildren
- Acts as a slot for the page’s own React content.
- Keep it in
layoutso page templates render inside the global shell.
Adding Page‑Specific UI
- Choose a page key like
Home,Product,Category,Collection,Store. - Add an array under
pages[Key]with your components. - In the corresponding page file, load and render:
import { DynamicLayoutRenderer } from "@vibentec/renderer"
import { loadPageConfig } from "@vibentec/configloader"
import { LayoutContext } from "@vibentec/component-map"
const nodes = await loadPageConfig("Home")
const context: LayoutContext = { /* region, countryCode, etc. */ }
return <DynamicLayoutRenderer nodes={nodes} context={context} />
Adding New Components
- Implement a template component that accepts
{ nodes, context }. - Register the JSON key in
componentMapusing eithernodesContextRendererorconfigOnly. - Example map entry:
src/vibentec/component-map.tsx:76–112.
Selecting a Design File
- Switch the active JSON file name in
src/vibentec/devJsonFileNames.ts:1–8and updatefileNameinsrc/vibentec/configloader.ts:5if needed. - Current active file:
jsonFileNames.namStarter.
Backward Compatibility
- If the JSON is a top‑level array (legacy schema), loaders treat it as
layoutandpagesresolve to empty arrays. Migrate incrementally by introducingpagesper route.
Troubleshooting
- Unknown component key logs a warning in the renderer:
src/vibentec/renderer.tsx:16–22. - Empty or missing
pages[Key]renders nothing for that route. - Ensure page context includes
regionandcountryCodewhen components depend on them.
Configuration Checklist
- Update your design JSON with
layoutandpageskeys. - Keep global UI under
layout; place route‑specific UI underpages[Key]. - Verify page files call
loadPageConfig("Key")and renderDynamicLayoutRenderer. - Confirm
componentMapincludes the JSON keys you use.