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. Thechildren
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:
- Open the Store Theme app using the code editor of your choice.
- Go to
store
and thenblocks
. - Access
home
and thenhome.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.