HubSpot custom modules are the building blocks of professional HubSpot CMS websites. Understanding how to architect, build, and maintain custom modules effectively separates basic HubSpot implementations from truly flexible, scalable digital experiences. In 2026, with HubSpot’s continued platform investment in developer tooling and module capabilities, custom modules have become the standard deliverable for any serious HubSpot website project — moving far beyond what marketplace themes and default drag-and-drop sections can provide.

What Are HubSpot Custom Modules?

A HubSpot custom module is a self-contained, reusable content component that content editors can add to any page in the HubSpot CMS. Each module has its own:

  • HTML template (module.html) — the HubL markup that renders the module’s output
  • CSS (module.css) — scoped styles that only load when the module is present on a page
  • JavaScript (module.js) — front-end scripts, also loaded conditionally
  • Fields (fields.json) — the content fields that editors configure in the page editor sidebar
  • Metadata (meta.json) — module type, label, description, and icon configuration

This separation of concerns is what makes custom modules powerful: developers control the code, marketers control the content — and the two can work independently without blocking each other.

Module Field Types: A Complete Reference

HubSpot provides a rich set of field types for module configuration. Understanding them is essential for building modules that editors actually enjoy using:

Content Fields

  • text — single-line text input. Use for headlines, labels, short strings.
  • richtext — WYSIWYG editor. Use for body copy, descriptions, formatted content.
  • image — image picker with src, alt, width, height. Always use this for images.
  • video — video field supporting YouTube, Vimeo, or file upload.
  • cta — HubSpot CTA picker, links to the CTA tool for tracking and A/B testing.
  • form — HubSpot form picker. Essential for lead capture modules.
  • blog — references a HubSpot blog for dynamic post listing modules.

Layout and Structural Fields

  • choice — dropdown or radio for selecting layout variants (e.g., “left” | “right” | “center”)
  • boolean — toggle for show/hide controls (e.g., “Show background overlay”)
  • color — color picker for when editors need theming control
  • number — numeric input for values like column count or item limit
  • group — a nested group of fields, used for complex data structures
  • repeater — an array of grouped fields, essential for lists, accordions, and card grids

Designing Modules for Content Editors

The best custom modules are invisible in the best sense — editors can use them intuitively without referring to documentation. Achieving this requires thinking about module UX alongside module code.

Use Clear Labels and Help Text

Every field should have a human-readable label and, where needed, help text that explains what it affects. “Hero Image (recommended size: 1920x1080px, JPG or WebP)” is infinitely better than “Image.”

Set Meaningful Defaults

Default values prevent broken-looking modules when editors first add them. For text fields, use placeholder copy that demonstrates the ideal length and tone. For images, use a representative placeholder that shows the expected aspect ratio.

Use Choice Fields for Layout Variants

Instead of building three separate modules (hero-left, hero-center, hero-right), build one with a layout choice field. This reduces module library sprawl and makes maintenance much simpler. The choice field value becomes a CSS class or a HubL conditional:

{% if module.layout == 'split' %}
...
...
{% else %}
...
{% endif %}

Building a Card Grid Module: End-to-End Example

A card grid is one of the most common module types. Here’s a complete implementation approach.

fields.json

[
  {
    "name": "section_title",
    "label": "Section Title",
    "type": "text",
    "default": "Our Services"
  },
  {
    "name": "columns",
    "label": "Columns per Row",
    "type": "choice",
    "choices": [["2", "2 Columns"], ["3", "3 Columns"], ["4", "4 Columns"]],
    "default": "3"
  },
  {
    "name": "cards",
    "label": "Cards",
    "type": "group",
    "occurrence": { "min": 1, "max": 12, "default": 3 },
    "children": [
      { "name": "icon", "label": "Icon", "type": "image" },
      { "name": "title", "label": "Card Title", "type": "text" },
      { "name": "description", "label": "Description", "type": "richtext" },
      { "name": "link", "label": "Link", "type": "link" }
    ]
  }
]

module.html

{% if module.section_title %}

{{ module.section_title }}

{% endif %}
{% for card in module.cards %}
{% if card.icon.src %} {{ card.icon.alt }} {% endif %}

{{ card.title }}

{{ card.description }}
{% if card.link.url %} {{ card.link.text }} {% endif %}
{% endfor %}

Module Performance Best Practices

HubSpot’s module system supports conditional asset loading natively. Use it:

  • Place CSS in module.css — it only loads on pages that use the module
  • Place JavaScript in module.js — same conditional loading applies
  • Use require_css() and require_js() in module.html for shared utility files
  • Lazy-load images below the fold using loading="lazy"
  • Use HubSpot’s image resize API for responsive images: {{ module.image.src }}?width=800

Testing Custom Modules

Always test custom modules against these criteria before delivery:

  • Empty state — what does the module look like with no content? Add conditional checks for all optional fields.
  • Long content — test with extremely long titles, descriptions, and lists to ensure the layout holds.
  • Missing images — always check for image.src before rendering an <img> tag.
  • Mobile responsiveness — test at 375px, 768px, 1024px, and 1440px viewports.
  • Accessibility — verify heading hierarchy, image alt text, and keyboard navigation.

Well-built HubSpot custom modules transform what content teams can achieve independently. When marketers can confidently build, modify, and publish pages without waiting on developer resources, marketing velocity increases substantially. For development teams building HubSpot websites, investing time in module UX — not just module code — is what separates projects that empower clients from projects that create dependency. A thoughtfully built custom module library is one of the highest-value deliverables in any HubSpot website engagement.