vibespot 0.4.1 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/assets/conversion-guide.md +2 -2
- package/dist/index.js +24 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/ui/chat.js +64 -12
- package/ui/index.html +15 -4
- package/ui/styles.css +141 -17
package/README.md
CHANGED
|
@@ -6,6 +6,10 @@ AI-powered HubSpot CMS landing page builder — vibe coding & React converter.
|
|
|
6
6
|
≋ vibeSpot — Build HubSpot Landing Pages with AI
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
+
> **Before you start:** vibeSpot's in-app setup will walk you through configuration, but for the smoothest experience, install your preferred AI engine and the HubSpot CLI **before** running vibeSpot. The onboarding flow is still being refined — having these tools ready avoids extra back-and-forth.
|
|
10
|
+
>
|
|
11
|
+
> **Requirements:** Node.js 18+, HubSpot CLI 8+ (`npm install -g @hubspot/cli@latest`). HubSpot CLI versions below 8 are **not supported** — deprecated commands like `hs create` were removed in v8.
|
|
12
|
+
|
|
9
13
|
## What It Does
|
|
10
14
|
|
|
11
15
|
vibeSpot lets you build HubSpot landing pages by chatting with AI. Describe what you want, and it generates native HubSpot CMS modules — fully editable in the HubSpot page editor. No coding knowledge required.
|
|
@@ -222,7 +222,7 @@ This is where React props become HubSpot-editable fields. Every piece of text, i
|
|
|
222
222
|
| `"name": "name"` | `missing field name` | `name` is reserved — use `item_name`, `link_label`, etc. |
|
|
223
223
|
| `{% module %}` in module.html | `'module' is disabled in this context` | Cannot nest modules — use `{% form %}` for forms |
|
|
224
224
|
| `{{ now() }}` | `Could not resolve function 'now'` | Use `{{ local_dt }}` for current date/time |
|
|
225
|
-
| Partially uploaded module | Re-upload still fails | Run `hs
|
|
225
|
+
| Partially uploaded module | Re-upload still fails | Run `hs cms delete <path>` first, then re-upload |
|
|
226
226
|
| SVG in text field | SVG renders as escaped text | SVG markup in text fields is auto-escaped by HubL |
|
|
227
227
|
|
|
228
228
|
### Image Fields
|
|
@@ -618,7 +618,7 @@ For backgrounds with transparency (e.g., glassmorphism cards):
|
|
|
618
618
|
|
|
619
619
|
**Cause**: Partially uploaded module with invalid `fields.json` is cached on HubSpot.
|
|
620
620
|
|
|
621
|
-
**Fix**: `hs
|
|
621
|
+
**Fix**: `hs cms delete my-theme/modules/MyModule.module` then re-upload.
|
|
622
622
|
|
|
623
623
|
### 5. Repeater Group Content Missing
|
|
624
624
|
|
package/dist/index.js
CHANGED
|
@@ -162,13 +162,14 @@ function saveConfig(config) {
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
// src/utils/detect.ts
|
|
165
|
+
var whichCmd = process.platform === "win32" ? "where" : "which";
|
|
165
166
|
function detectNode() {
|
|
166
167
|
const result = run("node --version");
|
|
167
168
|
return {
|
|
168
169
|
name: "Node.js",
|
|
169
170
|
found: result.success,
|
|
170
171
|
version: result.stdout.replace(/^v/, ""),
|
|
171
|
-
path: run(
|
|
172
|
+
path: run(`${whichCmd} node`).stdout
|
|
172
173
|
};
|
|
173
174
|
}
|
|
174
175
|
function detectGit() {
|
|
@@ -177,7 +178,7 @@ function detectGit() {
|
|
|
177
178
|
name: "Git",
|
|
178
179
|
found: result.success,
|
|
179
180
|
version: result.stdout.replace("git version ", ""),
|
|
180
|
-
path: run(
|
|
181
|
+
path: run(`${whichCmd} git`).stdout
|
|
181
182
|
};
|
|
182
183
|
}
|
|
183
184
|
function detectHubSpotCLI() {
|
|
@@ -186,7 +187,7 @@ function detectHubSpotCLI() {
|
|
|
186
187
|
name: "HubSpot CLI",
|
|
187
188
|
found: result.success,
|
|
188
189
|
version: result.stdout,
|
|
189
|
-
path: run(
|
|
190
|
+
path: run(`${whichCmd} hs`).stdout
|
|
190
191
|
};
|
|
191
192
|
}
|
|
192
193
|
function detectClaudeCode() {
|
|
@@ -214,7 +215,7 @@ function detectClaudeCode() {
|
|
|
214
215
|
name: "Claude Code",
|
|
215
216
|
found: true,
|
|
216
217
|
version: result.stdout,
|
|
217
|
-
path: run(
|
|
218
|
+
path: run(`${whichCmd} claude`).stdout,
|
|
218
219
|
authenticated,
|
|
219
220
|
authDetail
|
|
220
221
|
};
|
|
@@ -300,7 +301,7 @@ function detectGeminiCLI() {
|
|
|
300
301
|
name: "Gemini CLI",
|
|
301
302
|
found: true,
|
|
302
303
|
version: result.stdout,
|
|
303
|
-
path: run(
|
|
304
|
+
path: run(`${whichCmd} gemini`).stdout,
|
|
304
305
|
authenticated,
|
|
305
306
|
authDetail: authenticated ? "Authenticated" : "Run `gemini` to sign in with Google"
|
|
306
307
|
};
|
|
@@ -326,7 +327,7 @@ function detectCodexCLI() {
|
|
|
326
327
|
name: "OpenAI Codex CLI",
|
|
327
328
|
found: true,
|
|
328
329
|
version: result.stdout,
|
|
329
|
-
path: run(
|
|
330
|
+
path: run(`${whichCmd} codex`).stdout,
|
|
330
331
|
authenticated,
|
|
331
332
|
authDetail: detail
|
|
332
333
|
};
|
|
@@ -337,7 +338,7 @@ function detectGitHubCLI() {
|
|
|
337
338
|
name: "GitHub CLI",
|
|
338
339
|
found: result.success,
|
|
339
340
|
version: result.stdout.split("\n")[0]?.replace("gh version ", "").split(" ")[0] || "",
|
|
340
|
-
path: run(
|
|
341
|
+
path: run(`${whichCmd} gh`).stdout
|
|
341
342
|
};
|
|
342
343
|
}
|
|
343
344
|
function detectGitHubAuth() {
|
|
@@ -363,6 +364,10 @@ function nodeVersionOk(version) {
|
|
|
363
364
|
const major = parseInt(version.split(".")[0], 10);
|
|
364
365
|
return major >= 18;
|
|
365
366
|
}
|
|
367
|
+
function hsCliVersionOk(version) {
|
|
368
|
+
const major = parseInt(version.split(".")[0], 10);
|
|
369
|
+
return !isNaN(major) && major >= 8;
|
|
370
|
+
}
|
|
366
371
|
function detectEnvironment() {
|
|
367
372
|
const config = loadConfig();
|
|
368
373
|
const node = detectNode();
|
|
@@ -960,13 +965,13 @@ async function setupTheme() {
|
|
|
960
965
|
themePath = join5(workspaceDir, themeName);
|
|
961
966
|
const s = await spinner2();
|
|
962
967
|
s.start("Fetching theme from HubSpot...");
|
|
963
|
-
const result = run(`hs fetch "${themeName}" "${themePath}"`);
|
|
968
|
+
const result = run(`hs cms fetch "${themeName}" "${themePath}"`);
|
|
964
969
|
if (!result.success) {
|
|
965
970
|
s.stop("Fetch failed");
|
|
966
971
|
logError(
|
|
967
972
|
`Could not fetch theme "${themeName}". Check the name in HubSpot Design Manager.`
|
|
968
973
|
);
|
|
969
|
-
logError("Run `hs list /` to see available themes.");
|
|
974
|
+
logError("Run `hs cms list /` to see available themes.");
|
|
970
975
|
process.exit(1);
|
|
971
976
|
}
|
|
972
977
|
s.stop(`Theme fetched: ${theme.dim(themePath)}`);
|
|
@@ -980,7 +985,7 @@ async function setupTheme() {
|
|
|
980
985
|
const s = await spinner2();
|
|
981
986
|
s.start("Creating theme from boilerplate...");
|
|
982
987
|
const cwdBefore = new Set(readdirSync3(process.cwd()));
|
|
983
|
-
const result = run(`hs
|
|
988
|
+
const result = run(`hs cms theme create "${themeName}"`);
|
|
984
989
|
let createdAt = join5(process.cwd(), themeName);
|
|
985
990
|
if (!fileExists(createdAt)) {
|
|
986
991
|
const cwdAfter = readdirSync3(process.cwd());
|
|
@@ -994,7 +999,7 @@ async function setupTheme() {
|
|
|
994
999
|
const errMsg = result.stderr || result.stdout || "";
|
|
995
1000
|
logError(
|
|
996
1001
|
`Could not create theme "${themeName}".` + (errMsg ? `
|
|
997
|
-
${errMsg.slice(0, 300)}` : "") + "\nTry running manually: hs
|
|
1002
|
+
${errMsg.slice(0, 300)}` : "") + "\nTry running manually: hs cms theme create my-theme"
|
|
998
1003
|
);
|
|
999
1004
|
process.exit(1);
|
|
1000
1005
|
}
|
|
@@ -2811,7 +2816,7 @@ The theme may work \u2014 check HubSpot Design Manager.`
|
|
|
2811
2816
|
}
|
|
2812
2817
|
if (!anyFixed) {
|
|
2813
2818
|
s.start("Cleaning up stuck modules...");
|
|
2814
|
-
run(`hs cms
|
|
2819
|
+
run(`hs cms delete "${themeName}/modules"`, {
|
|
2815
2820
|
cwd: join12(themePath, "..")
|
|
2816
2821
|
});
|
|
2817
2822
|
s.stop("Cleaned up modules, retrying...");
|
|
@@ -2996,6 +3001,10 @@ async function doctorCommand() {
|
|
|
2996
3001
|
if (!hs.found) {
|
|
2997
3002
|
logWarn("HubSpot CLI \u2014 not installed (only needed for deployment)");
|
|
2998
3003
|
log2(" Install: npm install -g @hubspot/cli");
|
|
3004
|
+
} else if (!hsCliVersionOk(hs.version)) {
|
|
3005
|
+
logWarn(`HubSpot CLI v${hs.version} \u2014 too old (need v8+)`);
|
|
3006
|
+
log2(" Update: npm install -g @hubspot/cli@latest");
|
|
3007
|
+
issues++;
|
|
2999
3008
|
} else {
|
|
3000
3009
|
logSuccess(`HubSpot CLI v${hs.version}`);
|
|
3001
3010
|
const auth = detectHubSpotAuth();
|
|
@@ -5438,7 +5447,7 @@ function handleSetupCreateRoute(req, res) {
|
|
|
5438
5447
|
rmSync5(themePath, { recursive: true, force: true });
|
|
5439
5448
|
}
|
|
5440
5449
|
const cwdBefore = new Set(readdirSync11(process.cwd()));
|
|
5441
|
-
execSync4(`hs
|
|
5450
|
+
execSync4(`hs cms theme create "${themeName}"`, {
|
|
5442
5451
|
encoding: "utf-8",
|
|
5443
5452
|
stdio: "pipe"
|
|
5444
5453
|
});
|
|
@@ -5479,7 +5488,7 @@ function handleSetupFetchRoute(req, res) {
|
|
|
5479
5488
|
}
|
|
5480
5489
|
const themePath = join15(WORKSPACE_DIR, name);
|
|
5481
5490
|
ensureDir(WORKSPACE_DIR);
|
|
5482
|
-
execSync4(`hs fetch "${name}" "${themePath}"`, {
|
|
5491
|
+
execSync4(`hs cms fetch "${name}" "${themePath}"`, {
|
|
5483
5492
|
encoding: "utf-8",
|
|
5484
5493
|
stdio: "pipe"
|
|
5485
5494
|
});
|
|
@@ -5728,7 +5737,7 @@ function handleSettingsHsAuthRoute(req, res) {
|
|
|
5728
5737
|
}
|
|
5729
5738
|
if (parsed.personalAccessKey) {
|
|
5730
5739
|
const jobId = startJob(
|
|
5731
|
-
`
|
|
5740
|
+
`hs auth --pak="${parsed.personalAccessKey}"`,
|
|
5732
5741
|
"Authenticating with HubSpot",
|
|
5733
5742
|
{ timeout: 3e4 }
|
|
5734
5743
|
);
|