vibespot 0.4.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/LICENSE +33 -0
- package/README.md +118 -0
- package/assets/content-guide.md +445 -0
- package/assets/conversion-guide.md +693 -0
- package/assets/design-guide.md +380 -0
- package/assets/hubspot-rules.md +560 -0
- package/assets/page-types.md +116 -0
- package/bin/vibespot.mjs +11 -0
- package/dist/index.js +6552 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
- package/ui/chat.js +803 -0
- package/ui/dashboard.js +383 -0
- package/ui/dialog.js +117 -0
- package/ui/field-editor.js +292 -0
- package/ui/index.html +393 -0
- package/ui/preview.js +132 -0
- package/ui/settings.js +927 -0
- package/ui/setup.js +830 -0
- package/ui/styles.css +2552 -0
- package/ui/upload-panel.js +554 -0
package/ui/index.html
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>vibeSpot — Build HubSpot Landing Pages with AI</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600&family=Space+Grotesk:wght@500;600;700&display=swap" rel="stylesheet">
|
|
10
|
+
<link rel="stylesheet" href="/styles.css">
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
|
|
14
|
+
<!-- ============================================================ -->
|
|
15
|
+
<!-- SETUP SCREEN — shown until a session is created -->
|
|
16
|
+
<!-- ============================================================ -->
|
|
17
|
+
<div class="setup-topbar" id="setup-topbar">
|
|
18
|
+
<div class="topbar__brand">
|
|
19
|
+
<div class="topbar__logo-icon">v</div>
|
|
20
|
+
<span class="topbar__brand-name">vibeSpot</span>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="setup" id="setup-screen">
|
|
24
|
+
<!-- Left sidebar: project list -->
|
|
25
|
+
<aside class="setup-sidebar" id="setup-sidebar">
|
|
26
|
+
<div class="setup-sidebar__header">
|
|
27
|
+
<span class="setup-sidebar__title">Projects</span>
|
|
28
|
+
<span class="setup-sidebar__count" id="sidebar-project-count">0</span>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="setup-sidebar__list" id="sidebar-project-list">
|
|
31
|
+
<!-- Populated by setup.js -->
|
|
32
|
+
</div>
|
|
33
|
+
<div class="setup-sidebar__footer">
|
|
34
|
+
<button class="setup-sidebar__settings-btn" id="btn-setup-settings">
|
|
35
|
+
<svg width="14" height="14" viewBox="0 0 18 18" fill="none"><path d="M7.5 1.5h3l.4 2.1a5.5 5.5 0 0 1 1.3.7l2-.8 1.5 2.6-1.6 1.3a5.5 5.5 0 0 1 0 1.5l1.6 1.3-1.5 2.6-2-.8a5.5 5.5 0 0 1-1.3.7l-.4 2.1h-3l-.4-2.1a5.5 5.5 0 0 1-1.3-.7l-2 .8-1.5-2.6 1.6-1.3a5.5 5.5 0 0 1 0-1.5L2.3 6.1l1.5-2.6 2 .8a5.5 5.5 0 0 1 1.3-.7L7.5 1.5Z" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/><circle cx="9" cy="9" r="2" stroke="currentColor" stroke-width="1.5"/></svg>
|
|
36
|
+
Settings
|
|
37
|
+
</button>
|
|
38
|
+
</div>
|
|
39
|
+
</aside>
|
|
40
|
+
|
|
41
|
+
<!-- Right side: main content -->
|
|
42
|
+
<div class="setup__main">
|
|
43
|
+
<div class="setup__container">
|
|
44
|
+
<div class="setup__symbol">✦</div>
|
|
45
|
+
<h1 class="setup__title">vibeSpot</h1>
|
|
46
|
+
<p class="setup__subtitle">Build HubSpot landing pages with AI</p>
|
|
47
|
+
|
|
48
|
+
<!-- Environment info (populated by JS) -->
|
|
49
|
+
<div class="setup__alerts" id="setup-alerts"></div>
|
|
50
|
+
|
|
51
|
+
<!-- Walkthrough (shown on first run when environment is not configured) -->
|
|
52
|
+
<div class="walkthrough hidden" id="walkthrough">
|
|
53
|
+
<div class="walkthrough__progress" id="walkthrough-progress"></div>
|
|
54
|
+
<div class="walkthrough__content" id="walkthrough-content"></div>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<!-- Settings link (hidden — now in sidebar footer) -->
|
|
58
|
+
<div class="setup__settings-link hidden" id="setup-settings-link"></div>
|
|
59
|
+
|
|
60
|
+
<!-- Main options -->
|
|
61
|
+
<div class="setup__options" id="setup-options">
|
|
62
|
+
<!-- Previous sessions (hidden — now shown in sidebar) -->
|
|
63
|
+
<div class="setup__section hidden" id="section-recent">
|
|
64
|
+
<div class="setup__cards" id="recent-sessions"></div>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<!-- Local themes (hidden — now shown in sidebar) -->
|
|
68
|
+
<div class="setup__section hidden" id="section-local">
|
|
69
|
+
<div class="setup__cards" id="local-themes"></div>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<!-- Create new -->
|
|
73
|
+
<div class="setup__section">
|
|
74
|
+
<p class="setup__label">Start a new project</p>
|
|
75
|
+
<div class="setup__row">
|
|
76
|
+
<input type="text" class="setup__input setup__input--wide" id="new-theme-name" placeholder="my-landing-page" />
|
|
77
|
+
<button class="btn btn--primary" id="btn-create-theme">Create</button>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<!-- Fetch from HubSpot (only shown if hs is installed) -->
|
|
82
|
+
<div class="setup__section hidden" id="section-fetch">
|
|
83
|
+
<p class="setup__label">Download from HubSpot</p>
|
|
84
|
+
<div class="setup__row">
|
|
85
|
+
<input type="text" class="setup__input setup__input--wide" id="fetch-theme-name" placeholder="theme-name-in-hubspot" />
|
|
86
|
+
<button class="btn btn--secondary" id="btn-fetch-theme">Fetch</button>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<!-- Import from GitHub -->
|
|
91
|
+
<div class="setup__section">
|
|
92
|
+
<p class="setup__label">Import from GitHub</p>
|
|
93
|
+
<div class="setup__row">
|
|
94
|
+
<input type="text" class="setup__input setup__input--wide" id="import-url" placeholder="https://github.com/user/my-landing-page" />
|
|
95
|
+
<button class="btn btn--secondary" id="import-btn">Import</button>
|
|
96
|
+
</div>
|
|
97
|
+
<p class="setup__hint">Convert a React/Lovable project to HubSpot</p>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<!-- Open folder -->
|
|
101
|
+
<div class="setup__section">
|
|
102
|
+
<p class="setup__label">Open from disk</p>
|
|
103
|
+
<div class="setup__row">
|
|
104
|
+
<input type="text" class="setup__input setup__input--wide" id="open-theme-path" placeholder="/path/to/my-theme" />
|
|
105
|
+
<button class="btn btn--secondary" id="btn-open-theme">Open</button>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<div class="setup__loading hidden" id="setup-loading">
|
|
111
|
+
<div class="setup__spinner"></div>
|
|
112
|
+
<span id="setup-loading-text">Setting up...</span>
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<div class="setup__error hidden" id="setup-error"></div>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<!-- ============================================================ -->
|
|
121
|
+
<!-- DASHBOARD — project overview with templates & brand assets -->
|
|
122
|
+
<!-- ============================================================ -->
|
|
123
|
+
<div class="dashboard hidden" id="dashboard-screen">
|
|
124
|
+
<header class="topbar">
|
|
125
|
+
<div class="topbar__left">
|
|
126
|
+
<button class="topbar__back-btn" id="dashboard-back" title="Back to projects">
|
|
127
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>
|
|
128
|
+
</button>
|
|
129
|
+
<div class="topbar__brand">
|
|
130
|
+
<div class="topbar__logo-icon">v</div>
|
|
131
|
+
<span class="topbar__brand-name">vibeSpot</span>
|
|
132
|
+
</div>
|
|
133
|
+
<span class="topbar__project-pill" id="dashboard-theme-name"></span>
|
|
134
|
+
</div>
|
|
135
|
+
<div class="topbar__right">
|
|
136
|
+
<button class="topbar__icon-btn" id="dashboard-settings-btn" title="Settings">
|
|
137
|
+
<svg width="18" height="18" viewBox="0 0 18 18" fill="none"><path d="M7.5 1.5h3l.4 2.1a5.5 5.5 0 0 1 1.3.7l2-.8 1.5 2.6-1.6 1.3a5.5 5.5 0 0 1 0 1.5l1.6 1.3-1.5 2.6-2-.8a5.5 5.5 0 0 1-1.3.7l-.4 2.1h-3l-.4-2.1a5.5 5.5 0 0 1-1.3-.7l-2 .8-1.5-2.6 1.6-1.3a5.5 5.5 0 0 1 0-1.5L2.3 6.1l1.5-2.6 2 .8a5.5 5.5 0 0 1 1.3-.7L7.5 1.5Z" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/><circle cx="9" cy="9" r="2" stroke="currentColor" stroke-width="1.5"/></svg>
|
|
138
|
+
</button>
|
|
139
|
+
<button class="btn btn--primary" id="dashboard-deploy-btn" title="Deploy entire theme to HubSpot">
|
|
140
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right:4px;vertical-align:-2px"><path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z"/></svg>
|
|
141
|
+
Deploy
|
|
142
|
+
</button>
|
|
143
|
+
</div>
|
|
144
|
+
</header>
|
|
145
|
+
|
|
146
|
+
<div class="dashboard__body">
|
|
147
|
+
<div class="dashboard__container">
|
|
148
|
+
|
|
149
|
+
<!-- Brand Assets -->
|
|
150
|
+
<section class="dashboard__section">
|
|
151
|
+
<div class="dashboard__section-header">
|
|
152
|
+
<h2 class="dashboard__section-title">Brand Assets</h2>
|
|
153
|
+
<span class="dashboard__section-hint">Optional — injected into AI prompts</span>
|
|
154
|
+
</div>
|
|
155
|
+
<div class="dashboard__brand-assets" id="dashboard-brand-assets">
|
|
156
|
+
<label class="brand-asset-upload" id="brand-upload-styleguide">
|
|
157
|
+
<input type="file" accept=".md,.txt" hidden>
|
|
158
|
+
<span class="brand-asset-upload__icon" id="brand-icon-styleguide">+</span>
|
|
159
|
+
<span class="brand-asset-upload__label">styleguide.md</span>
|
|
160
|
+
</label>
|
|
161
|
+
<label class="brand-asset-upload" id="brand-upload-brandvoice">
|
|
162
|
+
<input type="file" accept=".md,.txt" hidden>
|
|
163
|
+
<span class="brand-asset-upload__icon" id="brand-icon-brandvoice">+</span>
|
|
164
|
+
<span class="brand-asset-upload__label">brandvoice.md</span>
|
|
165
|
+
</label>
|
|
166
|
+
</div>
|
|
167
|
+
</section>
|
|
168
|
+
|
|
169
|
+
<!-- Page Type Selector -->
|
|
170
|
+
<section class="dashboard__section">
|
|
171
|
+
<div class="dashboard__section-header">
|
|
172
|
+
<h2 class="dashboard__section-title">Create New Page</h2>
|
|
173
|
+
</div>
|
|
174
|
+
<div class="dashboard__page-types" id="dashboard-page-types">
|
|
175
|
+
<button class="page-type-card" data-type="landing_page">
|
|
176
|
+
<div class="page-type-card__icon">
|
|
177
|
+
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18"/><path d="M9 21V9"/></svg>
|
|
178
|
+
</div>
|
|
179
|
+
<span class="page-type-card__label">Landing Page</span>
|
|
180
|
+
<span class="page-type-card__desc">Single-page, conversion-focused</span>
|
|
181
|
+
</button>
|
|
182
|
+
<button class="page-type-card" data-type="blog_post">
|
|
183
|
+
<div class="page-type-card__icon">
|
|
184
|
+
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4h16v16H4z" rx="2"/><path d="M8 8h8"/><path d="M8 12h8"/><path d="M8 16h4"/></svg>
|
|
185
|
+
</div>
|
|
186
|
+
<span class="page-type-card__label">Blog Post</span>
|
|
187
|
+
<span class="page-type-card__desc">Article with blog features</span>
|
|
188
|
+
</button>
|
|
189
|
+
<button class="page-type-card" data-type="website_page">
|
|
190
|
+
<div class="page-type-card__icon">
|
|
191
|
+
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
|
|
192
|
+
</div>
|
|
193
|
+
<span class="page-type-card__label">Website Page</span>
|
|
194
|
+
<span class="page-type-card__desc">With navigation & menu</span>
|
|
195
|
+
</button>
|
|
196
|
+
<button class="page-type-card" data-type="module_only">
|
|
197
|
+
<div class="page-type-card__icon">
|
|
198
|
+
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg>
|
|
199
|
+
</div>
|
|
200
|
+
<span class="page-type-card__label">Module Only</span>
|
|
201
|
+
<span class="page-type-card__desc">Standalone module, no template</span>
|
|
202
|
+
</button>
|
|
203
|
+
</div>
|
|
204
|
+
</section>
|
|
205
|
+
|
|
206
|
+
<!-- Template List -->
|
|
207
|
+
<section class="dashboard__section">
|
|
208
|
+
<div class="dashboard__section-header">
|
|
209
|
+
<h2 class="dashboard__section-title">Templates</h2>
|
|
210
|
+
<span class="dashboard__template-count" id="dashboard-template-count">0</span>
|
|
211
|
+
</div>
|
|
212
|
+
<div class="dashboard__template-list" id="dashboard-template-list">
|
|
213
|
+
<p class="dashboard__empty-state">No templates yet. Choose a page type above to get started.</p>
|
|
214
|
+
</div>
|
|
215
|
+
</section>
|
|
216
|
+
|
|
217
|
+
<!-- Module Library -->
|
|
218
|
+
<section class="dashboard__section">
|
|
219
|
+
<div class="dashboard__section-header">
|
|
220
|
+
<h2 class="dashboard__section-title">Module Library</h2>
|
|
221
|
+
</div>
|
|
222
|
+
<div class="dashboard__module-library" id="dashboard-module-library">
|
|
223
|
+
<p class="dashboard__empty-state">Modules will appear here as you build pages.</p>
|
|
224
|
+
</div>
|
|
225
|
+
<div class="dashboard__module-preview hidden" id="dashboard-module-preview">
|
|
226
|
+
<div class="dashboard__module-preview-header">
|
|
227
|
+
<span class="dashboard__module-preview-name" id="dashboard-preview-name"></span>
|
|
228
|
+
<span class="dashboard__module-preview-used" id="dashboard-preview-used"></span>
|
|
229
|
+
<button class="dashboard__module-preview-close" id="dashboard-preview-close">×</button>
|
|
230
|
+
</div>
|
|
231
|
+
<iframe class="dashboard__module-preview-frame" id="dashboard-preview-frame" sandbox="allow-scripts allow-same-origin"></iframe>
|
|
232
|
+
</div>
|
|
233
|
+
</section>
|
|
234
|
+
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
|
|
239
|
+
<!-- ============================================================ -->
|
|
240
|
+
<!-- MAIN APP — shown after a session is active -->
|
|
241
|
+
<!-- ============================================================ -->
|
|
242
|
+
<div class="app hidden" id="app-screen">
|
|
243
|
+
<header class="topbar">
|
|
244
|
+
<div class="topbar__left">
|
|
245
|
+
<div class="topbar__brand">
|
|
246
|
+
<div class="topbar__logo-icon">v</div>
|
|
247
|
+
<span class="topbar__brand-name">vibeSpot</span>
|
|
248
|
+
</div>
|
|
249
|
+
<span class="topbar__project-pill" id="theme-name"></span>
|
|
250
|
+
</div>
|
|
251
|
+
<div class="topbar__center">
|
|
252
|
+
<div class="responsive-toggle" id="responsive-toggle">
|
|
253
|
+
<button class="responsive-btn active" data-width="100%" title="Desktop">
|
|
254
|
+
<svg width="18" height="14" viewBox="0 0 18 14" fill="none"><rect x="1" y="1" width="16" height="10" rx="1" stroke="currentColor" stroke-width="1.5"/><line x1="6" y1="13" x2="12" y2="13" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
255
|
+
</button>
|
|
256
|
+
<button class="responsive-btn" data-width="768px" title="Tablet">
|
|
257
|
+
<svg width="14" height="18" viewBox="0 0 14 18" fill="none"><rect x="1" y="1" width="12" height="16" rx="1.5" stroke="currentColor" stroke-width="1.5"/><circle cx="7" cy="15" r="0.75" fill="currentColor"/></svg>
|
|
258
|
+
</button>
|
|
259
|
+
<button class="responsive-btn" data-width="375px" title="Mobile">
|
|
260
|
+
<svg width="10" height="18" viewBox="0 0 10 18" fill="none"><rect x="1" y="1" width="8" height="16" rx="1.5" stroke="currentColor" stroke-width="1.5"/><circle cx="5" cy="15" r="0.75" fill="currentColor"/></svg>
|
|
261
|
+
</button>
|
|
262
|
+
</div>
|
|
263
|
+
</div>
|
|
264
|
+
<div class="topbar__right">
|
|
265
|
+
<button class="topbar__icon-btn" id="btn-history" title="Version History" style="display:none">
|
|
266
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
|
267
|
+
</button>
|
|
268
|
+
<button class="topbar__icon-btn" id="btn-settings" title="Settings">
|
|
269
|
+
<svg width="18" height="18" viewBox="0 0 18 18" fill="none"><path d="M7.5 1.5h3l.4 2.1a5.5 5.5 0 0 1 1.3.7l2-.8 1.5 2.6-1.6 1.3a5.5 5.5 0 0 1 0 1.5l1.6 1.3-1.5 2.6-2-.8a5.5 5.5 0 0 1-1.3.7l-.4 2.1h-3l-.4-2.1a5.5 5.5 0 0 1-1.3-.7l-2 .8-1.5-2.6 1.6-1.3a5.5 5.5 0 0 1 0-1.5L2.3 6.1l1.5-2.6 2 .8a5.5 5.5 0 0 1 1.3-.7L7.5 1.5Z" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/><circle cx="9" cy="9" r="2" stroke="currentColor" stroke-width="1.5"/></svg>
|
|
270
|
+
</button>
|
|
271
|
+
<button class="btn btn--primary" id="btn-upload" title="Deploy theme to HubSpot">
|
|
272
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right:4px;vertical-align:-2px"><path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z"/></svg>
|
|
273
|
+
Deploy
|
|
274
|
+
</button>
|
|
275
|
+
</div>
|
|
276
|
+
</header>
|
|
277
|
+
|
|
278
|
+
<div class="layout">
|
|
279
|
+
<aside class="panel panel--left" id="panel-left">
|
|
280
|
+
<div class="module-list" id="module-list">
|
|
281
|
+
<div class="module-list__header">
|
|
282
|
+
<span>Modules</span>
|
|
283
|
+
<span class="module-list__count" id="module-count">0</span>
|
|
284
|
+
<button class="module-list__add-btn" id="btn-add-module" title="Add module from library">+</button>
|
|
285
|
+
</div>
|
|
286
|
+
<div class="module-list__items" id="module-items"></div>
|
|
287
|
+
<div class="module-library-dropdown hidden" id="module-library-dropdown"></div>
|
|
288
|
+
</div>
|
|
289
|
+
|
|
290
|
+
<div class="chat">
|
|
291
|
+
<div class="chat__messages" id="chat-messages">
|
|
292
|
+
<div class="chat__welcome" id="chat-welcome">
|
|
293
|
+
<p>Describe what you want or pick a template to get started.</p>
|
|
294
|
+
|
|
295
|
+
<div class="chat__section-label">Templates</div>
|
|
296
|
+
<div class="chat__starters" id="starter-templates">
|
|
297
|
+
<button class="starter-btn" data-prompt="Create a modern SaaS landing page with a hero section featuring a gradient background, a features grid with icons, a testimonials carousel, a pricing table with 3 tiers, and a CTA section.">SaaS Landing Page</button>
|
|
298
|
+
<button class="starter-btn" data-prompt="Create a portfolio landing page with a hero section, a project gallery grid, an about/bio section, a skills section, and a contact form section.">Portfolio</button>
|
|
299
|
+
<button class="starter-btn" data-prompt="Create a restaurant landing page with a hero section featuring a food image background, a menu section with categories, a reservations section, a reviews section, and a location/hours section.">Restaurant</button>
|
|
300
|
+
<button class="starter-btn" data-prompt="Create an event landing page with a countdown hero, a speakers section with photos and bios, a schedule/agenda section, a sponsors section with logos, and a registration CTA section.">Event / Conference</button>
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
303
|
+
</div>
|
|
304
|
+
<div class="chat__input-area">
|
|
305
|
+
<textarea class="chat__input" id="chat-input" placeholder="Describe your landing page..." rows="1"></textarea>
|
|
306
|
+
<button class="chat__send" id="chat-send" title="Send (Enter)">
|
|
307
|
+
<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M3 10L17 3L10 17L9 11L3 10Z" fill="currentColor"/></svg>
|
|
308
|
+
</button>
|
|
309
|
+
</div>
|
|
310
|
+
</div>
|
|
311
|
+
</aside>
|
|
312
|
+
|
|
313
|
+
<div class="resize-handle" id="resize-handle"></div>
|
|
314
|
+
|
|
315
|
+
<main class="panel panel--right" id="panel-right">
|
|
316
|
+
<div class="preview" id="preview-container">
|
|
317
|
+
<div class="browser-chrome" id="browser-chrome">
|
|
318
|
+
<div class="browser-chrome__bar">
|
|
319
|
+
<div class="browser-chrome__dots">
|
|
320
|
+
<span class="browser-chrome__dot"></span>
|
|
321
|
+
<span class="browser-chrome__dot"></span>
|
|
322
|
+
<span class="browser-chrome__dot"></span>
|
|
323
|
+
</div>
|
|
324
|
+
<div class="browser-chrome__url" id="browser-url">vibespot.app</div>
|
|
325
|
+
</div>
|
|
326
|
+
<iframe id="preview-frame" class="browser-chrome__frame" sandbox="allow-scripts allow-same-origin"></iframe>
|
|
327
|
+
</div>
|
|
328
|
+
</div>
|
|
329
|
+
<aside class="field-editor" id="field-editor">
|
|
330
|
+
<div class="field-editor__header">
|
|
331
|
+
<h3 id="field-editor-title">Fields</h3>
|
|
332
|
+
<button class="field-editor__close" id="field-editor-close">×</button>
|
|
333
|
+
</div>
|
|
334
|
+
<div class="field-editor__content" id="field-editor-content"></div>
|
|
335
|
+
</aside>
|
|
336
|
+
<aside class="history-panel hidden" id="history-panel">
|
|
337
|
+
<div class="history-panel__header">
|
|
338
|
+
<h3>Version History</h3>
|
|
339
|
+
<button class="history-panel__close" id="history-panel-close">×</button>
|
|
340
|
+
</div>
|
|
341
|
+
<div class="history-panel__list" id="history-list"></div>
|
|
342
|
+
</aside>
|
|
343
|
+
</main>
|
|
344
|
+
</div>
|
|
345
|
+
|
|
346
|
+
<!-- Upload panel -->
|
|
347
|
+
<div class="upload-panel hidden" id="upload-panel">
|
|
348
|
+
<div class="upload-panel__header">
|
|
349
|
+
<span class="upload-panel__title" id="upload-status-text">Upload</span>
|
|
350
|
+
<div class="upload-panel__actions" id="upload-actions"></div>
|
|
351
|
+
<button class="upload-panel__toggle" id="upload-panel-toggle" title="Toggle log">
|
|
352
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2"><polyline points="2 8 6 4 10 8"/></svg>
|
|
353
|
+
</button>
|
|
354
|
+
</div>
|
|
355
|
+
<pre class="upload-panel__log" id="upload-log"></pre>
|
|
356
|
+
</div>
|
|
357
|
+
|
|
358
|
+
<footer class="statusbar">
|
|
359
|
+
<span id="status-text">Ready</span>
|
|
360
|
+
<span class="statusbar__pill" id="status-hs-account"></span>
|
|
361
|
+
<span id="status-engine" class="statusbar__engine"></span>
|
|
362
|
+
</footer>
|
|
363
|
+
</div>
|
|
364
|
+
|
|
365
|
+
<!-- ============================================================ -->
|
|
366
|
+
<!-- SETTINGS OVERLAY — accessible from setup screen & main app -->
|
|
367
|
+
<!-- ============================================================ -->
|
|
368
|
+
<div class="settings-overlay hidden" id="settings-overlay">
|
|
369
|
+
<div class="settings-panel">
|
|
370
|
+
<div class="settings__header">
|
|
371
|
+
<h2 class="settings__title">Settings</h2>
|
|
372
|
+
<button class="settings__close" id="settings-close">×</button>
|
|
373
|
+
</div>
|
|
374
|
+
<div class="settings__body" id="settings-body">
|
|
375
|
+
<!-- Populated dynamically by settings.js -->
|
|
376
|
+
<div class="settings__loading">
|
|
377
|
+
<div class="settings__spinner-lg"></div>
|
|
378
|
+
<span>Loading environment...</span>
|
|
379
|
+
</div>
|
|
380
|
+
</div>
|
|
381
|
+
</div>
|
|
382
|
+
</div>
|
|
383
|
+
|
|
384
|
+
<script src="/dialog.js"></script>
|
|
385
|
+
<script src="/setup.js"></script>
|
|
386
|
+
<script src="/dashboard.js"></script>
|
|
387
|
+
<script src="/settings.js"></script>
|
|
388
|
+
<script src="/upload-panel.js"></script>
|
|
389
|
+
<script src="/chat.js"></script>
|
|
390
|
+
<script src="/preview.js"></script>
|
|
391
|
+
<script src="/field-editor.js"></script>
|
|
392
|
+
</body>
|
|
393
|
+
</html>
|
package/ui/preview.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preview management — iframe loading and module scrolling.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const previewFrame = document.getElementById("preview-frame");
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Refresh the preview iframe by reloading from /preview endpoint.
|
|
9
|
+
*/
|
|
10
|
+
function refreshPreview() {
|
|
11
|
+
// Use srcdoc approach: fetch preview HTML and set as srcdoc
|
|
12
|
+
// This avoids cache issues and allows the iframe to update smoothly
|
|
13
|
+
fetch("/preview")
|
|
14
|
+
.then((res) => res.text())
|
|
15
|
+
.then((html) => {
|
|
16
|
+
previewFrame.srcdoc = html;
|
|
17
|
+
})
|
|
18
|
+
.catch((err) => {
|
|
19
|
+
console.error("Preview refresh failed:", err);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Scroll the preview iframe to a specific module by name.
|
|
25
|
+
*/
|
|
26
|
+
function scrollPreviewToModule(moduleName) {
|
|
27
|
+
try {
|
|
28
|
+
const doc = previewFrame.contentDocument || previewFrame.contentWindow.document;
|
|
29
|
+
const el = doc.querySelector(`[data-module="${moduleName}"]`);
|
|
30
|
+
if (el) {
|
|
31
|
+
el.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
32
|
+
|
|
33
|
+
// Brief highlight effect
|
|
34
|
+
el.style.outline = "2px solid #e8613a";
|
|
35
|
+
el.style.outlineOffset = "4px";
|
|
36
|
+
el.style.transition = "outline-color 0.5s ease";
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
el.style.outlineColor = "transparent";
|
|
39
|
+
setTimeout(() => { el.style.outline = ""; el.style.outlineOffset = ""; }, 500);
|
|
40
|
+
}, 1500);
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
// Cross-origin issues — fall back to simple reload
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Show the generating preview — spinner + rotating fun messages.
|
|
49
|
+
* Called when AI generation starts to entertain the user while waiting.
|
|
50
|
+
*/
|
|
51
|
+
function showGeneratingPreview() {
|
|
52
|
+
const html = `<!DOCTYPE html>
|
|
53
|
+
<html lang="en">
|
|
54
|
+
<head>
|
|
55
|
+
<meta charset="utf-8">
|
|
56
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
57
|
+
<style>
|
|
58
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
59
|
+
body {
|
|
60
|
+
min-height: 100vh;
|
|
61
|
+
display: flex;
|
|
62
|
+
align-items: center;
|
|
63
|
+
justify-content: center;
|
|
64
|
+
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
65
|
+
background: #0c0a09;
|
|
66
|
+
color: rgba(255,255,255,0.45);
|
|
67
|
+
}
|
|
68
|
+
.gen {
|
|
69
|
+
text-align: center;
|
|
70
|
+
padding: 2rem;
|
|
71
|
+
}
|
|
72
|
+
.gen p {
|
|
73
|
+
font-size: 1.1rem;
|
|
74
|
+
line-height: 1.6;
|
|
75
|
+
max-width: 440px;
|
|
76
|
+
transition: opacity 0.6s ease;
|
|
77
|
+
}
|
|
78
|
+
.gen p.fade { opacity: 0; }
|
|
79
|
+
.spinner {
|
|
80
|
+
width: 44px;
|
|
81
|
+
height: 44px;
|
|
82
|
+
margin: 0 auto 1.5rem;
|
|
83
|
+
border: 3px solid rgba(232, 97, 58, 0.12);
|
|
84
|
+
border-top-color: rgba(232, 97, 58, 0.7);
|
|
85
|
+
border-radius: 50%;
|
|
86
|
+
animation: spin 0.9s linear infinite;
|
|
87
|
+
}
|
|
88
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
89
|
+
</style>
|
|
90
|
+
</head>
|
|
91
|
+
<body>
|
|
92
|
+
<div class="gen">
|
|
93
|
+
<div class="spinner"></div>
|
|
94
|
+
<p id="msg"></p>
|
|
95
|
+
</div>
|
|
96
|
+
<script>
|
|
97
|
+
var lines = [
|
|
98
|
+
"Choosing the perfect fonts\\u2026 no Comic Sans, we promise",
|
|
99
|
+
"Writing headlines that hit different\\u2026",
|
|
100
|
+
"Crafting testimonials that sound real, not robotic\\u2026",
|
|
101
|
+
"Setting up a pricing section\\u2026 transparent, no hidden fees",
|
|
102
|
+
"Adding the finishing touches\\u2026 micro-animations & hover states",
|
|
103
|
+
"Picking colors that actually work together\\u2026",
|
|
104
|
+
"Building your hero section\\u2026 first impressions matter",
|
|
105
|
+
"Creating a navigation that just makes sense\\u2026",
|
|
106
|
+
"Hold tight \\u2014 great pages take a moment\\u2026",
|
|
107
|
+
"Generating responsive layouts that look good everywhere\\u2026",
|
|
108
|
+
"Making your page scroll-stoppingly good\\u2026",
|
|
109
|
+
"Assembling your FAQ section\\u2026 answering questions before they\\u2019re asked",
|
|
110
|
+
"Designing call-to-action buttons people actually want to click\\u2026",
|
|
111
|
+
"Adding trust signals\\u2026 because credibility matters",
|
|
112
|
+
"Polishing the footer\\u2026 every detail counts"
|
|
113
|
+
];
|
|
114
|
+
var idx = Math.floor(Math.random() * lines.length);
|
|
115
|
+
var el = document.getElementById("msg");
|
|
116
|
+
el.textContent = lines[idx];
|
|
117
|
+
setInterval(function() {
|
|
118
|
+
el.classList.add("fade");
|
|
119
|
+
setTimeout(function() {
|
|
120
|
+
idx = (idx + 1) % lines.length;
|
|
121
|
+
el.textContent = lines[idx];
|
|
122
|
+
el.classList.remove("fade");
|
|
123
|
+
}, 600);
|
|
124
|
+
}, 4000);
|
|
125
|
+
<\/script>
|
|
126
|
+
</body>
|
|
127
|
+
</html>`;
|
|
128
|
+
previewFrame.srcdoc = html;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Preview refresh is triggered by setup.js after a session is created.
|
|
132
|
+
// Do NOT auto-refresh here.
|