Handoff HubSpot Transformer CLI
raw JSON → 0.2.1 verified Fri May 01 auth: no javascript
A CLI toolchain (v0.2.1, pre-1.0, no regular release cadence) that fetches Handoff design system component payloads (Handlebars templates, property schemas) and transpiles them into HubSpot CMS .module folders. Handles Handlebars-to-HubL conversion (variables, conditionals, loops), automatic type-specific rewrites (links, buttons, menus, images, etc.), field JSON generation, metadata assembly, and module validation. Differentiators: schema-aware transpilation reducing manual HubL coding; no active alternatives bridging Handoff and HubSpot natively. Only works with Handoff API access.
Common errors
error Error: Cannot find module 'handoff-hubspot' ↓
cause Package not installed or not in node_modules.
fix
Run
npm install handoff-hubspot or yarn add handoff-hubspot. error TypeError: fetchComponent is not a function ↓
cause Default import used instead of named import.
fix
Change to
import { fetchComponent } from 'handoff-hubspot'. error Error: HANDOFF_API_KEY is required ↓
cause Environment variable HANDOFF_API_KEY not set.
fix
Set the variable:
export HANDOFF_API_KEY=your_key or pass via .env file. Warnings
deprecated The `field` block helper syntax ({{#field type}}) is deprecated and will be removed in v1.0. ↓
fix Use the new property-schema-aware transpilation (automatic). Remove manual {{#field}} blocks from Handlebars templates.
gotcha Handoff API key is required but not validated until fetch time; invalid keys cause opaque 403 errors. ↓
fix Ensure HANDOFF_API_KEY env var is set. Use try/catch around fetchComponent and log the response status.
breaking In v0.1.0, writeModule accepted separate params; in v0.2.0 it was changed to a single options object. ↓
fix Update to writeModule('./path', { html, fields, meta, css, js }).
gotcha Transpiler outputs HubL for HubSpot but does not handle all Handlebars constructs (e.g., partials, subexpressions). ↓
fix Avoid using Handlebars partials or complex subexpressions. Stick to variables, conditionals, and each loops.
breaking In v0.1.0, the 'button' type was mapped to a single field; v0.2.0 introduced split fields (_url.href, _text). ↓
fix Regenerate fields.json with v0.2.0+. Existing modules may need field re-mapping.
Install
npm install handoff-hubspot yarn add handoff-hubspot pnpm add handoff-hubspot Imports
- fetchComponent wrong
const { fetchComponent } = require('handoff-hubspot')correctimport { fetchComponent } from 'handoff-hubspot' - transpile wrong
import transpile from 'handoff-hubspot'correctimport { transpile } from 'handoff-hubspot' - validateModule wrong
import { validateModule } from 'handoff-hubspot/validate'correctimport { validateModule } from 'handoff-hubspot'
Quickstart
import { fetchComponent, transpile, buildFields, buildMeta, writeModule } from 'handoff-hubspot';
async function main() {
const component = await fetchComponent('your-component-id', { apiKey: process.env.HANDOFF_API_KEY ?? '' });
const validation = validateModule(component);
if (validation.some(e => e.severity === 'error')) {
console.error('Validation errors:', validation);
process.exit(1);
}
const html = transpile(component.code, component.properties);
const fields = buildFields(component.properties);
const meta = buildMeta(component);
await writeModule('./output/my-component.module', { html, fields, meta, css: '', js: '' });
console.log('Module generated.');
}
main().catch(console.error);