HUBSPOT / DESIGN SYSTEM
A design system for HubSpot: 21 modules, 30 templates, five web properties
21 custom HubSpot modules and 30 templates, running email and web for an entire brand portfolio. One system, not five.

The problem
Our group runs four brands plus a partner programme, five web properties in all, on one HubSpot instance. The default way to serve that is brute force: build every email and page from scratch, per brand, forever. It is slow, it drifts, and it breaks quietly. Two brands end up with three button styles. A template gets cloned, edited, cloned again, and nobody knows which copy is the real one. Production becomes a queue, and the queue becomes the marketing bottleneck.
Agencies will happily bill you per template for this. That is the problem, not the solution.
What I built
I applied design-system thinking to CRM content. Instead of templates as one-off artefacts, I built 21 custom HubSpot modules as reusable components: each one carries the brand styling logic internally, exposes safe editing controls to the team, and works across every brand in the portfolio. The 30 templates are assembled from those modules, the way a component library assembles an interface.
The architecture in plain terms: brand identity lives in the system, not in each individual email. Editors choose content; the modules enforce the standards. When something needs to change, it changes once, in the module, and every template that uses it follows.
The outcome
The multi-brand email cadence runs on this system today. Building a new campaign email became an assembly job rather than a development job, which means the team can ship without waiting on a developer, and what they ship is on-brand by construction rather than by review. Consistency stopped depending on vigilance. The system holds the standard so people don't have to.
It also changed what one marketing team could credibly take on: five web properties, one source of truth, no agency invoice per template.
The stack
- HubSpot CMS and Marketing Hub
- HubL with JSON module fields
- Theme settings carrying per-brand tokens
- CSS and JavaScript inside the modules
- Drag-and-drop email and page templates assembled from the module library
HUBSPOT MODULE SYSTEM / HUBL / BRAND-AWARE CTA MODULE, ILLUSTRATIVE EXCERPT
{# The module carries the brand logic. The editor never touches it. #}
{% set brand = module.brand_select || 'teos' %}
{% set tokens = theme.brands[brand] %}
<a class="cta cta--{{ brand }}"
href="{{ module.cta_url.href }}"
style="background: {{ tokens.primary }}; color: {{ tokens.on_primary }};">
{{ module.cta_label }}
</a>Where next
Next build
MagicINFO end of sale: a migration strategy that didn't panic anyone
How I approached an end-of-sale moment as a trust problem first and a campaign second, with a three-path framework instead of one forced route.
Another build
AI agent systems, built standards-first
Marketing standards captured in writing first, AI agents built on those documents second, and a named human signing off. The method that keeps quality from drifting.