Module Structure
Every HubSpot module in FreshJuice DEV follows a consistent structure:Creating Your First Module
Create the module directory
Navigate to The
theme/modules/ and create a new directory with the .module extension:.module suffix is required for HubSpot to recognize it as a module.Create meta.json
Define the module metadata. This file controls where and how your module appears in the HubSpot editor.Key properties:
theme/modules/my-custom-module.module/meta.json
global: Set totrueif the module should be available globally across all pagescontent_types: Array of content types where this module can be usedlabel: Display name in the HubSpot editoricon: Optional FontAwesome icon (e.g.,"fontawesome-5.14.0:Folder")
Define module fields
Create Common field types:
fields.json to define the editable fields for your module:theme/modules/my-custom-module.module/fields.json
text: Single-line text inputrichtext: Rich text editor with formattingimage: Image pickergroup: Repeater group for multiple itemsboolean: Checkboxchoice: Dropdown or radio buttonscolor: Color pickerurl: URL input
Create the module template
Create Template tips:
module.html with HubL template code. FreshJuice DEV uses Tailwind CSS and Alpine.js:theme/modules/my-custom-module.module/module.html
- Access field values using
module.field_name - Use conditional statements to handle optional fields
- Apply Tailwind classes directly in your HTML
- Use HubL syntax for loops and conditionals
Add custom styles (optional)
If you need module-specific CSS, create
module.css:theme/modules/my-custom-module.module/module.css
Most styling should be done with Tailwind CSS classes. Only use custom CSS for truly unique styles not available in Tailwind.
Real Example: Stats Module
Here’s how the Stats Simple module is structured in FreshJuice DEV:Module Template (module.html)
theme/modules/stats-simple.module/module.html
- Dynamic grid columns based on the number of items
- HubL loops to iterate through repeating fields
- Tailwind classes for responsive layout
- Clean, semantic HTML structure
Using Repeater Groups
For modules with multiple items (like tabs, testimonials, or stats), use repeater groups:Adding Alpine.js Interactivity
FreshJuice DEV includes Alpine.js for interactive components. Here’s an example from the Tabs module:Testing Your Module
Add to a page
- Go to Marketing > Website > Website Pages
- Create or edit a page
- In the page editor, click the + button to add a module
- Find your module under “Custom Modules”
- Drag it onto the page
Best Practices
Use Semantic HTML
Use appropriate HTML elements (
<article>, <section>, <nav>) for better accessibility and SEO.Mobile-First Design
Apply responsive classes (
sm:, md:, lg:) to ensure your module looks great on all devices.Modular CSS
Prefer Tailwind utility classes over custom CSS. Only add custom CSS when absolutely necessary.
Performance
Keep JavaScript minimal. Use Alpine.js for interactivity instead of heavy frameworks.
Next Steps
Styling Components
Learn how to style your modules with Tailwind CSS
Adding JavaScript
Add interactive functionality with Alpine.js
Theme Fields
Use global theme settings in your modules
Module Reference
Browse all available modules