Skip to main content

Pages

Each JSON file in the pages/ folder represents a page in your theme. Pages define which layout to use and which widgets to display.

Page Files

pages/
├── index.json # Homepage
├── product.json # Single product page
├── collection.json # Collection/category page
├── cart.json # Shopping cart
├── search.json # Search results
├── blog.json # Blog listing
├── article.json # Single blog article
├── page.json # Generic page
└── collections.json # Collections listing

Page Structure

{
"layout": "layout",
"title": "Homepage",
"widgets": [
{
"name": "hero-slider",
"widget": "hero-slider",
"settings": { ... },
"blocks": [ ... ]
}
]
}

Properties

PropertyTypeDescription
layoutstringLayout file name from layouts/ (without .njk)
titlestringPage title for SEO and breadcrumbs
widgetsarrayOrdered list of widget instances

Widget Instance

Each widget in the widgets array has:

{
"name": "hero-slider",
"widget": "hero-slider",
"settings": {
"autoplay": true,
"speed": 5,
"contentPosition": "center",
"titleColor": "#ffffff"
},
"blocks": [
{
"block": "slide",
"name": "Slide 1",
"settings": {
"title": "Welcome to Our Store",
"description": "Discover amazing products",
"buttonText": "Shop Now",
"buttonUrl": "/collections"
}
}
]
}
PropertyTypeDescription
namestringInstance name shown in theme builder
widgetstringWidget folder name from widgets/
settingsobjectWidget-level settings values
blocksarrayBlock instances (if widget supports blocks)

Complete Page Example

index.json (Homepage):

{
"layout": "layout",
"title": "Homepage",
"widgets": [
{
"name": "hero-slider",
"widget": "hero-slider",
"settings": {
"autoplay": true,
"speed": 5
},
"blocks": [
{
"block": "slide",
"name": "Welcome Slide",
"settings": {
"title": "Welcome to Our Store",
"buttonText": "Shop Now",
"buttonUrl": "/collections"
}
},
{
"block": "slide",
"name": "New Arrivals",
"settings": {
"title": "New Arrivals",
"buttonText": "Discover",
"buttonUrl": "/collections/new"
}
}
]
},
{
"name": "categories",
"widget": "categories",
"settings": {
"title": "Shop by Category",
"columns": 4
}
},
{
"name": "product-slider",
"widget": "product-slider",
"settings": {
"title": "Featured Products",
"collection": "featured"
}
},
{
"name": "testimonials",
"widget": "testimonials",
"settings": {
"title": "What Our Customers Say"
},
"blocks": [
{
"block": "testimonial",
"name": "Review 1",
"settings": {
"customerName": "Ahmed",
"review": "Great products and fast shipping!",
"rating": 5
}
}
]
}
]
}

How Pages Render

  1. The layout file (layouts/layout.njk) is loaded
  2. Templates are rendered (header, footer, global) via {% template %} tags
  3. Page widgets replace {% content %} in order
{# In layout.njk #}
<body>
{% template "header" %}

<main>
{% content " " %} {# Page widgets render here #}
</main>

{% template "footer" %}
</body>

Tips

Best Practices
  • Use descriptive name values for easy identification in the builder
  • Keep one page per file (product.json, search.json, etc.)
  • Provide sensible default settings values
  • Test widget arrangements with qumra theme dev
Debugging
  • Widget not showing? Check that widget matches a folder in widgets/
  • JSON errors? Validate brackets and commas
  • Use the browser console for template errors