HubSpot CMSとは何か・他CMSとの違い・プラン選定の考え方から、開発用ポータルの取得・CLI のセットアップ・テーマのディレクトリ設計・theme.json によるデザイントークン定義まで。開発を始めるために必要なすべてをこの章で揃えます。
HubSpot CMS(Content Management System)は、 HubSpotが提供するクラウド型のウェブサイト構築・管理プラットフォームです。 他のCMSと最も異なる点は、CRM(顧客管理)・マーケティング・営業ツールと同一プラットフォーム上に存在することです。 サイトに訪れた人がフォームを送信した瞬間に、コンタクトレコードが作られ、 ワークフローが動き、担当営業に通知が届く——この一気通貫の仕組みが最大の強みです。
① テンプレート言語は HubL のみ:React・Vue・Next.js 等のフロントエンドフレームワークは直接使えない。HubL + 生の HTML/CSS/JS が基本。
② サーバーサイドのカスタム処理不可:PHP・Node.js 等のバックエンドコードは動かせない。動的処理は HubL・HubDB・JavaScript API で代替する。
③ ファイルシステムへの直接アクセス不可:CLI または管理画面を通じてのみファイルを操作できる。
HubSpot CMS は利用プランによって使える機能が大きく異なります。 開発前にクライアントのプランを確認し、何が使えて何が使えないかを把握することが設計の起点になります。
| 機能 | Starter | Professional | Enterprise |
|---|---|---|---|
| カスタムテーマ・モジュール開発 | ✅ | ✅ | ✅ |
| ブログ機能(記事・タグ) | ✅ 1ブログ | ✅ 複数 | ✅ 複数 |
| HubDB(クラウドDB) | ❌ | ✅ | ✅ |
| スマートコンテンツ(パーソナライズ) | ❌ | ✅ | ✅ |
| Dynamic Pages(HubDB連動ページ) | ❌ | ✅ | ✅ |
| A/Bテスト | ❌ | ✅ | ✅ |
| 多言語コンテンツ | ❌ | ✅ | ✅ |
| カスタムオブジェクト(CRM) | ❌ | ❌ | ✅ |
| サンドボックス環境 | ❌ | ⚠️ 標準 | ✅ 開発者用 |
| コンテンツパーティショニング | ❌ | ❌ | ✅ |
| 設計要素 | Starter での代替手段 | Professional以上 |
|---|---|---|
| コンテンツ種別管理 | 1ブログ+タグプレフィックス(type:blog / type:seminar 等)で種別を管理 | 種別ごとに独立したブログを設置 |
| 製品・事例一覧 | ブログのタグ機能で代替・静的なHTMLページで管理 | HubDBテーブルで動的管理 |
| ユーザー属性でのコンテンツ変更 | 基本的に不可(全訪問者に同一コンテンツ) | スマートコンテンツでライフサイクル・業種別表示 |
「HubDBを使ったスタッフ紹介ページを作りたい」という要件があっても、 クライアントが Starter プランであれば HubDB は使えません。 受注直後・設計開始前に必ずプランを確認し、 使えない機能がある場合は代替手段を提案またはプランアップグレードを検討してください。 プランの確認はHubSpot管理画面の「アカウントとサブスクリプション」から行えます。
HubSpot では無料の Developer Accountを作成できます。 Developer Account は本番相当の機能をほぼすべて使えるサンドボックス環境で、 クライアントのポータルに触れる前に開発・検証を行うための必須の環境です。
app.hubspot.com/signup-hubspot/developers からアカウントを作成します。
通常の HubSpot アカウントとは別に「開発者アカウント」として登録します。
既存のHubSpotアカウントを持っている場合は、同じメールアドレスでは作成できないことがあるため、
開発用のメールアドレスを用意することを推奨します。
| 項目 | 内容 |
|---|---|
| 費用 | 無料(Developer Account自体の料金なし) |
| 使える主な機能 | テーマ・モジュール開発・HubDB・フォーム・ブログ・ページ作成 |
| 制限 | メール送信・一部マーケティング機能は制限あり。公開サイトとしての実運用は不可。 |
| ポータル数 | 最大10個のテストポータルを作成可能 |
| データ保持 | 90日間操作がないと削除される場合があるため、定期的にアクセスする |
CLI でポータルにアクセスするために Personal Access Key が必要です。 Developer Account 作成後、以下の手順で発行します。
Personal Access Key はポータルへのフルアクセス権を持ちます。 Slack・メール・GitHubへの貼り付けは厳禁です。 1Password・Bitwarden 等のパスワードマネージャーで管理し、 チームで共有する場合は SecretSharing ツール(例:Keybase)を経由してください。 漏洩した場合は即座に無効化して再発行します。
HubSpot の管理画面は多機能なため、最初は迷いやすいです。 開発者として最低限把握しておくべき画面を整理します。
| 画面名 | メニューの場所 | 開発者が使う場面 |
|---|---|---|
| デザインマネージャー | マーケティング → ファイルとテンプレート → デザインマネージャー | テンプレート・モジュール・CSSの確認・ブラウザ上での編集・プレビュー |
| ファイルマネージャー | マーケティング → ファイルとテンプレート → ファイルマネージャー | 画像・PDFのアップロード・ファイルURLの確認 |
| ウェブサイトページ | マーケティング → ウェブサイト → ウェブサイトページ | 作成したテンプレートの動作確認・ページ設定(canonical・OGP等) |
| ブログ | マーケティング → ウェブサイト → ブログ | ブログ設定・テンプレートとの紐付け確認・タグ管理 |
| HubDB | マーケティング → ファイルとテンプレート → HubDB | テーブルの作成・スキーマ設計・データのテスト投入 |
| フォーム | マーケティング → フォーム | フォームID確認・hidden フィールドの設定・送信後アクションの設定 |
| 設定 → ドメインとURL | ⚙️ 設定 → ウェブサイト → ドメインとURL | ドメイン接続・www設定・ページURLの確認 |
| 設定 → トラッキングコード | ⚙️ 設定 → トラッキングとアナリティクス | GA4・GTMのID設定・HubSpotトラッキングの確認 |
| ツール | バージョン要件 | 用途 |
|---|---|---|
| Node.js | 20.x 以上(必須) | HubSpot CLI v8.0.0 以降は Node 20 が最低要件。nvm での管理を推奨。Node 18 は 2025年10月にサポート終了済み。 |
| @hubspot/cli | v8.0.0 以上 | 2026年2月よりv8が有効。コマンド体系が hs cms upload 等に変更。旧v5系は新規プロジェクト非推奨。 |
| VS Code | 任意 | 推奨エディタ。HubL の拡張機能あり(後述)。 |
| Git | 2.x 以上 | バージョン管理。GitHub Actions での CI/CD に必須。 |
# ===== Step 1: Node.js のバージョン確認(20以上が必要)===== $ node --version v20.11.0 ← 20以上であることを確認(18.x は NG) # nvm を使ったバージョン管理(推奨) $ nvm install 20 $ nvm use 20 # ===== Step 2: HubSpot CLI インストール ===== $ npm install -g @hubspot/cli $ hs --version 5.x.x ← インストール確認 # ===== Step 3: プロジェクトフォルダ作成 ===== $ mkdir my-company-hubspot $ cd my-company-hubspot $ git init $ npm init -y # ===== Step 4: HubSpot CLI 認証 ===== $ hs init ? Enter a name for this account: my-company-dev ? Enter your HubSpot portal ID: 12345678 ? How would you like to authenticate? ❯ Personal Access Key (recommended) ? Enter your personal access key: eu1-xxxx-xxxx-xxxx ✔ Authenticated! Config saved to hubspot.config.yml # ===== Step 5: .gitignore を作成 ===== $ echo "hubspot.config.yml" >> .gitignore $ echo "node_modules/" >> .gitignore $ echo ".DS_Store" >> .gitignore # ===== Step 6: テーマの雛形を生成 ===== $ mkdir src $ hs create theme my-theme --path=./src ✔ Theme created at ./src/my-theme
{
"recommendations": [
"HubSpot.hubl", // HubL シンタックスハイライト・補完
"esbenp.prettier-vscode", // コードフォーマッター
"dbaeumer.vscode-eslint", // JavaScript lint
"bradlc.vscode-tailwindcss", // Tailwind 使う場合
"streetsidesoftware.code-spell-checker" // スペルチェック
]
}
{
// .html ファイルを HubL として認識させる
"files.associations": {
"*.html": "hubl"
},
// 保存時にフォーマット
"editor.formatOnSave": true,
// インデントは2スペース
"editor.tabSize": 2,
"editor.insertSpaces": true
}
実案件のコードベース分析(741モジュール・964テンプレートを持つ大規模プロジェクト)から、 実務で機能する最適なディレクトリ構成を導き出しました。 以下が推奨する標準構成です。
741モジュール・964テンプレートを持つ大規模プロジェクトの分析から、
モジュール数が増えても管理しやすい設計のために以下が重要とわかりました。
① モジュールは .module ディレクトリ単位で管理(5ファイル1セット)
② CSS は ITCSS に近い層構造で管理し、モジュール固有のスタイルは module.css に分離
③ テンプレートはページタイプ別に明確に分ける(汎用/LP/ブログ系/エラーページ)
theme.json は HubSpot テーマの設定ファイルです。
ここで定義した値はHubSpotの管理画面でノーコードで変更でき、
CSS 変数として全テンプレート・全モジュールで参照できます。
「デザインの一元管理の起点」として最も重要なファイルです。
{
"label": "My Company Theme",
"preview_path": "./templates/page.html",
"screenshot_path": "./images/screenshot.png",
"enable_domain_stylesheets": false,
"hide_all_default_modules": true,
// ↑ HubSpotデフォルトモジュールをページエディタに表示しない
// カスタムモジュールのみ使わせる場合は true にする
"fields": [
// ===== カラー =====
{
"type": "group",
"name": "colors",
"label": "カラー設定",
"children": [
{
"type": "color",
"name": "primary_color",
"label": "プライマリカラー",
"default": { "color": "#0052CC", "opacity": 100 }
},
{
"type": "color",
"name": "secondary_color",
"label": "セカンダリカラー",
"default": { "color": "#FF5630", "opacity": 100 }
},
{
"type": "color",
"name": "text_color",
"label": "テキストカラー",
"default": { "color": "#2d3748", "opacity": 100 }
},
{
"type": "color",
"name": "bg_color",
"label": "ページ背景色",
"default": { "color": "#ffffff", "opacity": 100 }
}
]
},
// ===== タイポグラフィ =====
{
"type": "group",
"name": "typography",
"label": "タイポグラフィ",
"children": [
{
"type": "font",
"name": "heading_font",
"label": "見出しフォント",
"default": {
"font": "Noto Sans JP",
"font_set": "GOOGLE",
"variant": "700",
"size": "36px",
"color": "#1a202c"
}
},
{
"type": "font",
"name": "body_font",
"label": "本文フォント",
"default": {
"font": "Noto Sans JP",
"font_set": "GOOGLE",
"variant": "400",
"size": "16px",
"color": "#2d3748"
}
}
]
},
// ===== スペーシング・レイアウト =====
{
"type": "group",
"name": "layout",
"label": "レイアウト設定",
"children": [
{
"type": "number",
"name": "container_max_width",
"label": "コンテナ最大幅(px)",
"default": 1200
},
{
"type": "number",
"name": "section_padding_v",
"label": "セクション上下余白(px)",
"default": 80
},
{
"type": "number",
"name": "border_radius",
"label": "角丸(px)",
"default": 8
}
]
}
]
}
theme.json で定義した値は、HubL を使って CSS 変数として展開します。
全テンプレートの <head> 内か、グローバル CSS の冒頭で定義します。
/* theme.json の値を CSS 変数として展開する HubL の theme 変数でアクセスする */ :root { /* ===== カラー ===== */ --color-primary : {{ theme.colors.primary_color.color }}; --color-secondary : {{ theme.colors.secondary_color.color }}; --color-text : {{ theme.colors.text_color.color }}; --color-bg : {{ theme.colors.bg_color.color }}; /* ===== タイポグラフィ ===== */ --font-heading : {{ theme.typography.heading_font.font }}, sans-serif; --font-body : {{ theme.typography.body_font.font }}, sans-serif; --font-size-base : {{ theme.typography.body_font.size }}; /* ===== レイアウト ===== */ --container-max : {{ theme.layout.container_max_width }}px; --section-padding : {{ theme.layout.section_padding_v }}px; --border-radius : {{ theme.layout.border_radius }}px; /* ===== ブレークポイント(固定値・CSS変数はメディアクエリ内で使えないため参照用)===== */ --bp-sm : 480px; --bp-md : 768px; --bp-lg : 1024px; --bp-xl : 1280px; }
実案件のコードベース分析では、グローバル CSS が ITCSS(Inverted Triangle CSS)に近い 層構造で設計されていることが確認されました。 ITCSS は「抽象→具体」「広範囲→局所」の順にCSSを定義する設計思想で、 スタイルの上書き問題や詳細度の衝突を防ぎます。
/* ===== Objects: レイアウトパターン ===== デザイン(色・フォント)は持たない。構造のみ定義する。 ===================================================== */ /* コンテナ */ .container { width: 100%; max-width: var(--container-max); margin-inline: auto; padding-inline: 20px; } @media (min-width: 768px) { .container { padding-inline: 32px; } } @media (min-width: 1280px) { .container { padding-inline: 40px; } } /* セクション */ .section { padding-block: var(--section-padding); } .section--sm { padding-block: calc(var(--section-padding) * 0.5); } .section--lg { padding-block: calc(var(--section-padding) * 1.5); } /* グリッド */ .grid { display: grid; gap: var(--gap, 24px); } .grid-2 { grid-template-columns: repeat(2, 1fr); } .grid-3 { grid-template-columns: repeat(3, 1fr); } .grid-4 { grid-template-columns: repeat(4, 1fr); } @media (max-width: 768px) { .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; } } @media (min-width: 480px) and (max-width: 1024px) { .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); } }
環境が整ったら、テーマをHubSpotにアップロードして動作を確認します。 以下の手順で最初のアップロードから確認までを完了させます。
# ===== 初回:全ファイルをアップロード ===== $ hs upload src/my-theme @my-theme --portal=dev Uploading "src/my-theme" to "@my-theme" on portal "dev"... ✔ Done! Uploaded 12 files. # ===== 開発中:watch モードで自動同期 ===== $ hs watch src/my-theme @my-theme --portal=dev Watcher started, watching "src/my-theme" # ファイルを保存するたびに自動アップロードされる # ===== アップロード後の確認 ===== # HubSpot管理画面 → マーケティング → デザインマネージャー # 左ペインに @my-theme が表示されれば成功 # ===== ページにテンプレートを適用して確認 ===== # ウェブサイトページ → 新しいページを作成 # → テンプレートに "page.html" を選択 # → プレビューで表示を確認
{
"name": "my-company-hubspot",
"scripts": {
"dev" : "hs cms watch src/my-theme @my-theme --portal=dev",
"deploy:dev" : "hs cms upload src/my-theme @my-theme --portal=dev --overwrite",
"deploy:prod" : "hs cms upload src/my-theme @my-theme --portal=prod --overwrite",
"lint" : "hs lint src/my-theme --portal=dev",
"predeploy:prod": "npm run lint"
},
"devDependencies": {
"@hubspot/cli": "^8.0.0" // CLI v8以上(Node 20必須)
}
}
CRM・MA と一体化したSaaS型CMS。インフラ管理不要・グローバルCDN標準搭載。制約(HubLのみ・バックエンド処理不可)を理解した上で設計する。
HubDB・スマートコンテンツ・複数ブログはProfessional以上。受注直後にプランを確認し、使えない機能がある場合は代替手段を事前に提案する。
Developer Account(無料)/ Personal Access Key(要スコープ設定)/ hubspot.config.yml(必ず.gitignoreに追加)。この3つで開発の準備が整う。
templates / layouts / partials / modules / css / js の分離が基本。モジュールは.moduleディレクトリ単位(5ファイル1セット)で管理する。
カラー・フォント・スペーシングをtheme.jsonで定義 → CSS変数として展開 → 全ファイルで参照。ハードコードは禁止。変更は必ずtheme.jsonを通す。
Settings→Generic→Elements→Objects→Components→Utilitiesの順に定義。モジュール固有スタイルはmodule.cssに分離。層を守ると詳細度の衝突が起きない。