Documentation
Feedback
Guides
Storefront Development

Storefront Development
Store FrameworkGetting started4. Configuring templates
4. Configuring templates

Learn how to manage templates and customize your Store Theme.

In this guide, you'll learn how to customize your store theme by managing templates that define the structure of your website pages. Templates declare JSON blocks that, once rendered, determine the set of components for your website pages, such as the homepage, product page, search results page, etc.

The Store Theme app already implements basic templates for each page of your store, defined within its blocks.json or blocks.jsonc files. These templates enable your store to display VTEX Store Framework default components, even if you haven’t made any custom configurations in the code. By managing templates, you can create a custom theme for your website by adding or removing blocks to meet your business needs.

Before you begin

Learn about the JSON block concept

Familiarize yourself with the concept of a JSON block - the smallest Store Framework abstraction of React components displayed on the user interface. Thus, blocks are self-contained pieces of code, exported to the platform by independent apps, that determine how components are rendered on your website.

Blocks are imbued with higher flexibility, allowing you to achieve complex scenarios and specific component behaviors by configuring their properties (props) or even declaring them in other blocks. In practice, when you edit your theme's code using the Store Theme app, you're directly modifying blocks that will become your store's page components when rendered.

To add a new component to a page, you simply declare a new block in the corresponding template. Similarly, removing a block from a template will exclude its associated component from the page.

Get to know the property (prop) concept

To manage your templates efficiently, be familiar with the concept of properties (prop), which define the performance and visual identity of the component rendered in the interface. The more props a block has, the more flexible its configuration becomes for the end user.

Every JSON is defined using { }, with keys and values that together specify its properties, representing its inherent characteristics. See the example below:


_10
{
_10
"name": "Pedro",
_10
"height": 1.90
_10
}

In the example above, name and height are the object's keys, and their respective values are Pedro and 1.90.

The key + value pair constitutes the property (or prop) of the JSON, defining its essential characteristics.

The key and value can also be called, respectively, property name and property value.

Understand the block composition

When a block is being developed, the composition definition indicates how the block’s content is structured or how it interacts with other components. There are 3 types of composition definitions:

  • blocks: Have a fixed position on the store’s page irrespective of where they were declared in the code, leading to a preordained position on the UI.
  • children: Do not have a fixed position on the store’s page, which means that how they’re declared in the code directly impacts the page position. The children block declared first will be at the top of the page, followed by the second one below it, and so on.
  • slots: Placeholders within a block that enable the insertion of dynamic content. It is useful for flexible component design where content can be passed into specific slots, enabling the customization or reuse of a block with different content.

According to their composition, the listed blocks will determine whether they should be declared in the parent block's blocks list or in its children list when building a single component on the UI.

You can find out which composition a block has by looking at its code in the exporting app's interfaces.json file.

Instructions

Step 1 - Declaring blocks in your Store Theme app

Declare all your blocks in the blocks.jsonc file, or create as many files and folders as needed within the store folder to organize store blocks and templates. You can also declare blocks in the blocks subfolder. The only difference is that jsonc files allow you to add comments to the code.

Since blocks are pieces of code exported by VTEX Store Framework apps, whenever a block is used in your theme, the app behind it must be declared in your Store Theme dependencies list.

The dependencies object within the manifest.json file of your Store Theme app specifies the names and versions of various apps. These apps are pre-listed, as the default Store Theme code already defines templates that use blocks exported by them.

When declaring a new block in your Store Theme app, check if the app blocking it is listed as a dependency. If not, open the manifest.json file and add the app name and desired version to the dependencies list, following this format: "vtex.{appName}": "{majorVersion}.x".

Replace the values between the curly braces based on your scenario.

Step 2 - Managing blocks in your theme

To better understand how to manage blocks within your Store Theme app, follow the steps below to see the structure of the predefined homepage template:

  1. Open the Store Theme app using the code editor of your choice.
  2. Go to store and then blocks.
  3. Access home and then home.jsonc. You'll see a result similar to the following:

_123
{
_123
"store.home": {
_123
"blocks": [
_123
"list-context.image-list#demo",
_123
/* You can make references to blocks defined in other files.
_123
* For example, `flex-layout.row#deals` is defined in the `deals.json` file. */
_123
"flex-layout.row#deals",
_123
"rich-text#shelf-title",
_123
"flex-layout.row#shelf",
_123
"info-card#home",
_123
"rich-text#question",
_123
"rich-text#link",
_123
"newsletter"
_123
]
_123
},
_123
_123
"shelf#home": {
_123
"blocks": ["product-summary.shelf"]
_123
},
_123
_123
"product-summary.shelf": {
_123
"children": [
_123
"product-summary-name",
_123
"product-summary-description",
_123
"product-summary-image",
_123
"product-summary-price",
_123
"product-summary-sku-selector",
_123
"product-summary-buy-button"
_123
]
_123
},
_123
_123
"list-context.image-list#demo": {
_123
"children": ["slider-layout#demo-images"],
_123
"props": {
_123
"height": 720,
_123
"images": [
_123
{
_123
"image": "https://storecomponents.vteximg.com.br/arquivos/banner-principal.png",
_123
"mobileImage": "https://storecomponents.vteximg.com.br/arquivos/banner-principal-mobile.jpg"
_123
},
_123
{
_123
"image": "https://storecomponents.vteximg.com.br/arquivos/banner.jpg",
_123
"mobileImage": "https://storecomponents.vteximg.com.br/arquivos/banner-principal-mobile.jpg"
_123
}
_123
]
_123
}
_123
},
_123
"slider-layout#demo-images": {
_123
"props": {
_123
"itemsPerPage": {
_123
"desktop": 1,
_123
"tablet": 1,
_123
"phone": 1
_123
},
_123
"infinite": true,
_123
"showNavigationArrows": "desktopOnly",
_123
"blockClass": "carousel"
_123
}
_123
},
_123
_123
"rich-text#shelf-title": {
_123
"props": {
_123
"text": "## Summer",
_123
"blockClass": "shelfTitle"
_123
}
_123
},
_123
"flex-layout.row#shelf": {
_123
"children": ["list-context.product-list#demo1"]
_123
},
_123
"list-context.product-list#demo1": {
_123
"blocks": ["product-summary.shelf"],
_123
"children": ["slider-layout#demo-products"],
_123
"props": {
_123
"orderBy": "OrderByTopSaleDESC"
_123
}
_123
},
_123
"slider-layout#demo-products": {
_123
"props": {
_123
"itemsPerPage": {
_123
"desktop": 5,
_123
"tablet": 3,
_123
"phone": 1
_123
},
_123
"infinite": true,
_123
"fullWidth": true,
_123
"blockClass": "shelf"
_123
}
_123
},
_123
_123
"info-card#home": {
_123
"props": {
_123
"id": "info-card-home",
_123
"isFullModeStyle": false,
_123
"textPosition": "left",
_123
"imageUrl": "https://storecomponents.vteximg.com.br/arquivos/banner-infocard2.png",
_123
"headline": "Clearance Sale",
_123
"callToActionText": "DISCOVER",
_123
"callToActionUrl": "/sale/d",
_123
"blockClass": "info-card-home",
_123
"textAlignment": "center"
_123
}
_123
},
_123
_123
"rich-text#question": {
_123
"props": {
_123
"text": "**This is an example store built using the VTEX platform.\nWant to know more?**",
_123
"blockClass": "question"
_123
}
_123
},
_123
_123
"rich-text#link": {
_123
"props": {
_123
"text": "\n**Reach us at**\nwww.vtex.com.br",
_123
"blockClass": "link"
_123
}
_123
},
_123
_123
"product-summary-buy-button": {
_123
"props": {
_123
"displayBuyButton": "displayButtonAlways"
_123
}
_123
}
_123
}

As you can see above, the default store.home homepage template declares the following blocks:

  • list-context.image-list#demo
  • flex-layout.row#deals
  • rich-text#shelf-title
  • flex-layout.row#shelf
  • info-card#home
  • rich-text#question
  • rich-text#link
  • newsletter

This means that your default store homepage will comprise the components defined by these blocks.

To build more complex components, the home.jsonc file includes each block’s declaration and configuration, using the block's props and, if necessary, other blocks.

More than simply declaring a block in the block list template, you must also define its behavior when rendered as a component. To do this, use the block's props, as shown in the Clarifying block naming and properties section, and include other child blocks to configure it, as detailed in Defining blocks composition.

Step 3 - Clarifying block naming and properties

Still in the home.jsonc file, use ctrl+f and search for the rich-text#question block. This block renders a component that displays markdown text to users.


_10
"rich-text#question": {
_10
"props": {
_10
"text": "**This is an example store built using the VTEX platform. Want to know more?**",
_10
"blockClass": "question"
_10
}
_10
},

The rich-text#question block has two props: text and blockClass. The text prop specifies the content the component will display, while blockClass defines an ID used for customization.

To check the available props of the app behind the rich-text block, see the Configuration section within the Rich Text app documentation. Note that the exported block's name is simply rich-text, whereas Store Theme uses rich-text#block. This is because you can use a # symbol after the block's official name to easily identify it when inserting it into the theme's code and better organize the theme.

All the props available to configure a block can be found in the documentation of its exporting app or in the block's own documentation (if applicable).

Step 4 - Defining blocks composition

Still in the home.jsonc, search for theshelf#home block.


_10
"shelf#home": {
_10
"blocks": ["product-summary.shelf"]
_10
},

Note that it declares another block to your blocks list, which in turn declares other blocks below in a list called children:


_10
"product-summary.shelf": {
_10
"children": [
_10
"product-summary-name",
_10
"product-summary-description",
_10
"product-summary-image",
_10
"product-summary-price",
_10
"product-summary-sku-selector",
_10
"product-summary-buy-button"
_10
]
_10
},

In the example above, product-summary.shelf requires other blocks as children, such as product-summary-name, to render the component properly.

As previously mentioned, a component can be a crossroad for multiple blocks. Therefore, one of your theme blocks may need to list other blocks to achieve the desired rendering on the UI.

To build a component using multiple blocks, the main block can declare a blocks list, such as shelf#home, or a children list, as seen in the product-summary.shelf block.

As explained in Understand the block composition, the choice between using a blocks or children list depends on the composition of the blocks being declared.

Contributors
2
Photo of the contributor
Photo of the contributor
+ 2 contributors
Was this helpful?
Yes
No
Suggest Edits (GitHub)
Contributors
2
Photo of the contributor
Photo of the contributor
+ 2 contributors
On this page