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
| Property | Type | Description |
|---|---|---|
layout | string | Layout file name from layouts/ (without .njk) |
title | string | Page title for SEO and breadcrumbs |
widgets | array | Ordered 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"
}
}
]
}
| Property | Type | Description |
|---|---|---|
name | string | Instance name shown in theme builder |
widget | string | Widget folder name from widgets/ |
settings | object | Widget-level settings values |
blocks | array | Block 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
- The layout file (
layouts/layout.njk) is loaded - Templates are rendered (header, footer, global) via
{% template %}tags - 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
namevalues 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
widgetmatches a folder inwidgets/ - JSON errors? Validate brackets and commas
- Use the browser console for template errors