Modules: Getting Started

Last updated:

In this tutorial, we will create our first module and see how we can use it in templates and pages as part of a theme. We’ll be constructing a Testimonial module that includes an image field, a text field, and a rich text field. 

If you want to jump ahead, you can preview the finished project files

An important note: In this tutorial, we’ll use the HubSpot CMS boilerplate theme. Because the boilerplate theme's code may change over time, we have decided to include only the most critical files that developers will need to create or edit during the tutorial. These files include:

  1. Testimonial.module - the folder containing the files that make up the custom module we will build as part of the tutorial.
  2. homepage.html - the template that we will be editing to include our custom module.
  3. images - the folder containing the profile pictures we will use in the Testimonial module. 

We're going to use the module editor in the Design Manager to build out our module. The module editor provides you with a more guided experience. Once you get comfortable, you may prefer developing modules locally — either is possible. Let's get started.

Part 1: Creating the Module

1. Upload the boilerplate

Before we begin with the module, please download the HubSpot CMS boilerplate theme and upload it to your HubSpot account. This will provide us with our theme file structure; the theme also includes other modules that can serve as examples for you.

The HubSpot CMS boilerplate is designed to work with both local development and the HubSpot Design Manager. To get started, you will need to have Node.js installed. We also strongly suggest that you set up a HubSpot CMS Developer Sandbox.

First, in your terminal, navigate to the directory you want to use for your theme.

Run npx @hubspot/create-cms-project <my-theme> to create the theme from the boilerplate. 

Create a "hubspot.config.yml" file in your new directory "my-theme". Then configure the CLI, so that you can upload files to the HubSpot portal you use.

Run hs watch --portal=<portal> src <my-theme> to upload all the files in the boilerplate and watch for changes to files in the "src" directory.

While the watch command is running, all your changes will be uploaded to your HubSpot account on file saves. Changes will immediately be live. You can leave this command running in the background, as you work.  

The <name> is the portal where you’ve stored the module. It should match either your portal ID number or the name attribute you assigned to your portal in the "hubspot.config.yml" file, when you configured your CLI. 

The <src> in this command is the path to your local file relative to your current working directory.

The <dest> is the path to a file in your HubSpot account and can be a new folder.

Lastly, Control-C to stop watching.

2. Create a Module

Navigate to the Design Manager in your HubSpot account where you uploaded the boilerplate theme. 

Then select the "modules" folder in your "my-theme" directory.

Navigate to "File > New file in 'modules'" at the top of the left-hand sidebar menu.

A modal will appear; in the modal, select "Module" under the "Components" heading.

Modal Example

At this point, we will be presented with some options that determine where the module can be used and where the data for the module will be stored. You can find more information in our documentation on configuring and building modules.

Under “Where would you like to use this module?”, select “Pages.” 

Under “Module content scope”, select “Local module.” 

Name the module “Testimonial.”

Select the "Create" button.

3. Add the fields.

Centered in the Design Manager, you’ll see the module editor with three panes, the first labeled “module.html (HTML + HubL)”, the second “module.css”, and the third “module.js”. We’ll come back to the module editor in Step 4.

Module Editor Example

We’ll be adding three fields to our module: a text field that will store the name of the customer giving the testimonial; an image field that will store the URL, alt attribute, and other important attributes for the customer’s profile picture; and a rich text field that will store the customer’s actual testimonial. You can find more information in our documentation on the best practices for creating and organizing fields.

In the sidebar menu, select “Add field” in the Fields menu item. From the Add field dropdown menu, choose "Text" in the "Content" column.

Label the text field "Customer Name." 

You should also see the HubL variable name change to “customer_name.” 

As the final step for this field, set the default value under “Default text” as “Sally”. 

Text Field Example

Select the breadcrumbs to return to your module’s main menu. 

To add the second field, again select “Add field”  in the Fields menu item. From the dropdown menu, choose “Image” in the “Selectors” column. 

Label the image field “Profile Picture”. 

You should also see the HubL variable name change to “profile_picture”; shorten this to “profile_pic.”  

Now you can set a default image for the field under “Default image”. You can use the profile picture for Sally provided in the "images" folder in the completed project files

As the final step for this field, set the alt attribute under “Alt text” as “Customer Profile Picture.” 

Image Field Example

For the final field, create a “Rich text” field and label it “Testimonial.” Make sure that its HubL variable name is also “testimonial.” 

For the default text, you can simply write: “I’ve had nothing but wonderful experiences with this company.” 

Rich Text Field Example

A note: At this point, you can select the "Preview" button adjacent to the "Publish Changes" button. A new window will open with the module preview page. The sidebar will list the module’s three fields and the information associated with each field. The center preview pane will display how your module will appear in a page or template. At this point, the center pane should be completely empty. 

The center pane is empty, because our fields simply store data. Fields store data; they do not display data. To display the fields’ values we will use a mixture of HTML and HubL in the module's HTML file.

Another note: Modules are completely customizable. Sometimes you may want to create  “super” modules with multiple fields and with many functions, and sometimes you might split that functionality into separate modules to provide an easier editing or development experience. When you have more than one field, it can be useful to think of module fields like an HTML form, where each field has a name and associated data.

4. Display the fields' data

To display the data for our fields in the HTML, we need to write some HubL to access the data. 

Let’s return to the Design Manager tab. In the module.html (HTML + HubL) pane of the module editor, write the following: 

HubL
//module.html

  {{module.customer_name}}
  <img src={{module.profile_pic.src}} alt={{module.profile_pic.alt}}>
  {{module.testimonial}}

Here, we access the data stored in our fields with dot notation. Not surprisingly, the "module" variable represents our module; "customer_name", for example, is the HubL variable name we assigned our text field in Step 3. 

Note that the image field only stores the URL and the alt attribute for the customer’s profile picture. We still need to create an img tag in our HubL and HTML to access this data and display the picture.  

Now you can select the "Preview" button again or go back to your preview tab. Now that we have written our HubL and HTML, the testimonial is displayed in the center window. Success!

5. Pull the module down to your local environment

So far, we’ve created and edited our module in the Design Manager, but you can complete all these modifications in your local development environment. You may find it easier to write and refactor HTML in a code editor, for example, and make use of your preferred packages and tools.  

Return to the Design Manager once again, and ensure that your module editor is open. Select the "Publish changes" button. 

Next to the "Preview" and "Publish changes" buttons, make sure to switch the "Make available for templates" toggle to make this module available to add to your templates. Note: You can switch this toggle off, if you need to make changes to the module or test its functionality.

Publish Changes Button Example

Now navigate to your terminal, and run the following command:

hs fetch --portal=<name> <src> [dest]

Here, the fetch command takes your module file from your HubSpot account and brings it into your local environment. 

The <name> is the portal where you’ve stored your module. The name should match either your portal ID number or the name attribute you assigned to your portal in the “hubspot.config.yml” file, when you configured your CLI. 

The <src> is your module’s full path in the HubSpot Design Tools. In the Design Manager, you can right click on your module in the finder (sidebar menu). A context menu will appear, and you can select “Copy path” to copy the full path to your clipboard.

The [dest] is the path to the local directory where you would like the module to be placed. If this is omitted, this argument will default to the current working directory. 

For the purposes of this tutorial, you should pull down the module to the “src/modules” folder in the “my-theme” directory you created in Step 1. You can find more information in our documentation about the fetch command.

6. Open the module folder in your local environment.

In your preferred code editor, navigate to the module folder you’ve just pulled down from your HubSpot account. Within your module folder, you will see five different files:

Use this table to describe parameters / fields
Parameter Description
fields.json

A JSON object that contains your module’s fields.

meta.json

A JSON object that contains meta information about your module.

module.css

The CSS file that styles your module.

module.html

The HTML and HubL for your module.

module.js

The JavaScript for your module.

You can find more detailed information in our documentation about the module file structure, especially concerning the "fields.json" and "meta.json" files. In this tutorial, we’ll focus on the "fields.json", "module.css", and "module.html" files and how they are generated by, downloaded from, and uploaded to the module editor in the Design Manager.

7. Go to your module’s "fields.json" file.

This file should contain a JSON object similar to the following (The id numbers and the src attribute of the image field will differ):

JSON
//fields.json

[
  {
    "label": "Customer Name",
    "name": "customer_name",
    "id": "2a025cd5-7357-007f-ae2f-25ace762588e",
    "type": "text",
    "required": true,
    "locked": false,
    "validation_regex": "",
    "allow_new_line": false,
    "show_emoji_picker": false,
    "default": "Sally"
  },
  {
    "label": "Profile Picture",
    "name": "profile_pic",
    "id": "7877fb84-eb8a-d2c7-d939-77e6e9557d8f",
    "type": "image",
    "required": false,
    "locked": false,
    "responsive": true,
    "resizable": true,
    "default": {
      "src": "https://cdn2.hubspotqa.net/hubfs/101140939/profile-pic-sally.svg",
      "alt": "Sally Profile Picture",
      "width": 100,
      "height": 100,
      "max_width": 100,
      "max_height": 100
    }
  },
  {
    "label": "Testimonial",
    "name": "testimonial",
    "id": "c5524ece-1ab5-f92d-a5de-e2bf53199dfa",
    "type": "richtext",
    "required": false,
    "locked": false,
    "default": "<p>I’ve had nothing but wonderful experiences with this company.</p>"
  }
]

The properties within each field may follow a different order. Here, we've listed the field's properties according to the sequence laid out in the HubSpot CMS boilerplate theme's style guide.

Note that the value of the “name” key for each field is the variable name we assigned to that particular field in Step 3.

Also note the key “label” and its value for each field. We labeled our fields the same (“Customer Name”, “Profile Picture”, and “Testimonial”) in Step 3. 

Finally, the value of each “default” key should match the default value you gave each field in Step 3. 

Let’s experiment. In your local environment, change the default value of your rich text field (labeled “Testimonial”) and add the sentence “I would 100% recommend it to my colleagues and friends.” Now save your file. We’ll return to this in Step 10.

8. Go to your module's "module.html" file.

 This file should contain the HubL and HTML that we wrote in the HubL + HTML module editor in Step 4.

Let’s make our HubL and HTML a bit more interesting. You can copy the following snippet directly into the "module.html" file to replace the existing code:

HubL
//module.html

<div class="testimonial">
  <h1 class="testimonial__header"> {{ module.customer_name }} </h1>
  <img class="testimonial__picture" src={{ module.profile_pic.src }} alt={{ module.profile_pic.alt }}>
  {{ module.testimonial }}
</div>

In writing our HTML, we've used the BEM class structure in accordance with the HubSpot CMS boilerplate theme's style guide.

9. Go to your module’s "module.css" file.

This file should be empty. 

Let’s make our module’s styling a bit more exciting. Copy the following code snippet into the file:

CSS
//module.css

.testimonial {
  text-align: center;
}

.testimonial__header {
  font-weight: bold;
}

.testimonial__picture {
  display: block;
  margin: auto;
}

Now save your file.

10. Push your local changes to your HubSpot account.

Now that we’ve made changes to our module in our local environment, we need to push them back to our HubSpot account. 

Navigate to your terminal, making sure you are in the correct directory, and run the watch command once again:  

hs watch --portal=<name> <src> <dest>

See Step 1 for more details on this command. While the watch command runs, all your changes will be uploaded to your HubSpot account on file saves. Leave this command running in the background, and your changes will immediately be live, as you work through Part 2 of this tutorial.

11. Preview your local changes in the Design Manager.

Now let’s return to the Design Manager. 

Make sure that you have selected the module you’ve just created in the “src/module” folder,  and the module editor is open with three panes to enter HTML + HubL, CSS, and JS. 

In the module.html (HubL + HTML) editor, you should see the changes we made in our local environment. In addition, in the module.css editor, you should also observe the changes in styling we made to our module’s h1 and img tags.

But just to make sure these changes have been uploaded correctly, you can select the "Preview" button. Again, a new window will open with the module preview page. In the center pane, you should see the module’s title and description displayed with the changes we made in both the Design Manager and our local environment.

Module Preview Example

A note: So far, we:

  1. created our module in the Design Manager,
  2. pulled that module down from our HubSpot account,
  3. made changes to the HubL + HTML and CSS using our local development tools, and
  4. uploaded our changes to our HubSpot account using the CLI watch command we ran in Step 10.

But this is only one of many methods available for creating a module. For example, you can also:

  1. create a module in the Design Manager,
  2. pull that module down from our HubSpot account, and
  3. run the CLI watch command we ran in Step 10.

With the watch command running, you can edit your module locally and see the changes immediately appear in your HubSpot account.  

Feel free to experiment with your workflow, as you create modules. As you become more comfortable with editing the module’s files in your local environment, you might find yourself working with the Design Manager less. With the CMS Developer Tools, you can completely customize your own experience.

Part 2: Using the Module in a Template

12. Open the “my-theme” directory.

Navigate to the “my-theme” directory you created in Step 1 when you downloaded the HubSpot CMS boilerplate theme. 

The “src” folder holds all the files you will need to create a website. The file structure should be as so (or very similar):

File Structure Example

For this part of our tutorial, we’ll be most concerned with the “modules” and “templates” folders. 

Not surprisingly, all of your modules, including your Testimonial module, should reside in the “modules” folder. Each module is contained in its own folder (See Step 6 for more detail about module file structure). 

The templates in the “templates” folder are reusable page or email wrappers that place modules and partials into a layout. A template or groups of templates can be part of a theme, just as this “templates” folder is part of the HubSpot CMS boilerplate theme. You can find more information on templates in our documentation.

13. Insert the Testimonial module into a template.

By their most basic definition, modules are editable areas of HubSpot templates and pages. We can insert modules into templates by using the Template Builder, but here we’ll be using HubL to add modules to a template in our local environment.   

In your code editor, open the “homepage.html” file under the “templates” folder.

Not surprisingly, the “homepage.html” file serves as a template for a website homepage; this makes it the perfect template to test out our Testimonial module. 

In the “homepage.html” file, go to the final Drag and Drop section. This section will contain three default rich text modules labeled “Feature one”, “Feature two”, and “Feature three.” We are going to replace each of these modules with an instance of our Testimonial module. 

Homepage Features Example

Delete the first rich text module labeled “Feature one” and replace it with this HubL module tag:

HubL
{% dnd_module path= “../modules/Testimonial.module” %}
{% end_dnd_module %}

When we add a HubL module tag to a Drag and Drop area in a template, the tag requires a path that defines the location of where the module is in the design manager. Optionally, we can also give the module other parameters to specify other module information. We’ll do this in Step 15. 

A note: Since we are adding the testimonial module to a Drag and Drop area, our module tag does not require a unique name. If we were adding the module to a simple HTML file, however, we would need to assign the module a unique name. We would also use slightly different syntax, like so:

HubL
{% module "testimonial_one" path="../modules/Testimonial.module"
%}

You can find more information in our documentation about using modules in templates.

14. Preview your changes to the template.

Now navigate to the Design Manager again to preview your changes. If you haven’t kept the watch command running to track your work automatically, run hs watch --portal=<name> <src> <dest> again in your terminal to upload your changes. Make sure that this command keeps running, as you complete the next steps. 

In the Design Manager, in the sidebar menu, select the “homepage.html” file under the “templates” folder in your “my-theme” directory. 

Once the template’s HubL + HTML appears in the center preview pane, select the "Preview" button and choose “Live preview with display options.” 

Live Preview Example

A new window will open with a preview window that will display the homepage generated by “homepage.html.” 

Scroll down to the bottom, and you will see that the first Feature module has been replaced by our default Testimonial module. Not surprisingly, it displays our default customer name (“Sally”), our default customer image, and our default testimonial ("I’ve had nothing but wonderful experiences with this company. I would 100% recommend it to my colleagues and friends.").

Default Module in Template Example
15. Customize the Testimonial module in the template.

Let’s make our homepage template a bit more interesting. 

Navigate back to your code editor, and open the “homepage.html” file once again. 

Add the following parameters to the testimonial module we’ve already added to the template:

HubL
{% dnd_module path='../modules/Testimonial.module',
  customer_name = "Mary",
  profile_pic = {
    src: "{{ get_asset_url('../images/profile-pic-mary.svg') }}",
    alt: "Mary Profile Picture"
  },
  testimonial = "Wow, what a product! I can't wait to recommend this to all my family and friends!"
%}
{% end_dnd_module %}

Here, we’ve passed parameters to the module to override the default values we originally assigned our three fields. Note that we use the HubL variable name we assigned to each field in Step 3 to assign that field a new value. 

We pass our text field (HubL variable name: “customer_name”) the string “Mary.” 

Notice that we pass our image field (HubL variable name: “profile_pic”) an object that contains two properties: the “src” property, where we use the HubL get_asset_url function to retrieve the URL for Mary’s profile picture; and the “alt” property, where we assign a new alt attribute to Mary’s profile picture.

You can use the profile picture for Mary provided in the "images" folder in the completed project files.

Finally, we pass our rich text field (HubL variable name: “testimonial”) the string "Wow, what a product! I can't wait to recommend this to all my family and friends!"

Alternatively for our rich text field, we can use HubL block syntax to write a large block of HTML or text:

HubL
{% dnd_module path='../modules/Testimonial.module',
  customer_name = "Mary",
  profile_pic = {
    src: "{{ get_asset_url('../images/profile-pic-mary.svg') }}",
    alt: "Mary Profile Picture"
  }
%}
  {% module_attribute "testimonial" %}
    Wow, what a product! I can't wait to recommend this to all my family and friends!
  {% end_module_attribute %}
{% end_dnd_module %}

You can find more information on HubL block syntax in our documentation about module block syntax.

If you’ve kept the watch command running in your terminal, you should be able to navigate back to the Design Manager to preview your changes to the template (See Step 14).

Mary Module in Template
16. Complete adding modules to the template.

Let’s finish editing our homepage template.

Once again, navigate back to your code editor, and open the “homepage.html” file. 

Again, go to the final Drag and Drop section that contains three default rich text modules labeled “Feature one”, “Feature two”, and “Feature three.”

We’ve already replaced the first module with an instance of our Testimonial module. Now we’re going to replace the other two.

Delete the second rich text module labeled “Feature two” and replace it with a testimonial module that meets the following specifications.

  1. The customer’s name is “Ollie”.
  2. Ollie's testimonial reads: “I can't believe that I ever conducted business without the use of this product!”
  3. Give Ollie's image the alt attribute “Ollie Profile Picture.” For the src attribute, you can use the profile picture for Ollie provided in the completed project files. 

Finally, delete the third rich text module labeled "Feature three" and replace it with a testimonial module that meets these guidelines:

  1. The customer’s name should be “Erin."
  2. Erin’s testimony should read, “My business has nearly tripled since I began to use this product! Don't wait, start now!”
  3. You can assign Erin's image the alt attribute “Erin Profile Picture.” For the src attribute, you can use Erin's profile picture provided in the completed project files.

If you’ve kept the watch command running in your terminal, you can navigate back to the Design Manager to preview your changes to the template (See Step 14). 

Scroll down to the bottom, and you will see that the three Feature modules have been replaced by our three testimonial modules.

Final Modules in Template Example

Voila! You’ve just added modules to a template and customized your developer experience in the HubSpot CMS. 

To recap what we’ve accomplished so far: First, we downloaded the CMS boilerplate theme to serve as the basis of our own custom theme (contained in the “my-theme” directory). We then built a custom module and added it to our theme’s homepage template. Our final step will be to use the homepage template to create a website page that we can edit and publish to create a live site.

Part 3: Using the Custom Template in a HubSpot Page

17. Designate the “my-theme” directory as a theme.

Before we can create a page with the homepage template we just modified, we need to make one final change in our local environment by modifying the  “theme.json” file. In the “theme.json” file, we will designate this directory as a theme that is accessible across different HubSpot products.  

In your code editor, open the “theme.json” file in the “src” folder. Copy the following JSON object into the file:

JSON
//theme.json

{
  "name": "my_custom_theme",
  "label": "My Custom Theme"
}

Make sure that you’ve saved these changes and pushed them to your HubSpot account using the watch command.

18. Create a page from the homepage template.

To create a page, navigate to your Content Dashboard. Select the "Create" button, and opt to create a “Website page.” 

A new window will open, where you’ll need to choose a theme. In the sidebar, you can choose from three categories of themes:  “Your templates”, your own custom themes; “HubSpot themes”, the default themes that HubSpot has created for your convenience; and “Marketplace themes”, website themes created by other HubSpot customers that are available to you. 

Make sure you’ve selected “Your templates.” Select your theme (“My Custom Theme”) when it appears in the center preview pane.

Website Themes Example

Once you’ve selected your theme, the five templates included in your theme will preview in the center pane. Select the “Homepage” template.

A modal will appear prompting you to designate an “Internal page name” for the page. Name it “Sample-Homepage.”

19. Edit and publish the page.

A new window will open with the Page Editor, where you can edit and publish your website page. 

Page Editor Example

In the sidebar, there are three tabs. 

In the “Add”’ tab, you can choose from different modules, including the modules included with your custom theme. You can then drag your selected module into the center pane to add it to the page. 

In the “Contents” tab, you can review a condensed list of the modules that make up your page. 

Finally, in the “Design” tab, you can review the theme that styles your page and edit your theme settings. 

The center pane displays an editable version of the webpage you’ve built from the homepage template. If you scroll down to the bottom of the preview, you can see the three testimonials we added to the “homepage.html” file in our local environment. 

Make some changes to customize the page; the Page Editor allows you to edit modules directly in the center pane. You can even override default values you provided in your template and in your modules themselves.

You can preview your changes at any time by selecting the “Preview” button. You can find more information in our documentation about creating and editing pages.

Before you can publish your new page, you’ll need to navigate to Settings and designate a page title and a URL. Under “Page title”, you can write “Sample Homepage.” Under “Page URL”, you will need to set a URL. 

Page Settings Example

Once you’ve completed these steps, you can select the "Publish" button. You've created a module within your theme, customized a template, and your homepage is now live!

If you'd like more information about modules, templates, themes, or the HubSpot CMS, the CMS Reference Docs might interest you. You might also enjoy the module or template reference docs.