hs-fieldkit
v0.1.8
Published
A TypeScript library for generating HubSpot CMS fields programmatically.
Downloads
19
Maintainers
Readme
hs-fieldkit
A TypeScript utility library for generating HubSpot field JSON definitions with strong typing and validation.
Features
- Complete Field Coverage: Type-safe builders for all 37 HubSpot field types
- Advanced Properties: Support for all field-specific options and configurations
- Automatic Validation: Built-in validation for required properties and constraints
- TypeScript First: Full type safety with comprehensive type definitions
- Simple API: Composable field builders with consistent patterns
- Rich Examples: Extensive documentation with real-world usage examples
- Vite Integration: Plugin for automated field JSON generation
Installation
bun i hs-fieldkitUsage
Field Builders
All field builder functions require at least a name and label as the first two arguments. Additional properties are passed as the third argument (an object). Some fields require extra parameters.
Supported Field Types
Content Fields: textField, richTextField, emailAddressField, numberField, booleanField, choiceField, dateField, dateTimeField, tagField
Media Fields: imageField, videoField, fileField, logoField, iconField, embedField
Navigation Fields: linkField, urlField, menuField, simpleMenuField, pageField
HubSpot Integration: formField, ctaField, blogField, hubDbTableField, hubDbRowField, crmObjectField, crmObjectPropertyField, followupEmailField
Style Fields: colorField, fontField, alignmentField, textAlignmentField, spacingField, borderField, backgroundImageField, gradientField
Organizational: groupField
import {
textField,
richTextField,
groupField,
booleanField,
choiceField,
// ...other field builders
} from 'hs-fieldkit';
```typescript
import {
textField,
richTextField,
groupField,
booleanField,
choiceField,
alignmentField,
backgroundImageField,
borderField,
colorField,
crmObjectField,
crmObjectPropertyField,
ctaField,
dateField,
dateTimeField,
emailAddressField,
embedField,
fileField,
followupEmailField,
fontField,
formField,
gradientField,
hubDbRowField,
hubDbTableField,
iconField,
imageField,
linkField,
logoField,
menuField,
numberField,
pageField,
simpleMenuField,
spacingField,
tagField,
textAlignmentField,
urlField,
videoField,
blogField,
} from 'hs-fieldkit';
// Basic text field with validation
const productName = textField('product_name', 'Product Name', {
placeholder: 'Enter product name',
validation_regex: '^[a-zA-Z0-9\\s]+$',
required: true,
});
// Rich text with limited features
const description = richTextField('description', 'Description', {
default: '<p>Product description</p>',
enabled_features: ['bold', 'italic', 'link', 'lists'],
});
// Boolean field as toggle
const enableFeature = booleanField('enable_feature', 'Enable Feature', {
display: 'toggle',
default: true,
});
// Choice field with button preset
const layout = choiceField('layout', 'Layout Style', {
choices: [
['cards', 'Card Layout'],
['tiles', 'Tile Layout'],
['minimal', 'Minimal Layout']
],
display: 'buttons',
preset: 'layout',
});
// Number field with constraints
const quantity = numberField('quantity', 'Quantity', {
min: 1,
max: 100,
step: 1,
prefix: 'Qty: ',
suffix: ' items',
display: 'slider',
});
// Color field with limited options
const brandColor = colorField('brand_color', 'Brand Color', {
show_opacity: true,
limited_options: ['#ff0000', '#00ff00', '#0000ff'],
default: { color: '#ff0000', opacity: 100 },
});
// File field for documents
const attachment = fileField('attachment', 'Attachment', {
picker: 'document',
});
// Image field with lazy loading
const heroImage = imageField('hero_image', 'Hero Image', {
responsive: true,
show_loading: true,
resizable: true,
});
// Link field with advanced options
const ctaLink = linkField('cta_link', 'CTA Link', {
supported_types: ['EXTERNAL', 'CONTENT', 'CALL_TO_ACTION'],
show_advanced_rel_options: true,
});
// Form field with restrictions
const contactForm = formField('contact_form', 'Contact Form', {
required_property_types: ['CONTACT'],
embed_versions: ['v4'],
disable_inline_form_editing: false,
});
// Group field with nested fields
const contentGroup = groupField('content_group', 'Content Settings', {
children: [productName, description, enableFeature],
expanded: true,
});Advanced Field Examples
// Alignment field for positioning
const imageAlignment = alignmentField('image_align', 'Image Alignment', {
alignment_direction: 'HORIZONTAL',
default: { horizontal_align: 'CENTER', vertical_align: 'TOP' },
});
// Background image with positioning
const sectionBackground = backgroundImageField('section_bg', 'Section Background', {
default: {
src: '',
background_position: 'CENTER_CENTER',
background_size: 'cover',
},
});
// Border styling
const elementBorder = borderField('element_border', 'Element Border', {
allow_custom_border_sides: true,
});
// CRM object selection
const contactPicker = crmObjectField('contact', 'Select Contact', {
object_type: 'CONTACT',
properties_to_fetch: ['firstname', 'lastname', 'email'],
});
// Date picker
const eventDate = dateField('event_date', 'Event Date', {
default: Date.now(),
});
// Embed field for external content
const videoEmbed = embedField('video_embed', 'Video Embed', {
supported_source_types: ['oembed'],
supported_oembed_types: ['video'],
});
// Font styling
const headingFont = fontField('heading_font', 'Heading Font', {
load_external_fonts: true,
visibility: {
hidden_subfields: { size: false, color: false },
},
});
// Gradient background
const backgroundGradient = gradientField('bg_gradient', 'Background Gradient');
// HubDB table selection
const dataTable = hubDbTableField('data_table', 'Data Table');
// HubDB row selection
const featuredRow = hubDbRowField('featured_row', 'Featured Row', {
table_name_or_id: 'products_table',
display_columns: ['name', 'price'],
display_format: '%0 - $%1',
});
// Icon picker
const featureIcon = iconField('feature_icon', 'Feature Icon', {
icon_set: 'fontawesome-6.4.2',
});
// Logo field
const siteLogo = logoField('site_logo', 'Site Logo', {
show_loading: true,
});
// Page selector
const landingPage = pageField('landing_page', 'Landing Page', {
placeholder: 'Select a page',
});
// Spacing controls
const elementSpacing = spacingField('element_spacing', 'Element Spacing', {
limits: {
padding: {
top: { min: 0, max: 50, units: ['px', 'rem'] },
},
},
});
// Blog tag selector
const postTag = tagField('post_tag', 'Post Tag', {
tag_value: 'SLUG',
});
// Text alignment
const headingAlign = textAlignmentField('heading_align', 'Heading Alignment', {
alignment_direction: 'HORIZONTAL',
});
// Video player
const heroVideo = videoField('hero_video', 'Hero Video', {
show_advanced_options: true,
});
// Blog selector
const featuredBlog = blogField('featured_blog', 'Featured Blog');Common Properties
All fields support these common properties:
required- Whether the field is requiredlocked- Whether the field is editablehelp_text- Tooltip help text (300 char limit)inline_help_text- Inline help text (400 char limit)display_width-'half_width'or'full_width'visibility- Conditional display rulesdefault- Default value for the field
Validation
If required properties are missing (such as name, label, or required field-specific options), the builder functions will throw an error.
Vite Plugin
This package includes a Vite plugin to automate the generation of HubSpot field JSON files from your TypeScript field definitions.
Usage
// vite.config.ts
import { hsFieldkitPlugin } from 'hs-fieldkit/vitePlugin';
export default {
plugins: [
hsFieldkitPlugin(
[
'src/**/fields.ts', // glob patterns for your field definition files
],
'dist/fields.json',
{
prettyPrint: true, // format JSON output
failOnError: true, // throw on errors
}
),
],
};Plugin Options
prettyPrint(default: true): Format the output JSON for readability.failOnError(default: true): Throw errors and halt build on failure.output: Output file or directory. If not provided, outputs next to the source file asfields.json.
Each target file should export a default function that returns an array of field definitions.
Testing
This project uses Vitest for testing.
bun testLicense
MIT
