
When explaining service procedures or user onboarding flows on a website, simple bullet points often fail to capture the user's attention. To solve this, we can utilize a custom "Step Flow" module in HubSpot.
This article introduces a design module that visualizes processes using icons, numbers, and arrows. It is fully responsive: displaying a vertical flow on mobile devices and an optimized card layout on desktops.


The primary goal of this module is to visualize the "Next Action" for the user.
By breaking down complex processes into digestible "Steps" and adding visual cues like icons and flow arrows, you can significantly reduce user friction and improve conversion rates (CVR). Furthermore, by utilizing HubSpot's repeating groups and style fields, marketing teams can easily add steps or change brand colors without touching a single line of code.
This design is versatile and can be applied to various business scenarios:
Once implemented, this module provides a user-friendly experience in the Page Editor.
1. Style Settings (Global Design)You can customize the look and feel to match your brand directly from the module options:
2. Managing Steps (Content)The "Steps" section uses a Repeater Group, allowing you to add as many steps as needed.
To implement this, create a new module in the HubSpot Design Manager and paste the code below into the respective files.
This defines the module interface. It includes the style_settings group for design control and a steps group for the repeating content.
[
{
"allow_new_line": false,
"display_width": null,
"id": "acf72606-d674-5f90-274d-f9c9c98e6b77",
"label": "main_title",
"locked": false,
"name": "main_title",
"required": false,
"type": "text"
},
{
"children": [
{
"default": {
"color": null,
"opacity": null
},
"display_width": null,
"id": "3f2e92b0-dd50-01d2-4a95-8fb5702cc954",
"label": "text_color",
"locked": false,
"name": "text_color",
"required": false,
"type": "color"
},
{
"default": {
"color": null,
"opacity": null
},
"display_width": null,
"id": "e2ed5fe3-b347-78ce-c90d-2742e74c580d",
"label": "border_color",
"locked": false,
"name": "border_color",
"required": false,
"type": "color"
},
{
"display": "text",
"display_width": null,
"id": "ad9d333e-9eed-5663-82c8-5ad75cedb5cf",
"label": "border_width",
"locked": false,
"name": "border_width",
"required": false,
"step": 1,
"type": "number"
},
{
"display": "text",
"display_width": null,
"id": "1bafc3e9-47f2-b52b-004b-a4ae36be0c0b",
"label": "base_font_size",
"locked": false,
"name": "base_font_size",
"required": false,
"step": 1,
"type": "number"
}
],
"default": {
"text_color": {
"color": null,
"opacity": null
},
"border_color": {
"color": null,
"opacity": null
}
},
"display_width": null,
"expanded": false,
"group_occurrence_meta": null,
"id": "8ed3eabc-3007-ad43-8ae9-b5ed3c076cc0",
"label": "style_settings",
"locked": false,
"name": "style_settings",
"required": false,
"tab": "CONTENT",
"type": "group"
},
{
"children": [
{
"allow_new_line": false,
"display_width": null,
"id": "61df6f80-bb75-828e-ace3-d996467e4528",
"label": "step_label",
"locked": false,
"name": "step_label",
"required": false,
"type": "text"
},
{
"allow_new_line": false,
"display_width": null,
"id": "75918939-9e65-2c0d-8a9f-eca248270ae4",
"label": "step_number",
"locked": false,
"name": "step_number",
"required": false,
"type": "text"
},
{
"default": {},
"display_width": null,
"icon_set": "fontawesome-5.14.0",
"id": "f1c6fdf9-a639-f2cb-adcb-bc47aec3ca2a",
"label": "step_icon",
"locked": false,
"name": "step_icon",
"required": false,
"type": "icon"
},
{
"allow_new_line": false,
"display_width": null,
"id": "e263b998-b922-2d87-a978-fac5256b8572",
"label": "step_title",
"locked": false,
"name": "step_title",
"required": false,
"type": "text"
},
{
"display_width": null,
"id": "a085be67-2afd-839b-a162-9af69150c0f3",
"label": "step_description",
"locked": false,
"name": "step_description",
"required": false,
"type": "richtext"
}
],
"default": [],
"display_width": null,
"expanded": false,
"group_occurrence_meta": null,
"id": "a1f6d8a3-0a35-c9fa-2a9a-079247675a8c",
"label": "steps",
"locked": false,
"name": "steps",
"occurrence": {},
"required": false,
"tab": "CONTENT",
"type": "group"
}
]{# CSS Variable Definition #}
{% require_css %}
<style>
.flow-module-{{ name }} {
--text-color: {{ module.style_settings.text_color.css }};
--border-color: {{ module.style_settings.border_color.css }};
--border-width: {{ module.style_settings.border_width }}px;
--font-size: {{ module.style_settings.base_font_size }}px;
}
</style>
{% end_require_css %}
<div class="flow-wrapper flow-module-{{ name }}">
<div class="flow-container">
{# Main Title #}
{% if module.main_title %}
<h2 class="flow-main-title">{{ module.main_title }}</h2>
{% endif %}
<div class="flow-steps-group">
{# Loop through steps #}
{% for item in module.steps %}
{# Step Card Body #}
<div class="flow-card">
{# Left Side: Step Number & Icon #}
<div class="flow-card-left">
<div class="flow-step-info">
<span class="step-label">{{ item.step_label }}</span>
<span class="step-number">{{ item.step_number }}</span>
</div>
{# Icon Wrapper #}
<div class="step-icon-wrapper">
{% icon
name="{{ item.step_icon.name }}",
style="{{ item.step_icon.type }}",
unicode="{{ item.step_icon.unicode }}",
icon_set="{{ item.step_icon.icon_set }}"
%}
</div>
</div>
{# Right Side: Text Content #}
<div class="flow-card-right">
<h3 class="flow-step-title">{{ item.step_title }}</h3>
<div class="flow-step-desc">
{{ item.step_description }}
</div>
</div>
</div>
{# Arrow (Shows unless it is the last item) #}
{% unless loop.last %}
<div class="flow-arrow">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 5V19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M19 12L12 19L5 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
{% endunless %}
{% endfor %}
</div>
</div>
</div>
/* Main Wrapper */
.flow-wrapper {
width: 100%;
padding: 4rem 1rem;
display: flex;
justify-content: center;
color: var(--text-color, #333);
font-size: var(--font-size, 16px);
}
.flow-container {
width: 100%;
max-width: 1040px;
display: flex;
flex-direction: column;
gap: 2.5rem;
}
/* Main Title */
.flow-main-title {
font-size: 1.875rem;
font-weight: bold;
text-align: center;
margin-bottom: 1rem;
}
/* Steps Group Container */
.flow-steps-group {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
gap: 1.5rem;
}
/* Individual Step Card */
.flow-card {
width: 100%;
display: flex;
flex-direction: column;
gap: 2rem;
padding: 2rem 1.5rem;
border-radius: 8px;
box-shadow: 2px 4px 14px rgba(0, 0, 0, 0.1);
border: var(--border-width, 1px) solid var(--border-color, #e5e7eb);
background-color: #fff;
}
@media (min-width: 768px) {
.flow-card {
flex-direction: row;
align-items: center;
}
}
/* Left Side (Number + Icon) */
.flow-card-left {
display: flex;
gap: 1rem;
align-items: center;
justify-content: center;
min-width: 120px;
}
@media (min-width: 768px) {
.flow-card-left {
gap: 0.5rem;
}
}
/* Step Label and Number Container */
.flow-step-info {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.step-label {
font-size: 0.875rem;
font-weight: bold;
}
.step-number {
font-size: 1.5rem;
font-weight: bold;
line-height: 1.2;
}
/* Icon Wrapper and SVG Sizing Fix */
.step-icon-wrapper {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
}
/* Force SVG to respect container size */
.step-icon-wrapper svg {
width: 100% !important;
height: 100% !important;
object-fit: contain;
fill: currentColor; /* Inherit text color */
}
/* Right Side (Title + Description) */
.flow-card-right {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.flow-step-title {
font-size: 1.125rem;
font-weight: bold;
margin: 0;
}
.flow-step-desc {
font-size: 0.875rem;
line-height: 1.5;
}
/* Arrow between steps */
.flow-arrow {
width: 32px;
color: #9ca3af;
display: flex;
justify-content: center;
}There is no specific limit. Since this module uses HubSpot's "repeater" (repeating field) feature, you can freely add or remove as many steps as needed using the "Add" button in the page editor. Additionally, you can intuitively reorder each step via drag-and-drop, allowing you to easily adjust the flow or update the process steps at any time.
No, coding is not required. The module includes a "Style Settings" section where you can define the text color, border color, border width, and base font size all at once. Even without HTML or CSS knowledge, you can adjust the design to match your website's look and feel simply by using the color pickers and numeric inputs.
This module is fully responsive. While it displays an optimized layout for larger screens like PCs and tablets, it automatically switches to a "vertical" stacked layout on smaller screens like smartphones. This design ensures that text and icons do not become too small on narrow screens, allowing users to read through the steps clearly and without stress.
We can customize this sample to match your specific business requirements.
Book Free ConsultationPut it on Trello!Need a fix for HubSpot, CMS, or GAS? Post it on Trello.
Development Requests Here