vibespot 1.2.0 → 1.3.0
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 +44 -5
- package/assets/blog-rules.md +251 -0
- package/assets/email-rules.md +390 -0
- package/assets/humanify-guide.md +300 -101
- package/assets/plan-templates/blog-content-hub.md +18 -9
- package/assets/plan-templates/email-announcement.md +41 -0
- package/assets/plan-templates/email-event-invite.md +43 -0
- package/assets/plan-templates/email-newsletter.md +41 -0
- package/assets/plan-templates/email-re-engagement.md +42 -0
- package/assets/plan-templates/email-welcome.md +41 -0
- package/dist/index.js +1460 -387
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/starters/06-blog-content-hub.json +75 -0
- package/starters/06-email-welcome.json +60 -0
- package/starters/07-email-announcement.json +60 -0
- package/starters/08-email-newsletter.json +52 -0
- package/ui/chat.js +777 -63
- package/ui/code-editor.js +49 -7
- package/ui/dashboard.js +379 -93
- package/ui/docs/docs.css +29 -0
- package/ui/docs/index.html +186 -108
- package/ui/docs/screenshots/brand-kit-preview.png +0 -0
- package/ui/docs/screenshots/content-type-dropdown.png +0 -0
- package/ui/docs/screenshots/editor-full-layout.png +0 -0
- package/ui/docs/screenshots/inline-wysiwyg-editing.png +0 -0
- package/ui/docs/screenshots/multi-page-tree.png +0 -0
- package/ui/docs/screenshots/onboarding-walkthrough.png +0 -0
- package/ui/docs/screenshots/split-pane-view.png +0 -0
- package/ui/docs/screenshots/visual-controls-toolbar.png +0 -0
- package/ui/docs/screenshots/workspace-tabs.png +0 -0
- package/ui/email-preview.js +109 -0
- package/ui/field-editor.js +72 -1
- package/ui/icons.js +120 -0
- package/ui/index.html +877 -629
- package/ui/inline-edit.js +710 -0
- package/ui/plan.js +0 -0
- package/ui/preview.js +101 -198
- package/ui/section-controls.js +628 -0
- package/ui/settings.js +58 -16
- package/ui/setup.js +750 -140
- package/ui/styles.css +3430 -952
- package/ui/upload-panel.js +47 -20
package/ui/docs/docs.css
CHANGED
|
@@ -975,3 +975,32 @@ kbd {
|
|
|
975
975
|
h1 { font-size: 1.5rem; }
|
|
976
976
|
h2 { font-size: 1.2rem; }
|
|
977
977
|
}
|
|
978
|
+
|
|
979
|
+
/* ================================================================
|
|
980
|
+
Screenshot Placeholders
|
|
981
|
+
Shown until real screenshots are added by the UX team.
|
|
982
|
+
Replace with <img class="doc-screenshot" src="..." alt="...">
|
|
983
|
+
================================================================ */
|
|
984
|
+
.doc-screenshot-placeholder {
|
|
985
|
+
margin: 20px 0 28px;
|
|
986
|
+
padding: 40px 24px;
|
|
987
|
+
border: 2px dashed var(--doc-border-strong);
|
|
988
|
+
border-radius: var(--doc-radius-lg);
|
|
989
|
+
background: var(--doc-bg-card);
|
|
990
|
+
text-align: center;
|
|
991
|
+
}
|
|
992
|
+
.doc-screenshot-placeholder p {
|
|
993
|
+
color: var(--doc-text-muted);
|
|
994
|
+
font-size: 13px;
|
|
995
|
+
font-style: italic;
|
|
996
|
+
margin: 0;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
.doc-screenshot {
|
|
1000
|
+
margin: 20px 0 28px;
|
|
1001
|
+
border: 1px solid var(--doc-border-strong);
|
|
1002
|
+
border-radius: var(--doc-radius-lg);
|
|
1003
|
+
max-width: 100%;
|
|
1004
|
+
height: auto;
|
|
1005
|
+
display: block;
|
|
1006
|
+
}
|
package/ui/docs/index.html
CHANGED
|
@@ -59,12 +59,16 @@
|
|
|
59
59
|
<span class="doc-nav__heading">Using vibeSpot</span>
|
|
60
60
|
<a class="doc-nav__link" href="#editor">The Editor</a>
|
|
61
61
|
<a class="doc-nav__link doc-nav__link--sub" href="#editor-layout">Layout</a>
|
|
62
|
+
<a class="doc-nav__link doc-nav__link--sub" href="#workspace-tabs">Workspace Tabs</a>
|
|
62
63
|
<a class="doc-nav__link doc-nav__link--sub" href="#chat-panel">Chat</a>
|
|
63
64
|
<a class="doc-nav__link doc-nav__link--sub" href="#preview-panel">Preview</a>
|
|
64
65
|
<a class="doc-nav__link doc-nav__link--sub" href="#code-editor">Code Editor</a>
|
|
65
66
|
<a class="doc-nav__link doc-nav__link--sub" href="#module-sidebar">Modules</a>
|
|
66
67
|
<a class="doc-nav__link" href="#creating-pages">Creating Pages</a>
|
|
68
|
+
<a class="doc-nav__link doc-nav__link--sub" href="#onboarding">Onboarding</a>
|
|
67
69
|
<a class="doc-nav__link doc-nav__link--sub" href="#first-page">Your First Page</a>
|
|
70
|
+
<a class="doc-nav__link doc-nav__link--sub" href="#content-types">Content Types</a>
|
|
71
|
+
<a class="doc-nav__link doc-nav__link--sub" href="#multi-page">Multi-Page Sites</a>
|
|
68
72
|
<a class="doc-nav__link doc-nav__link--sub" href="#templates">Templates</a>
|
|
69
73
|
<a class="doc-nav__link doc-nav__link--sub" href="#module-library">Module Library</a>
|
|
70
74
|
</div>
|
|
@@ -87,8 +91,12 @@
|
|
|
87
91
|
<a class="doc-nav__link doc-nav__link--sub" href="#figma-image-modes">Image Modes</a>
|
|
88
92
|
<a class="doc-nav__link doc-nav__link--sub" href="#figma-pipeline">Translation Pipeline</a>
|
|
89
93
|
<a class="doc-nav__link doc-nav__link--sub" href="#figma-tips">Tips & Limits</a>
|
|
94
|
+
<a class="doc-nav__link" href="#inverse-pipeline">Inverse Pipeline</a>
|
|
90
95
|
<a class="doc-nav__link" href="#editing">Editing & Customization</a>
|
|
96
|
+
<a class="doc-nav__link doc-nav__link--sub" href="#inline-wysiwyg">Inline Editing</a>
|
|
97
|
+
<a class="doc-nav__link doc-nav__link--sub" href="#visual-controls">Visual Controls</a>
|
|
91
98
|
<a class="doc-nav__link doc-nav__link--sub" href="#field-editor">Field Editor</a>
|
|
99
|
+
<a class="doc-nav__link doc-nav__link--sub" href="#brand-kit">Brand Kit</a>
|
|
92
100
|
<a class="doc-nav__link doc-nav__link--sub" href="#design-system">Design System</a>
|
|
93
101
|
</div>
|
|
94
102
|
|
|
@@ -109,6 +117,7 @@
|
|
|
109
117
|
<a class="doc-nav__link doc-nav__link--sub" href="#settings-hubspot">HubSpot Tab</a>
|
|
110
118
|
<a class="doc-nav__link doc-nav__link--sub" href="#settings-figma">Figma Tab</a>
|
|
111
119
|
<a class="doc-nav__link" href="#cli-commands">CLI Commands</a>
|
|
120
|
+
<a class="doc-nav__link" href="#hubspot-glossary">HubSpot Terminology</a>
|
|
112
121
|
<a class="doc-nav__link" href="#shortcuts">Shortcuts</a>
|
|
113
122
|
<a class="doc-nav__link" href="#troubleshooting">Troubleshooting</a>
|
|
114
123
|
</div>
|
|
@@ -349,117 +358,28 @@ vibespot</code></pre>
|
|
|
349
358
|
<p>The vibeSpot editor is a browser-based environment for building HubSpot CMS pages. It combines a chat-driven AI assistant with a live preview and code editing capabilities.</p>
|
|
350
359
|
|
|
351
360
|
<h3 id="editor-layout">Layout Overview</h3>
|
|
361
|
+
<p>vibeSpot uses a <strong>two-mode architecture</strong>: <strong>Project Home</strong> for project selection and setup, and <strong>Editor</strong> for building pages. The active mode is controlled by a <code>data-mode</code> attribute and switches automatically when you open a project.</p>
|
|
352
362
|
<p>The editor has three main panels separated by a draggable resize handle:</p>
|
|
353
363
|
<ul>
|
|
354
364
|
<li><strong>Left panel</strong> (380px default) — Contains a module bar button at the top (click to open the module slideout) and the chat interface below it. The module slideout overlays the chat when open. The chat header shows the template name and active AI engine.</li>
|
|
355
365
|
<li><strong>Resize handle</strong> — A 4px draggable divider between panels. Turns orange on hover. Drag to resize the left/right split. The left panel has a minimum width of 300px and maximum of 600px.</li>
|
|
356
|
-
<li><strong>Right panel</strong> (fills remaining space) — Live preview of the rendered page (default) or
|
|
366
|
+
<li><strong>Right panel</strong> (fills remaining space) — Live preview of the rendered page (default), or toggle between Preview, Split, Plan, and Code views. The preview includes a slim browser chrome bar with dots and a URL display.</li>
|
|
357
367
|
</ul>
|
|
368
|
+
<p>On <strong>tablet</strong> viewports (768–1024px), the project rail collapses to a 48px icon-only width, the chat panel narrows, and topbar labels hide to prevent clipping. On viewports <strong>below 768px</strong>, a responsive gate dialog is shown — the full editor requires a wider screen.</p>
|
|
358
369
|
|
|
359
|
-
|
|
360
|
-
<
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
<span class="mock-topbar__btn mock-topbar__btn--accent">↑ Deploy</span>
|
|
373
|
-
</div>
|
|
374
|
-
<div class="mock-editor">
|
|
375
|
-
<div class="mock-editor__left">
|
|
376
|
-
<div class="mock-modules">
|
|
377
|
-
<div class="mock-modules__header"><span style="display:flex;align-items:center;gap:6px">▦▦ Modules</span> <span class="mock-modules__count">5</span></div>
|
|
378
|
-
<div class="mock-module-item"><span class="mock-module-item__grip">⋮⋮</span><span class="mock-module-item__name">Navigation Bar</span><span class="mock-module-item__actions"><span class="mock-module-item__action" title="Edit fields">✎</span><span class="mock-module-item__action" title="Delete">×</span></span></div>
|
|
379
|
-
<div class="mock-module-item"><span class="mock-module-item__grip">⋮⋮</span><span class="mock-module-item__name">Hero Banner</span><span class="mock-module-item__actions"><span class="mock-module-item__action">✎</span><span class="mock-module-item__action">×</span></span></div>
|
|
380
|
-
<div class="mock-module-item"><span class="mock-module-item__grip">⋮⋮</span><span class="mock-module-item__name">Features Grid</span><span class="mock-module-item__actions"><span class="mock-module-item__action">✎</span><span class="mock-module-item__action">×</span></span></div>
|
|
381
|
-
<div class="mock-module-item"><span class="mock-module-item__grip">⋮⋮</span><span class="mock-module-item__name">Pricing Cards</span><span class="mock-module-item__actions"><span class="mock-module-item__action">✎</span><span class="mock-module-item__action">×</span></span></div>
|
|
382
|
-
<div class="mock-module-item"><span class="mock-module-item__grip">⋮⋮</span><span class="mock-module-item__name">Footer</span><span class="mock-module-item__actions"><span class="mock-module-item__action">✎</span><span class="mock-module-item__action">×</span></span></div>
|
|
383
|
-
</div>
|
|
384
|
-
<div class="mock-chat">
|
|
385
|
-
<div style="display:flex;align-items:center;justify-content:space-between;padding:8px 10px;border-bottom:1px solid var(--doc-border)">
|
|
386
|
-
<span style="font-size:11px;font-weight:600;color:var(--doc-text-dim)">Chat</span>
|
|
387
|
-
<span style="font-size:10px;color:var(--doc-text-muted)">Claude (OAuth)</span>
|
|
388
|
-
</div>
|
|
389
|
-
<div class="mock-chat__messages">
|
|
390
|
-
<div class="mock-chat__msg mock-chat__msg--user"><span class="mock-chat__avatar">Y</span><div class="mock-chat__bubble">Build a SaaS landing page for an AI writing tool. Dark theme, modern.</div></div>
|
|
391
|
-
<div class="mock-chat__msg mock-chat__msg--ai"><span class="mock-chat__avatar">AI</span>
|
|
392
|
-
<div class="mock-chat__pipeline">
|
|
393
|
-
<div class="mock-chat__step">✔ Analyzing your request...</div>
|
|
394
|
-
<div class="mock-chat__step">✔ Creating design system...</div>
|
|
395
|
-
<div class="mock-chat__step">✔ Generating 5 modules...</div>
|
|
396
|
-
<div class="mock-chat__step">✔ Quality check...</div>
|
|
397
|
-
<div class="mock-chat__module-cards">
|
|
398
|
-
<span class="mock-chat__module-card mock-chat__module-card--done">✔ Navigation</span>
|
|
399
|
-
<span class="mock-chat__module-card mock-chat__module-card--done">✔ Hero</span>
|
|
400
|
-
<span class="mock-chat__module-card mock-chat__module-card--done">✔ Features</span>
|
|
401
|
-
<span class="mock-chat__module-card mock-chat__module-card--done">✔ Pricing</span>
|
|
402
|
-
<span class="mock-chat__module-card mock-chat__module-card--done">✔ Footer</span>
|
|
403
|
-
</div>
|
|
404
|
-
<div style="color:var(--doc-green);margin-top:4px;font-size:10px">Generated 5 modules in 42s</div>
|
|
405
|
-
</div>
|
|
406
|
-
</div>
|
|
407
|
-
<div class="mock-chat__msg mock-chat__msg--user"><span class="mock-chat__avatar">Y</span><div class="mock-chat__bubble">Make the hero headline bigger and add a gradient.</div></div>
|
|
408
|
-
<div class="mock-chat__msg mock-chat__msg--ai"><span class="mock-chat__avatar">AI</span>
|
|
409
|
-
<div class="mock-chat__pipeline">
|
|
410
|
-
<div class="mock-chat__step">✔ Analyzing your request...</div>
|
|
411
|
-
<div class="mock-chat__step mock-chat__step--active">⟳ Generating 1 module...</div>
|
|
412
|
-
<div class="mock-chat__module-cards">
|
|
413
|
-
<span class="mock-chat__module-card mock-chat__module-card--active">Hero Banner generating...</span>
|
|
414
|
-
</div>
|
|
415
|
-
<div style="color:var(--doc-text-muted);margin-top:4px;font-size:10px">14s</div>
|
|
416
|
-
</div>
|
|
417
|
-
</div>
|
|
418
|
-
</div>
|
|
419
|
-
<div class="mock-chat__input">
|
|
420
|
-
<span style="color:var(--doc-text-muted);font-size:13px;cursor:pointer" title="Attach file">📎</span>
|
|
421
|
-
<input class="mock-chat__input-field" placeholder="Describe your landing page..." disabled>
|
|
422
|
-
<span style="color:var(--doc-text-muted);font-size:12px;cursor:pointer" title="Starter templates">▦▦</span>
|
|
423
|
-
<span class="mock-chat__input-btn">▶</span>
|
|
424
|
-
</div>
|
|
425
|
-
</div>
|
|
426
|
-
</div>
|
|
427
|
-
<div class="mock-editor__resize" title="Drag to resize panels"></div>
|
|
428
|
-
<div class="mock-editor__right">
|
|
429
|
-
<div class="mock-preview">
|
|
430
|
-
<div class="mock-preview__tabs"><span class="mock-preview__tab active">Preview</span><span class="mock-preview__tab">Plan</span><span class="mock-preview__tab">Code</span></div>
|
|
431
|
-
<div class="mock-preview__chrome">
|
|
432
|
-
<div class="mock-preview__dots"><span class="mock-preview__dot"></span><span class="mock-preview__dot"></span><span class="mock-preview__dot"></span></div>
|
|
433
|
-
<div class="mock-preview__url">my-startup.vibespot.app</div>
|
|
434
|
-
</div>
|
|
435
|
-
<div class="mock-preview__body">
|
|
436
|
-
<div class="mock-preview__section" style="background:rgba(255,255,255,0.02);padding:6px 14px;display:flex;justify-content:space-between;font-size:10px">
|
|
437
|
-
<span style="font-weight:600;color:var(--doc-text)">WriteAI</span>
|
|
438
|
-
<span style="color:var(--doc-text-muted)">Features · Pricing · About</span>
|
|
439
|
-
</div>
|
|
440
|
-
<div class="mock-preview__section mock-preview__hero">
|
|
441
|
-
<div class="mock-preview__hero-title">Write Better. Faster.</div>
|
|
442
|
-
<div class="mock-preview__hero-sub">AI-powered writing assistant for teams that ship.</div>
|
|
443
|
-
<span class="mock-preview__hero-btn">Start Free Trial</span>
|
|
444
|
-
</div>
|
|
445
|
-
<div class="mock-preview__cards">
|
|
446
|
-
<div class="mock-preview__card"><div class="mock-preview__card-title">Smart Drafts</div><div class="mock-preview__card-text">Generate first drafts in seconds</div></div>
|
|
447
|
-
<div class="mock-preview__card"><div class="mock-preview__card-title">Team Collab</div><div class="mock-preview__card-text">Real-time editing with your team</div></div>
|
|
448
|
-
<div class="mock-preview__card"><div class="mock-preview__card-title">Brand Voice</div><div class="mock-preview__card-text">Consistent tone across all content</div></div>
|
|
449
|
-
</div>
|
|
450
|
-
</div>
|
|
451
|
-
</div>
|
|
452
|
-
</div>
|
|
453
|
-
</div>
|
|
454
|
-
<div class="mock-statusbar">
|
|
455
|
-
<span>Connected</span>
|
|
456
|
-
<span class="mock-statusbar__spacer"></span>
|
|
457
|
-
<span class="mock-statusbar__dot"></span>
|
|
458
|
-
<span>ALCMST (144870572)</span>
|
|
459
|
-
<span class="mock-statusbar__spacer"></span>
|
|
460
|
-
<span>Claude (OAuth)</span>
|
|
461
|
-
</div>
|
|
462
|
-
</div>
|
|
370
|
+
<h3 id="workspace-tabs">Workspace Tabs</h3>
|
|
371
|
+
<p>The Project Home dashboard is organized into workspace tabs, each covering a distinct concern:</p>
|
|
372
|
+
<ul>
|
|
373
|
+
<li><strong>Pages</strong> — Create new pages and manage existing templates. The page tree sidebar shows all templates with type badges (LP, Blog, Web, Sec), labels, and module counts.</li>
|
|
374
|
+
<li><strong>Brand</strong> — Brand kit (colors, fonts, logo URL) with a live visual preview card showing color swatches, sample text, and logo thumbnail. Also surfaces import analysis results for themes fetched from HubSpot.</li>
|
|
375
|
+
<li><strong>Library</strong> — The shared module library across all pages of the active theme. Browse, preview, and add reusable modules to any template.</li>
|
|
376
|
+
<li><strong>Marketplace</strong> — Marketplace validation and listing metadata editor.</li>
|
|
377
|
+
<li><strong>Settings</strong> — Quick access to AI, HubSpot, Figma, GitHub, and vibeSpot configuration.</li>
|
|
378
|
+
</ul>
|
|
379
|
+
|
|
380
|
+
<img class="doc-screenshot" src="screenshots/workspace-tabs.png" alt="Workspace tabs — Pages, Brand, Library, Marketplace, and Settings — visible in the editor topbar">
|
|
381
|
+
|
|
382
|
+
<img class="doc-screenshot" src="screenshots/editor-full-layout.png" alt="The full editor layout showing chat panel on the left, live preview on the right, and workspace tabs in the topbar">
|
|
463
383
|
|
|
464
384
|
<p>The topbar provides access to theme settings, upload, version history, responsive viewport toggle, and the settings gear.</p>
|
|
465
385
|
|
|
@@ -476,14 +396,19 @@ vibespot</code></pre>
|
|
|
476
396
|
<p>Drag and drop files onto the chat input, or click the attachment button to browse.</p>
|
|
477
397
|
|
|
478
398
|
<h4 id="starter-templates">Starter Templates</h4>
|
|
479
|
-
<p>For quick starts, the
|
|
399
|
+
<p>For quick starts, the Library tab offers six starter templates that bootstrap a new theme with pre-built modules, shared CSS/JS, and module order — instant preview with no AI wait:</p>
|
|
480
400
|
<ul>
|
|
481
401
|
<li><strong>SaaS Landing Page</strong> — Hero, features grid, pricing, testimonials, CTA, footer</li>
|
|
482
402
|
<li><strong>Portfolio</strong> — About section, project gallery, skills, contact form</li>
|
|
483
403
|
<li><strong>Restaurant</strong> — Hero with imagery, menu sections, reservation CTA, location map, hours</li>
|
|
484
404
|
<li><strong>Event / Conference</strong> — Event hero with date, speakers, schedule, sponsors, registration CTA</li>
|
|
405
|
+
<li><strong>Coming Soon</strong> — Countdown hero, email signup, teaser content</li>
|
|
406
|
+
<li><strong>Blog Content Hub</strong> — 8-module blog layout with post body, author bio, related posts, sidebar, and navigation</li>
|
|
485
407
|
</ul>
|
|
486
408
|
|
|
409
|
+
<h4 id="smart-suggestions">Smart Chat Suggestions</h4>
|
|
410
|
+
<p>After each pipeline completion, contextual suggestion chips appear below the assistant message with follow-up actions tailored to your current page. The suggestions are filtered by which modules already exist — you won't see "Add a pricing section" if you already have one. Click a chip to send it as the next message, or ignore them and type your own prompt.</p>
|
|
411
|
+
|
|
487
412
|
<h3 id="preview-panel">Preview Panel</h3>
|
|
488
413
|
<p>The preview panel renders your page using a local HubL subset renderer. It supports variables, conditionals, loops, filters, <code>scope_css</code>, and <code>require_css</code>/<code>require_js</code> tags. The preview automatically refreshes when modules are updated.</p>
|
|
489
414
|
<p>Use the responsive toggle buttons in the topbar to switch viewports:</p>
|
|
@@ -494,6 +419,19 @@ vibespot</code></pre>
|
|
|
494
419
|
</ul>
|
|
495
420
|
<p>During AI generation, modules that are being regenerated show a working overlay with a progress indicator. Modules that have already been generated remain visible and interactive.</p>
|
|
496
421
|
|
|
422
|
+
<h4 id="split-view">Split View</h4>
|
|
423
|
+
<p>Click the <strong>Split</strong> button in the view toggle to show the live preview and code editor side by side in a 50/50 CSS grid layout. This is useful when you want to see how code changes affect the preview in real time. Switching between Preview, Split, Plan, and Code views is fully coordinated.</p>
|
|
424
|
+
|
|
425
|
+
<img class="doc-screenshot" src="screenshots/split-pane-view.png" alt="Split-pane view with live preview on the left and code editor on the right">
|
|
426
|
+
|
|
427
|
+
<h4 id="interact-mode">Interact Mode</h4>
|
|
428
|
+
<p>The <strong>Interact</strong> toggle in the preview topbar replaces the previous separate Select and Edit modes with a single contextual mode. When active:</p>
|
|
429
|
+
<ul>
|
|
430
|
+
<li><strong>Editable elements</strong> (text, images, links) — get inline WYSIWYG editing. Click to edit directly in the preview; changes persist via the API.</li>
|
|
431
|
+
<li><strong>Module containers</strong> — prefill the chat input with a contextual reference so you can describe what you want to change.</li>
|
|
432
|
+
</ul>
|
|
433
|
+
<p>Interact mode auto-deactivates during AI generation and uses a crosshair cursor to distinguish it from normal preview interaction.</p>
|
|
434
|
+
|
|
497
435
|
<h3 id="code-editor">Code Editor</h3>
|
|
498
436
|
<p>Switch to the code editor tab to directly edit module files. The file tree is grouped by module name, and each module contains:</p>
|
|
499
437
|
<ul>
|
|
@@ -587,6 +525,17 @@ vibespot</code></pre>
|
|
|
587
525
|
<li><strong>From React (Beta)</strong> — Clones a React or Lovable project from a Git URL and converts its components into native HubSpot modules. The conversion uses the built-in conversion guide to map React patterns to HubL equivalents.</li>
|
|
588
526
|
</ul>
|
|
589
527
|
|
|
528
|
+
<h3 id="onboarding">Onboarding Walkthrough</h3>
|
|
529
|
+
<p>On first launch (no projects, no local themes), vibeSpot shows a <strong>3-step onboarding walkthrough</strong> on the Project Home screen:</p>
|
|
530
|
+
<ol class="doc-steps">
|
|
531
|
+
<li><strong>What is vibeSpot?</strong> — A brief intro to the product and what it does.</li>
|
|
532
|
+
<li><strong>How it maps to HubSpot</strong> — Sections become modules, design tokens become <code>:root</code> CSS variables, a project becomes a CMS theme.</li>
|
|
533
|
+
<li><strong>Try it</strong> — A pre-filled sample prompt lands in the setup textarea so you can start building immediately.</li>
|
|
534
|
+
</ol>
|
|
535
|
+
<p>The walkthrough includes back/next/skip controls and progress dots. Once completed, a <code>vibespot:introSeen</code> localStorage flag prevents it from reappearing. After the intro, the existing AI-engine setup walkthrough still triggers if no engine is configured. Force-show with <code>?intro</code> in the URL.</p>
|
|
536
|
+
|
|
537
|
+
<img class="doc-screenshot" src="screenshots/onboarding-walkthrough.png" alt="The 3-step onboarding walkthrough shown on first launch, with progress dots and Skip/Next controls">
|
|
538
|
+
|
|
590
539
|
<h3 id="first-page">Your First Page</h3>
|
|
591
540
|
<p>Follow these steps to build your first landing page from scratch:</p>
|
|
592
541
|
<ol class="doc-steps">
|
|
@@ -605,12 +554,36 @@ vibespot</code></pre>
|
|
|
605
554
|
<p><strong>Event:</strong> "Design a tech conference page for DevSummit 2026. Hero with event date and location, speaker grid with photos, 2-day schedule in tabs, sponsor logos, and early-bird registration CTA."</p>
|
|
606
555
|
</div>
|
|
607
556
|
|
|
557
|
+
<h3 id="content-types">Content Types</h3>
|
|
558
|
+
<p>vibeSpot supports three content types, each with its own pipeline prompts, validation rules, and starter templates:</p>
|
|
559
|
+
<ul>
|
|
560
|
+
<li><strong>Landing Page</strong> — The default. Full-width marketing pages with standard HubSpot CMS modules.</li>
|
|
561
|
+
<li><strong>Email</strong> — HubSpot email templates with table-based layout, inline CSS design tokens, and MSO/VML conditional structure for Outlook compatibility. Select "Email" from the page type dropdown in the web UI, or use <code>vibespot email</code> from the CLI. The pipeline routes through email-specific prompts at every stage (architect, module developer, validator).</li>
|
|
562
|
+
<li><strong>Blog</strong> — Blog templates with HubSpot blog variables (<code>content.post_body</code>, <code>content.author</code>, <code>blog_recent_posts</code>, etc.). Blog-specific prompts, validator auto-fix, and a pre-built Blog Content Hub starter template with 8 modules.</li>
|
|
563
|
+
</ul>
|
|
564
|
+
<p>The intent analyzer detects the content type from your prompt (e.g. "create a welcome email" triggers the email pipeline). You can also set it explicitly via the page type dropdown.</p>
|
|
565
|
+
|
|
566
|
+
<img class="doc-screenshot" src="screenshots/content-type-dropdown.png" alt="Page type dropdown showing Landing Page, Email, Website, and Blog Post options">
|
|
567
|
+
|
|
568
|
+
<h3 id="multi-page">Multi-Page Sites</h3>
|
|
569
|
+
<p>vibeSpot can create full multi-page HubSpot sites from a single prompt. When the intent analyzer detects a site-level request (e.g. "build a 5-page website for a restaurant"), it uses the <code>create_site</code> intent to plan:</p>
|
|
570
|
+
<ul>
|
|
571
|
+
<li><strong>Shared modules</strong> — header and footer modules used across all pages</li>
|
|
572
|
+
<li><strong>Per-page layouts</strong> — each page gets its own template with unique modules, a label, page type, and slug</li>
|
|
573
|
+
<li><strong>Cross-page navigation</strong> — nav links between pages are validated to ensure they match actual page slugs</li>
|
|
574
|
+
</ul>
|
|
575
|
+
<p>In the editor, a <strong>page tree sidebar</strong> replaces the old horizontal tab bar. It shows all templates with type badges (LP, Blog, Web, Sec), labels, and module counts. Click a page to switch to it — the chat, modules, and preview reload for that template. An inline creation form lets you add new pages with a type selector.</p>
|
|
576
|
+
<p><strong>Page-scoped chat</strong> means the intent analyzer knows which page you're editing, enabling prompts like "same header as the home page" or "update all pages." The AI context includes <code>activePageLabel</code> and the full list of site pages.</p>
|
|
577
|
+
|
|
578
|
+
<img class="doc-screenshot" src="screenshots/multi-page-tree.png" alt="Page tree sidebar showing Landing Page, About Us, and Company Blog with type badges and module counts">
|
|
579
|
+
|
|
608
580
|
<h3 id="templates">Templates</h3>
|
|
609
581
|
<p>Each theme can contain multiple templates. Templates define different page layouts that share the same module library and design system.</p>
|
|
610
582
|
<p>Supported page types:</p>
|
|
611
583
|
<ul>
|
|
612
584
|
<li><strong>Landing Page</strong> — The default. Full-width marketing pages.</li>
|
|
613
|
-
<li><strong>
|
|
585
|
+
<li><strong>Email</strong> — Table-based email templates with MSO/VML compatibility.</li>
|
|
586
|
+
<li><strong>Blog Post</strong> — Content-focused layout with HubSpot blog variable support.</li>
|
|
614
587
|
<li><strong>Website Page</strong> — Standard pages for your site (About, Contact, etc.).</li>
|
|
615
588
|
<li><strong>Module Only</strong> — Generate standalone modules without a page template.</li>
|
|
616
589
|
</ul>
|
|
@@ -694,6 +667,7 @@ vibespot</code></pre>
|
|
|
694
667
|
<tr><td><code>remove</code></td><td>Delete a module from the page</td><td>"Remove the testimonials section"</td></tr>
|
|
695
668
|
<tr><td><code>rearrange</code></td><td>Reorder existing modules without changing their content</td><td>"Move the CTA section above the footer"</td></tr>
|
|
696
669
|
<tr><td><code>style_change</code></td><td>Update the design system or shared CSS without module changes</td><td>"Change the primary color to green and increase font sizes"</td></tr>
|
|
670
|
+
<tr><td><code>create_site</code></td><td>Generate a full multi-page site with shared modules</td><td>"Build a 5-page restaurant website with Home, Menu, About, Gallery, and Contact"</td></tr>
|
|
697
671
|
<tr><td><code>question</code></td><td>Ask about the page, modules, or HubSpot features (no generation)</td><td>"What modules does this page have?"</td></tr>
|
|
698
672
|
</tbody>
|
|
699
673
|
</table>
|
|
@@ -860,12 +834,63 @@ vibespot</code></pre>
|
|
|
860
834
|
</div>
|
|
861
835
|
</div>
|
|
862
836
|
|
|
837
|
+
<!-- ============================================================
|
|
838
|
+
Section: Inverse Pipeline (HubSpot → vibeSpot)
|
|
839
|
+
============================================================ -->
|
|
840
|
+
<div class="doc-section" id="inverse-pipeline">
|
|
841
|
+
<h2 id="inverse-pipeline-heading">Inverse Pipeline (HubSpot → vibeSpot) <a href="#inverse-pipeline" class="doc-anchor">#</a></h2>
|
|
842
|
+
<p class="doc-subtitle">Reverse-engineer an imported HubSpot theme so the AI understands its design system, module relationships, and round-trip risks before generating modifications.</p>
|
|
843
|
+
|
|
844
|
+
<p>When you import a theme via <strong>From HubSpot</strong>, vibeSpot downloads the files and loads modules into a session. The inverse pipeline goes further: it analyzes the theme's CSS, templates, and field schemas to extract structured context that the AI uses when generating additions or modifications.</p>
|
|
845
|
+
|
|
846
|
+
<h3 id="inverse-what">What Gets Analyzed</h3>
|
|
847
|
+
<ul>
|
|
848
|
+
<li><strong>Design tokens</strong> — <code>:root</code> CSS variables, inferred color palette (with usage counts), typography scale (family, size, weight per role), spacing tokens, border radii, and shadows. These are extracted from both the theme-level CSS and per-module stylesheets.</li>
|
|
849
|
+
<li><strong>Module relationship graph</strong> — Which modules appear in which templates, shared field patterns across modules, and orphan modules (defined but unused by any template).</li>
|
|
850
|
+
<li><strong>Field schema flags</strong> — Patterns that vibeSpot doesn't natively generate: HubDB bindings, deeply nested groups, repeater occurrence limits, custom widget types, conditional visibility rules. These are flagged so the AI avoids breaking them.</li>
|
|
851
|
+
<li><strong>Round-trip risks</strong> — HubL macros, <code>{% raw %}</code> blocks, partials outside <code>modules/</code>, custom <code>module.js</code> files, and <code>import_modules.json</code> references. These patterns survive the round-trip but need preservation — the AI is told not to touch them.</li>
|
|
852
|
+
</ul>
|
|
853
|
+
|
|
854
|
+
<h3 id="inverse-tokens">Design Token Application</h3>
|
|
855
|
+
<p>If the imported theme has no <code>:root</code> variables (common in older themes), the inverse analyzer can synthesize a <code>:root</code> block from the inferred palette and typography, populating <code>sharedCss</code> so the AI generates new modules that visually match the existing ones. Use the <strong>Apply tokens</strong> action in the UI or <code>vibespot inverse --apply-tokens</code> from the CLI.</p>
|
|
856
|
+
|
|
857
|
+
<h3 id="inverse-access">How to Access</h3>
|
|
858
|
+
<ul>
|
|
859
|
+
<li><strong>UI</strong> — After fetching a theme via <strong>From HubSpot</strong>, the import wizard shows the analysis results (tokens, module graph, risks) before you enter the editor.</li>
|
|
860
|
+
<li><strong>CLI</strong> — <code>vibespot inverse [--path <theme-dir>] [--json] [--apply-tokens]</code>. Without <code>--path</code>, it uses the active theme.</li>
|
|
861
|
+
<li><strong>API</strong> — <code>GET /api/inverse/analyze</code> and <code>POST /api/inverse/apply-tokens</code> routes in the web server.</li>
|
|
862
|
+
</ul>
|
|
863
|
+
</div>
|
|
864
|
+
|
|
863
865
|
<!-- ============================================================
|
|
864
866
|
Section 6: Editing & Customization
|
|
865
867
|
============================================================ -->
|
|
866
868
|
<div class="doc-section" id="editing">
|
|
867
869
|
<h2 id="editing-heading">Editing & Customization <a href="#editing" class="doc-anchor">#</a></h2>
|
|
868
|
-
<p>After AI generation, you have full control over every aspect of your page. vibeSpot provides
|
|
870
|
+
<p>After AI generation, you have full control over every aspect of your page. vibeSpot provides multiple editing paths depending on your needs — from clicking directly in the preview to editing raw code.</p>
|
|
871
|
+
|
|
872
|
+
<h3 id="inline-wysiwyg">Inline WYSIWYG Editing</h3>
|
|
873
|
+
<p>The most direct way to edit your page. With <a href="#interact-mode">Interact mode</a> active, click text, images, or links directly in the live preview to edit them inline:</p>
|
|
874
|
+
<ul>
|
|
875
|
+
<li><strong>Text</strong> — Click any text element to get a contenteditable field. Type your changes and click away to save.</li>
|
|
876
|
+
<li><strong>Images</strong> — Click an image to swap the URL.</li>
|
|
877
|
+
<li><strong>Links</strong> — Click a link to edit both the text and the href in a popup.</li>
|
|
878
|
+
</ul>
|
|
879
|
+
<p>Changes persist via <code>/api/field</code> and refresh the preview automatically. Server-side field annotations (<code>annotateFieldRefs</code>) provide deterministic click-to-field mapping so the correct field is always updated. Interact mode is mutually exclusive with normal preview scrolling and disables during AI generation.</p>
|
|
880
|
+
|
|
881
|
+
<img class="doc-screenshot" src="screenshots/inline-wysiwyg-editing.png" alt="Editing a headline directly in the live preview via inline WYSIWYG — the text is selected with a blue highlight">
|
|
882
|
+
|
|
883
|
+
<h3 id="visual-controls">Per-Section Visual Controls</h3>
|
|
884
|
+
<p>Hover over any module section in the preview pane to reveal a floating toolbar with visual controls mapped to the module's fields:</p>
|
|
885
|
+
<ul>
|
|
886
|
+
<li><strong>Color picker</strong> — for color fields (background, text color, accent)</li>
|
|
887
|
+
<li><strong>Padding/margin sliders</strong> — for spacing fields</li>
|
|
888
|
+
<li><strong>Image URL swap</strong> — for image fields</li>
|
|
889
|
+
<li><strong>Font size selector</strong> — for text-size number fields</li>
|
|
890
|
+
</ul>
|
|
891
|
+
<p>All changes persist via <code>/api/field</code> with debounced saves and the preview refreshes on popover close. This is the fastest path for visual adjustments without touching a form or code.</p>
|
|
892
|
+
|
|
893
|
+
<img class="doc-screenshot" src="screenshots/visual-controls-toolbar.png" alt="Interact mode showing a Click to edit tooltip and dashed selection border over a module section">
|
|
869
894
|
|
|
870
895
|
<h3 id="field-editor">No-Code Field Editing</h3>
|
|
871
896
|
<p>The fastest way to tweak content. Open the module slideout (click the <strong>Modules</strong> button), then click the gear icon (⚙) on any module. The slideout switches to the field editor view with a form generated from the module's <code>fields.json</code>. See <a href="#field-editor-sidebar">Field Editor controls</a> for the full list of supported field types.</p>
|
|
@@ -886,6 +911,17 @@ vibespot</code></pre>
|
|
|
886
911
|
<p>Module order in the slideout list equals page order. Open the module slideout and drag items by their grip handle (⠷) to rearrange. The preview updates immediately.</p>
|
|
887
912
|
<p>Recommended landing page flow: Navigation → Hero → Features/Content → Social Proof → CTA/Pricing → Footer.</p>
|
|
888
913
|
|
|
914
|
+
<h3 id="brand-kit">Brand Kit</h3>
|
|
915
|
+
<p>The <strong>Brand</strong> workspace tab provides a structured brand kit that persists as <code>brand-kit.json</code> in <code>.vibespot/</code>. Configure:</p>
|
|
916
|
+
<ul>
|
|
917
|
+
<li><strong>Colors</strong> — primary, secondary, and accent colors via color pickers</li>
|
|
918
|
+
<li><strong>Fonts</strong> — heading and body font families</li>
|
|
919
|
+
<li><strong>Logo URL</strong> — your logo image reference</li>
|
|
920
|
+
</ul>
|
|
921
|
+
<p>A <strong>live preview card</strong> above the form shows color swatches, sample heading and body text rendered with your configured fonts, and a logo thumbnail. Brand kit values are injected as mandatory design constraints into the email architect, email module developer, and page architect prompts. The validator warns on off-brand colors and fonts in generated modules.</p>
|
|
922
|
+
|
|
923
|
+
<img class="doc-screenshot" src="screenshots/brand-kit-preview.png" alt="Brand tab showing live preview card with color swatches, sample heading and body text, color inputs, and font selectors">
|
|
924
|
+
|
|
889
925
|
<h3 id="design-system">Design System</h3>
|
|
890
926
|
<p>The agentic pipeline generates a consistent design system stored in the theme's shared CSS:</p>
|
|
891
927
|
<ul>
|
|
@@ -1243,10 +1279,12 @@ vibespot</code></pre>
|
|
|
1243
1279
|
</thead>
|
|
1244
1280
|
<tbody>
|
|
1245
1281
|
<tr><td><code>vibespot</code></td><td>Start the web UI (default)</td></tr>
|
|
1282
|
+
<tr><td><code>vibespot email</code></td><td>Start in email template mode</td></tr>
|
|
1246
1283
|
<tr><td><code>vibespot wizard</code></td><td>Interactive CLI wizard</td></tr>
|
|
1247
1284
|
<tr><td><code>vibespot init</code></td><td>Environment check & setup</td></tr>
|
|
1248
1285
|
<tr><td><code>vibespot convert</code></td><td>React-to-HubSpot conversion</td></tr>
|
|
1249
1286
|
<tr><td><code>vibespot upload</code></td><td>Upload theme to HubSpot</td></tr>
|
|
1287
|
+
<tr><td><code>vibespot inverse</code></td><td>Analyze an imported theme (design tokens, module graph, risks)</td></tr>
|
|
1250
1288
|
<tr><td><code>vibespot marketplace check</code></td><td>Audit a theme against HubSpot Marketplace requirements</td></tr>
|
|
1251
1289
|
<tr><td><code>vibespot marketplace edit</code></td><td>Edit Marketplace listing metadata (<code>marketplace.json</code>)</td></tr>
|
|
1252
1290
|
<tr><td><code>vibespot doctor</code></td><td>Diagnostics & health check</td></tr>
|
|
@@ -1321,6 +1359,18 @@ vibespot</code></pre>
|
|
|
1321
1359
|
</div>
|
|
1322
1360
|
</div>
|
|
1323
1361
|
|
|
1362
|
+
<div class="doc-collapse">
|
|
1363
|
+
<button class="doc-collapse__trigger">
|
|
1364
|
+
<span class="doc-collapse__arrow">▶</span>
|
|
1365
|
+
<code>vibespot inverse</code> — Analyze Imported Theme
|
|
1366
|
+
</button>
|
|
1367
|
+
<div class="doc-collapse__content">
|
|
1368
|
+
<p>Runs the inverse analyzer on an imported HubSpot theme, extracting design tokens, module relationship graph, field schema flags, and round-trip risks. See <a href="#inverse-pipeline">Inverse Pipeline</a> for details on what gets analyzed.</p>
|
|
1369
|
+
<pre><code>vibespot inverse [--path <theme-dir>] [--json] [--apply-tokens]</code></pre>
|
|
1370
|
+
<p>Without <code>--path</code>, uses the active theme. <code>--json</code> outputs the full report as JSON. <code>--apply-tokens</code> synthesizes a <code>:root</code> CSS block from inferred tokens and writes it to the theme's <code>sharedCss</code>.</p>
|
|
1371
|
+
</div>
|
|
1372
|
+
</div>
|
|
1373
|
+
|
|
1324
1374
|
<div class="doc-collapse">
|
|
1325
1375
|
<button class="doc-collapse__trigger">
|
|
1326
1376
|
<span class="doc-collapse__arrow">▶</span>
|
|
@@ -1334,6 +1384,32 @@ vibespot</code></pre>
|
|
|
1334
1384
|
</div>
|
|
1335
1385
|
</div>
|
|
1336
1386
|
|
|
1387
|
+
<!-- ============================================================
|
|
1388
|
+
Section 10b: HubSpot Glossary
|
|
1389
|
+
============================================================ -->
|
|
1390
|
+
<div class="doc-section" id="hubspot-glossary">
|
|
1391
|
+
<h2 id="hubspot-glossary-heading">HubSpot Terminology <a href="#hubspot-glossary" class="doc-anchor">#</a></h2>
|
|
1392
|
+
<p>vibeSpot generates native HubSpot CMS assets, so most things in the UI map 1:1 to a HubSpot concept. Where a vibeSpot label differs from HubSpot's official vocabulary, this glossary calls it out so you know what to look for inside HubSpot.</p>
|
|
1393
|
+
|
|
1394
|
+
<table>
|
|
1395
|
+
<thead>
|
|
1396
|
+
<tr><th>vibeSpot label</th><th>HubSpot term</th><th>What it is</th></tr>
|
|
1397
|
+
</thead>
|
|
1398
|
+
<tbody>
|
|
1399
|
+
<tr><td>Project</td><td><strong>Theme</strong></td><td>One vibeSpot project produces one HubSpot theme. The theme name in the topbar pill is the folder uploaded to HubSpot's Design Manager.</td></tr>
|
|
1400
|
+
<tr><td>Module / Modules</td><td><strong>Module</strong></td><td>A reusable building block (hero, CTA, pricing table, etc.) with its own <code>fields.json</code>, <code>module.html</code>, and CSS. Earlier vibeSpot copy called these “sections” — this is the same thing.</td></tr>
|
|
1401
|
+
<tr><td>Module Library</td><td><strong>Module library</strong> (theme)</td><td>All reusable modules in the active theme. In HubSpot's Design Manager this is the <code>modules/</code> folder.</td></tr>
|
|
1402
|
+
<tr><td>Module Only (page type)</td><td><strong>Section template</strong> / standalone module</td><td>A single-module template — useful for building one reusable section (e.g. a hero) that can be dropped into any page.</td></tr>
|
|
1403
|
+
<tr><td>Pages</td><td><strong>Templates & Pages</strong></td><td>Each entry under Pages is a HubSpot template (Landing Page, Website Page, Blog Post). Once deployed, you can spin up multiple HubSpot pages from one template.</td></tr>
|
|
1404
|
+
<tr><td>Brand → Brand Kit</td><td><strong>Brand Kit</strong></td><td>Colors, fonts, and logo applied to every generated module. Mirrors HubSpot's Brand Kit in the portal.</td></tr>
|
|
1405
|
+
<tr><td>Library tab</td><td><strong>Module library</strong></td><td>The Library workspace tab shows reusable modules across all pages of the active theme.</td></tr>
|
|
1406
|
+
<tr><td>Marketplace</td><td><strong>HubSpot Marketplace</strong></td><td>Validates the theme against marketplace requirements before publication.</td></tr>
|
|
1407
|
+
<tr><td>Fields</td><td><strong>Module fields</strong></td><td>The editable inputs on a module (text, image, choice, etc.) backed by <code>fields.json</code>.</td></tr>
|
|
1408
|
+
<tr><td>Deploy</td><td><strong>Upload theme</strong></td><td>Pushes the theme folder to HubSpot's Design Manager via the CMS API.</td></tr>
|
|
1409
|
+
</tbody>
|
|
1410
|
+
</table>
|
|
1411
|
+
</div>
|
|
1412
|
+
|
|
1337
1413
|
<!-- ============================================================
|
|
1338
1414
|
Section 11: Keyboard Shortcuts
|
|
1339
1415
|
============================================================ -->
|
|
@@ -1349,6 +1425,8 @@ vibespot</code></pre>
|
|
|
1349
1425
|
<tr><td><kbd>Shift</kbd>+<kbd>Enter</kbd></td><td>New line</td><td>Chat input</td></tr>
|
|
1350
1426
|
<tr><td><kbd>Cmd</kbd>/<kbd>Ctrl</kbd>+<kbd>S</kbd></td><td>Save file</td><td>Code editor</td></tr>
|
|
1351
1427
|
<tr><td><kbd>Escape</kbd></td><td>Close modal or dialog</td><td>Any overlay</td></tr>
|
|
1428
|
+
<tr><td><kbd>Cmd</kbd>/<kbd>Ctrl</kbd>+<kbd>Z</kbd></td><td>Step back one version</td><td>Editor (not in text fields)</td></tr>
|
|
1429
|
+
<tr><td><kbd>Cmd</kbd>/<kbd>Ctrl</kbd>+<kbd>Y</kbd> or <kbd>Shift</kbd>+<kbd>Z</kbd></td><td>Step forward one version</td><td>Editor (not in text fields)</td></tr>
|
|
1352
1430
|
<tr><td><kbd>Escape</kbd></td><td>Close settings panel</td><td>Settings panel</td></tr>
|
|
1353
1431
|
<tr><td><kbd>/</kbd></td><td>Focus search</td><td>Documentation</td></tr>
|
|
1354
1432
|
</tbody>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email client preview — heuristic rendering for Gmail, Outlook Desktop, Apple Mail.
|
|
3
|
+
* Only visible in email content mode.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
(function () {
|
|
7
|
+
const overlay = document.getElementById("email-preview-overlay");
|
|
8
|
+
const closeBtn = document.getElementById("email-preview-close");
|
|
9
|
+
const openBtn = document.getElementById("btn-email-preview");
|
|
10
|
+
const tabsContainer = document.getElementById("email-preview-tabs");
|
|
11
|
+
const frame = document.getElementById("email-preview-frame");
|
|
12
|
+
const notesEl = document.getElementById("email-preview-notes");
|
|
13
|
+
|
|
14
|
+
if (!overlay || !frame) return;
|
|
15
|
+
|
|
16
|
+
let cachedPreviews = null;
|
|
17
|
+
let activeClient = "gmail";
|
|
18
|
+
|
|
19
|
+
function showPreview(client) {
|
|
20
|
+
activeClient = client;
|
|
21
|
+
tabsContainer.querySelectorAll(".email-preview-tab").forEach(function (btn) {
|
|
22
|
+
btn.classList.toggle("active", btn.getAttribute("data-client") === client);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
if (!cachedPreviews) return;
|
|
26
|
+
var preview = cachedPreviews.find(function (p) { return p.client === client; });
|
|
27
|
+
if (!preview) return;
|
|
28
|
+
|
|
29
|
+
frame.srcdoc = preview.html;
|
|
30
|
+
|
|
31
|
+
if (preview.notes && preview.notes.length > 0) {
|
|
32
|
+
notesEl.innerHTML = preview.notes
|
|
33
|
+
.map(function (n) { return '<span class="email-preview-note">' + escapeHtml(n) + '</span>'; })
|
|
34
|
+
.join("");
|
|
35
|
+
notesEl.classList.remove("hidden");
|
|
36
|
+
} else {
|
|
37
|
+
notesEl.classList.add("hidden");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function escapeHtml(str) {
|
|
42
|
+
var div = document.createElement("div");
|
|
43
|
+
div.textContent = str;
|
|
44
|
+
return div.innerHTML;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function openEmailPreview() {
|
|
48
|
+
overlay.classList.remove("hidden");
|
|
49
|
+
notesEl.textContent = "Loading previews...";
|
|
50
|
+
notesEl.classList.remove("hidden");
|
|
51
|
+
|
|
52
|
+
fetch("/api/email-preview/render", {
|
|
53
|
+
method: "POST",
|
|
54
|
+
headers: { "Content-Type": "application/json" },
|
|
55
|
+
body: JSON.stringify({}),
|
|
56
|
+
})
|
|
57
|
+
.then(function (res) { return res.json(); })
|
|
58
|
+
.then(function (data) {
|
|
59
|
+
if (data.error) {
|
|
60
|
+
notesEl.textContent = "Error: " + data.error;
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
cachedPreviews = data.previews;
|
|
64
|
+
showPreview(activeClient);
|
|
65
|
+
})
|
|
66
|
+
.catch(function (err) {
|
|
67
|
+
notesEl.textContent = "Failed to load previews: " + err.message;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function closeEmailPreview() {
|
|
72
|
+
overlay.classList.add("hidden");
|
|
73
|
+
cachedPreviews = null;
|
|
74
|
+
frame.srcdoc = "";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (openBtn) {
|
|
78
|
+
openBtn.addEventListener("click", openEmailPreview);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (closeBtn) {
|
|
82
|
+
closeBtn.addEventListener("click", closeEmailPreview);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
overlay.addEventListener("click", function (e) {
|
|
86
|
+
if (e.target === overlay) closeEmailPreview();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
tabsContainer.addEventListener("click", function (e) {
|
|
90
|
+
var btn = e.target.closest(".email-preview-tab");
|
|
91
|
+
if (!btn) return;
|
|
92
|
+
var client = btn.getAttribute("data-client");
|
|
93
|
+
if (client) showPreview(client);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
document.addEventListener("keydown", function (e) {
|
|
97
|
+
if (e.key === "Escape" && !overlay.classList.contains("hidden")) {
|
|
98
|
+
closeEmailPreview();
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
window.showEmailPreviewButton = function () {
|
|
103
|
+
if (openBtn) openBtn.classList.remove("hidden");
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
window.hideEmailPreviewButton = function () {
|
|
107
|
+
if (openBtn) openBtn.classList.add("hidden");
|
|
108
|
+
};
|
|
109
|
+
})();
|