Skip to main content
Once you’ve built your multi-step form layout, you can export it as a HubSpot CMS module ready for deployment. This guide covers the complete export workflow.

Overview

The export process generates five files packaged in a ZIP archive:
  • fields.json - Module field definitions and your layout configuration
  • module.html - HubL template with multi-step form markup
  • module.css - Styles for the form interface
  • module.js - JavaScript for step navigation and validation
  • meta.json - Module metadata for HubSpot
These files together create a fully functional HubSpot module.

Generated Module Files

Let’s examine what each file contains:

fields.json

This is the most important file - it contains your custom layout encoded as HubSpot module fields. Structure:
[
  {
    "id": "sr_module_id",
    "name": "sr_module_id",
    "label": "Module ID",
    "type": "text"
  },
  {
    "id": "steps_group",
    "name": "steps",
    "label": "Steps",
    "type": "group",
    "occurrence": { "min": 1, "max": null, "default": 3 },
    "children": [
      {
        "id": "tab_label",
        "name": "tab_label",
        "label": "Label",
        "type": "text",
        "default": "STEP 1"
      },
      {
        "id": "field_group",
        "name": "field_group",
        "label": "Field Group",
        "type": "group",
        "occurrence": { "min": null, "max": null },
        "children": [
          {
            "id": "field",
            "name": "field",
            "label": "Field",
            "type": "group",
            "occurrence": { "min": 1, "max": 3 }
          }
        ]
      }
    ],
    "default": [
      {
        "tab_label": "STEP 1",
        "tab_name": "Personal Information",
        "field_group": [
          {
            "field": [
              {
                "field_type": "text",
                "field_label": "First Name",
                "form_property": "firstname",
                "required": true
              },
              {
                "field_type": "text",
                "field_label": "Last Name",
                "form_property": "lastname",
                "required": true
              }
            ]
          },
          {
            "field": [
              {
                "field_type": "email",
                "field_label": "Email",
                "form_property": "email",
                "required": true
              }
            ]
          }
        ],
        "buttons": {
          "previous": "Back",
          "next": "Continue"
        }
      }
    ]
  }
]
Key points:
  • Default values: Your exact layout is encoded in the default property
  • Field mapping: Each field maps to a HubSpot form property via form_property
  • Field types: Automatically converted from HubSpot types (text, email, phone_number, etc.)
  • Row structure: field_group represents rows, each containing 1-3 fields
Generated by fieldsJsonGenerator.ts:39-372.

module.html

The HubL template that renders your multi-step form. Key features:
  • Loops through module.steps to render each step
  • Generates progress indicator
  • Renders fields in rows based on field_group structure
  • Includes hidden HubSpot form for submission
  • Step navigation buttons
Example snippet:
{% for step in module.steps %}
  <div class="sr-step" data-step="{{ loop.index }}">
    <div class="sr-step-header">
      <h3>{{ step.tab_name }}</h3>
    </div>
    
    {% for group in step.field_group %}
      <div class="sr-field-row">
        {% for field in group.field %}
          <!-- Render field based on field.field_type -->
        {% endfor %}
      </div>
    {% endfor %}
  </div>
{% endfor %}
Generated by moduleHtmlGenerator.ts.

module.css

Styles for the multi-step form UI. Includes:
  • Progress bar styles
  • Step container layout
  • Field row responsive grid (1-3 columns)
  • Button styles
  • Validation error states
  • Mobile responsive breakpoints
Generated by moduleCssGenerator.ts.

module.js

JavaScript for form functionality. Features:
  • Step navigation (next/previous)
  • Progress bar updates
  • Field validation before advancing steps
  • Form submission to HubSpot Forms API
  • Error handling and display
Generated by moduleJsGenerator.ts.

meta.json

HubSpot module metadata. Structure:
{
  "label": "Contact Form",
  "icon": "form",
  "module_id": "unique-uuid",
  "host_template_types": ["PAGE", "BLOG_POST", "BLOG_LISTING"],
  "is_available_for_new_content": true
}
Key fields:
  • label: Your HubSpot form name
  • module_id: Unique identifier (generated via crypto.randomUUID())
  • host_template_types: Where module can be used
Generated by exportModule.ts:18-37.

Export Workflow

Follow these steps to export your module:
1

Complete Your Layout

Ensure your form layout is finalized:
  • All required fields are in the layout
  • Steps are properly named
  • Fields are organized into logical rows
  • Layout has been previewed and tested
2

Click Generate Module

In the canvas header, click the “Generar Módulo” button.The button shows a loading spinner while generating.Behind the scenes:
// App.tsx:47-60
const handleGenerateModule = async () => {
  setIsGenerating(true);
  const blob = await generateModule(schema, layout);
  setGeneratedModule(blob);
  setIsGenerating(false);
}
3

Wait for Generation

The system:
  • Converts your layout to fields.json format
  • Generates HTML, CSS, and JS files
  • Creates meta.json with unique module ID
  • Packages everything into a ZIP using JSZip
Note: Generation is fast (less than 1 second for most forms).
4

Download the Module

Once generation completes, the button changes to “Descargar Módulo” with a green color.Click it to download the ZIP file.File name format: {sanitized-form-name}.zipExample: contact-form.zip
The generated module is stored in browser memory. If you make changes to your layout, you’ll need to regenerate to get an updated module (App.tsx:86-88).

Uploading to HubSpot Design Manager

After downloading your module ZIP, upload it to HubSpot:
1

Navigate to Design Manager

In your HubSpot portal:
  • Click MarketingFiles and TemplatesDesign Tools
  • Or go directly to https://app.hubspot.com/design-manager/{your-portal-id}
2

Navigate to Modules Folder

In the file tree on the left:
  • Expand your design folder (e.g., @hubspot/design-folder)
  • Find or create a modules folder
  • Click on it to select
3

Upload the ZIP

Click the Upload button in the top right.Select your downloaded .zip file.Or drag and drop the ZIP into the Design Manager.
4

Wait for Extraction

HubSpot automatically:
  • Extracts the ZIP contents
  • Creates a .module folder
  • Registers the module
You’ll see {form-name}.module appear in your modules folder.
5

Verify Files

Click on the .module folder to expand it.Confirm all 5 files are present:
  • fields.json
  • module.html
  • module.css
  • module.js
  • meta.json
You must have Design Manager permissions in your HubSpot portal to upload modules. Contact your portal admin if you don’t see the Design Tools option.

Using the Module in HubSpot

Once uploaded, you can add your module to pages:
1

Edit a Page

Go to MarketingWebsiteWebsite Pages.Select an existing page or create a new one.Click Edit to open the page editor.
2

Add Module to Page

In the left sidebar, click Add (+).Search for your module by name (e.g., “Contact Form”).Drag it onto the page canvas.
3

Configure Module

The module editor opens on the right.You should see:
  • Steps section with your layout (tab labels, field groups)
  • HubSpot Form selector to choose which form to connect
  • Module ID and Class fields for customization
Your default layout is already configured!
4

Select HubSpot Form

In the HubSpot Form field:
  • Click the dropdown
  • Select the same form you used in the Form Builder
  • This connects the module fields to actual HubSpot form properties
5

Customize (Optional)

You can override the defaults:
  • Edit step names
  • Reorder fields
  • Add/remove field groups
  • Customize button text
Warning: Manual changes won’t persist if you re-upload the module.
6

Publish Page

Click Publish or Update to make the form live.Visit the page to see your multi-step form in action!

Testing the Module in HubSpot

After publishing, thoroughly test your form:

Functionality Testing

  1. Fill out fields in step 1
  2. Click Continue button
  3. Verify step 2 appears
  4. Click Back button
  5. Verify step 1 reappears with data intact
  6. Complete all steps
  7. Click Submit on final step
  1. Leave a required field empty
  2. Try to advance to next step
  3. Verify error message appears
  4. Fill the field
  5. Verify you can now advance
  6. Test email field with invalid email
  7. Test phone field with invalid format
  1. Fill out all required fields
  2. Submit the form
  3. Verify success message appears
  4. Check HubSpot Contacts to confirm submission was recorded
  5. Verify all field values are correct in contact record
  1. Open page on desktop (1920px)
  2. Verify 2-3 field rows display side-by-side
  3. Resize to tablet (768px)
  4. Verify fields stack appropriately
  5. Open on mobile (375px)
  6. Verify single-column layout
  7. Test form submission on mobile

Browser Testing

Test in multiple browsers:
  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)
  • Mobile Safari (iOS)
  • Chrome Mobile (Android)

Troubleshooting Export Issues

Cause: Missing schema or layout.Solution:
  • Ensure a form is selected
  • Check browser console (F12) for errors
  • Verify schema and layout are not null (App.tsx:48)
Cause: Module generation failed.Solution:
  • Check console for error messages
  • Verify JSZip is installed (package.json)
  • Try regenerating the module
Cause: Browser download manager issue.Solution:
  • Try a different browser
  • Check available disk space
  • Disable browser extensions that might interfere with downloads
Cause: Field was in palette (not in layout) when generated.Solution:
  • Ensure all fields you want are in the canvas
  • Fields in “Campos detectados” palette are NOT included in export
  • Drag fields from palette to canvas before exporting
Possible causes:
  • Invalid JSON in fields.json or meta.json
  • Missing required files
  • Incorrect folder structure
Solution:
  • Extract ZIP locally to verify contents
  • Validate JSON files at jsonlint.com
  • Ensure folder name ends with .module
  • Re-generate and re-download the module
Cause: Module may be flagged as unavailable.Solution:
  • Check meta.json has "is_available_for_new_content": true
  • Verify host_template_types includes "PAGE"
  • Clear HubSpot cache (Settings → Advanced)
Possible causes:
  • HubSpot form not selected in module settings
  • Field form_property names don’t match HubSpot form fields
  • JavaScript errors in module.js
Solution:
  • In page editor, select the HubSpot form in module settings
  • Verify field property names match exactly (case-sensitive)
  • Check browser console for JS errors

Module Regeneration

If you need to update your module after making layout changes:
1

Make Your Changes

Modify the layout in the Form Builder:
  • Reorder fields
  • Add/remove steps
  • Rename steps
  • Reorganize rows
2

Regenerate

Click “Generar Módulo” again.A new ZIP is created with updated layout.
3

Download New ZIP

Click “Descargar Módulo” to get the updated file.
4

Re-upload to HubSpot

Upload the new ZIP to Design Manager.This will overwrite the existing module.
5

Pages Update Automatically

All pages using the module will see the new default layout.Warning: Manual customizations in the page editor will be lost.
Re-uploading a module with the same module_id will update all instances. If you want to keep the old version, change the form name in HubSpot before exporting to generate a new module ID.

Best Practices

Version your modules: Include version numbers in form names (e.g., “Contact Form v2”) to track iterations.
Test before deploying: Always test exported modules on a test page before using on production pages.
Backup your layout: Take screenshots or notes about your layout before regenerating, in case you need to recreate it.
Keep field names stable: Don’t rename HubSpot form field properties after exporting, or submissions won’t map correctly.
Export frequently: Generate and download modules at multiple stages of development as backups.

Advanced: Manual Module Editing

After uploading to HubSpot, you can manually edit module files:

Editing module.css

  1. Navigate to the module in Design Manager
  2. Click module.css
  3. Add custom styles:
    .sr-step-header h3 {
      color: #ff6b35;
      font-size: 24px;
    }
    
  4. Click Publish changes

Editing module.html

  1. Click module.html
  2. Modify the HubL template
  3. Test in preview mode
  4. Publish changes
Manual edits will be lost if you re-upload the module from the Form Builder. Consider this when deciding between editing in HubSpot vs. regenerating.

Next Steps

Deployment

Learn production deployment strategies

Building Forms

Back to building forms guide

Build docs developers (and LLMs) love