Building a custom HubSpot CMS theme from scratch gives you precise control over design, performance, and the content editing experience. Unlike WordPress, HubSpot’s theming system is built around HubL (HubSpot Markup Language), a Jinja2-inspired templating language that integrates natively with HubSpot’s CRM, modules, and Smart Content engine. In 2026, with HubSpot’s continued investment in its CMS platform, custom HubSpot theme development remains one of the most powerful ways to build a high-converting, fully integrated business website.

Understanding the HubSpot CMS Architecture

Before writing your first line of HubL, it’s essential to understand how the HubSpot CMS structures a theme. A HubSpot theme consists of:

  • Templates — HTML+HubL files that define page layouts. Each template corresponds to a content type (page, blog post, blog listing, email, etc.)
  • Modules — reusable, self-contained content components with their own HTML, CSS, JavaScript, and fields (the equivalent of Gutenberg blocks or HubSpot’s drag-and-drop sections)
  • Macros — reusable HubL code snippets, similar to partials or includes
  • CSS/JS files — stylesheets and scripts managed through HubSpot’s design tools
  • theme.json — theme metadata and settings configuration
  • Fields.json — defines theme-level design settings editable in the CMS

Setting Up Your HubSpot Development Environment

HubSpot’s CLI (hs-cli) is the foundation of a modern local development workflow. Here’s how to get set up:

# Install HubSpot CLI globally
npm install -g @hubspot/cli

# Authenticate with your portal
hs auth

# Create a new theme from the default boilerplate
hs create website-theme my-custom-theme

# Start local development with file watching and auto-upload
hs watch --src my-custom-theme --dest my-custom-theme

The hs watch command monitors your local files and automatically uploads changes to your HubSpot sandbox portal. You edit locally, preview in the browser in near real time — no manual upload step required.

Theme File Structure

A well-organized HubSpot theme follows a predictable structure:

my-custom-theme/
├── theme.json
├── fields.json
├── templates/
│   ├── home.html
│   ├── about.html
│   ├── blog-post.html
│   ├── blog-listing.html
│   └── 404.html
├── modules/
│   ├── hero-banner/
│   │   ├── meta.json
│   │   ├── module.html
│   │   ├── module.css
│   │   ├── module.js
│   │   └── fields.json
│   └── cta-section/
├── macros/
│   ├── navigation.html
│   └── footer.html
├── css/
│   ├── main.css
│   └── variables.css
└── js/
    └── main.js

Writing HubL Templates

HubL is a superset of the Jinja2 templating language. A basic page template looks like this:




  {{ standard_header_includes }}
  {{ content.html_title }}
  


  {% include "my-custom-theme/macros/navigation.html" %}

  
{% if is_editable %} {{ widget_block "dnd_area", label="Main Content" }} {% endif %}
{% include "my-custom-theme/macros/footer.html" %} {{ standard_footer_includes }}

The {{ standard_header_includes }} and {{ standard_footer_includes }} HubL tags are critical — they inject HubSpot’s required scripts, tracking code, and module assets. Never omit them.

Building Custom Modules

Modules are the heart of HubSpot theme development. A well-designed module separates concerns cleanly: the fields.json defines what content editors can customize, while module.html controls the output.

Here’s a simple hero module’s fields.json:

[
  {
    "name": "headline",
    "label": "Headline",
    "type": "text",
    "default": "Welcome to our site"
  },
  {
    "name": "subheadline",
    "label": "Subheadline",
    "type": "richtext",
    "default": ""
  },
  {
    "name": "background_image",
    "label": "Background Image",
    "type": "image",
    "default": {}
  },
  {
    "name": "cta_button",
    "label": "CTA Button",
    "type": "cta"
  }
]

And the corresponding module.html:

{{ module.headline }}

{{ module.subheadline }}
{% if module.cta_button %} {{ cta(module.cta_button) }} {% endif %}

Theme-Level Design Settings with fields.json

The top-level fields.json of your theme defines design tokens that content editors can customize through the theme editor. This is how you expose color palettes, font choices, and spacing values without exposing the code itself.

Best practice is to define CSS custom properties in your stylesheet that reference these theme field values via HubL, creating a single source of truth for your design system.

Performance Optimization in HubSpot Themes

HubSpot handles CDN delivery and caching automatically, but there are still meaningful performance decisions in theme development:

  • Load module CSS and JS conditionally — use the require_css and require_js HubL tags inside modules so styles and scripts only load on pages that use the module
  • Optimize image fields — use HubSpot’s image sizing parameters (?width=800) to serve appropriately sized images
  • Use lazy loading for images below the fold with the loading="lazy" attribute
  • Minimize global JavaScript — keep module scripts modular and scoped

Testing and Quality Assurance

HubSpot provides a sandbox (Developer Test Account) for testing theme changes without affecting a live portal. Use the HubSpot Design Manager’s preview mode to test templates across multiple pages and content types before pushing to production.

For automated testing, the HubSpot CLI supports a staging-to-production workflow where you can maintain separate portals for development, staging, and production with controlled theme deployments.

When Custom Themes Make Business Sense

Marketplace themes are a reasonable starting point, but businesses with distinct branding, complex content requirements, or specific performance targets often outgrow them quickly. A custom HubSpot CMS theme gives you full control over the HTML structure, design system, and content editing experience — with zero unnecessary code.

The investment in a properly built custom theme pays off in faster page loads, a better editor experience for your marketing team, and a design that precisely matches your brand standards. For teams planning a HubSpot website build or migration, the architecture decisions made during theme development have a direct impact on both performance and long-term maintenance cost.