If you’ve ever tried to ship a complex HubSpot module — a quiz, calculator, or configurator — you’ve probably asked the same question: why does everything start empty, even when defaults are defined? This article explains why that happens, what HubSpot actually allows, and which patterns work in production.
At first glance, HubSpot modules look declarative. You define structure and defaults in fields.json, and it feels natural to expect the module to arrive with meaningful demo content.
In theory, this would mean:
Unfortunately, this expectation does not match how HubSpot modules actually work.
The most important distinction to understand is this:
Defaults in fields.json are fallback values, not content initialization.
However, in practice, HubSpot’s editor does not apply defaults eagerly. Some default values — especially inside repeaters — may only appear after the editor re-normalizes data in response to user interaction. This behavior is undocumented and inconsistent, and should not be relied on.
They exist to:
They do not:
This difference is subtle, poorly documented, and responsible for most confusion.
Example: Default on a Simple Field
This may appear prefilled in some cases — but this behavior does not extend to repeaters.
Simple fields behave as expected. A text field with a default value will render correctly. Repeaters behave differently.
If a field group is marked as repeatable, HubSpot will never auto-create items for it — even if every child field has a default value.
The result is always the same:
This is intentional and consistent behavior.
Example: Repeatable Group With Defaults That Will Not Appear
Despite the default value, no question item will be created.
Most real-world modules are not flat. In quizzes and assessments, repeaters are often nested multiple levels deep.
For example:
HubSpot provides no supported mechanism to prefill this hierarchy:
Once this limitation is understood, many confusing behaviors suddenly make sense.
Example: Nested Repeatable Structure
No part of this structure will be auto-populated.
While working on a production quiz module with deeply nested repeaters (questions → answers → scoring rules), I attempted to prepare a full demo preset via the HubSpot CLI by defining complete default values in fields.json.
When the module was added to a page, the result looked broken:
At first glance, this looked like partial failure of defaults — or even a CLI bug.
However, something unexpected happened.
After adding or removing any repeater item in the editor UI, all previously broken fields suddenly normalized:
This behavior creates the illusion that repeaters can be fully prefilled via CLI — but that conclusion is misleading.
HubSpot does not eagerly apply defaults when a module is first added to a page. Instead, the editor performs partial initialization and defers full normalization until the user mutates repeater data.
When a repeater item is added or removed, the editor re-processes the entire structure:
This process is internal, undocumented, and not guaranteed to run on initial render.
The CLI did not “seed” content. It merely defined a schema that the editor later reconciled during user interaction.
No.
The Design Manager UI allows you to define module structure, but it does not provide any way to inject instance data when a module is added to a page.
Every module instance starts empty by design.
This is a common assumption and an understandable one.
The HubSpot CLI operates on module source files, not on page instances. Fetching or pushing a module only updates its definition.
It does not:
Example: CLI Commands That Do Not Seed Content
These commands sync schema — nothing more.
In some cases, deeply defined defaults may appear to populate after editor interaction. This is a side effect of internal editor normalization — not a supported content seeding mechanism.
This limitation is not a bug — it is a deliberate architectural decision.
HubSpot modules are designed to be:
Allowing modules to auto-seed complex data would introduce serious risks:
HubSpot chose content ownership over automation.
This design choice creates a real challenge for complex modules:
Without demo content, first-time UX suffers and support questions increase.
Relying on editor-side normalization for demo content is risky:
If demo content matters, it must be controlled at runtime — not inferred from editor side effects.
The most reliable approach is to resolve demo versus real data at the template level, before JavaScript execution.
Instead of trying to prefill or mutate iterable fields at runtime, the module decides which dataset to expose based on a clear condition.
This allows:
This is the approach used in the Persona Scoring Quiz module.
Example: Runtime Seeding Pattern
For complex modules, heuristic checks are often not enough. A more robust solution is to expose an explicit Demo Mode toggle.
This makes behavior deterministic and fully controlled by the editor:
Example: Demo Mode Toggle via HUBL
If someone claims otherwise, they are confusing schema with instance data.
If you are building advanced HubSpot modules:
fields.json as schema only;HubSpot modules are powerful — once their boundaries are understood.