gitcast 1.0.0__py3-none-any.whl
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.
- ai/__init__.py +0 -0
- ai/formatter.py +59 -0
- ai/generator.py +604 -0
- ai/prompts.py +197 -0
- ai/viral_patterns.py +75 -0
- api/__init__.py +0 -0
- api/analytics.py +48 -0
- api/auth.py +49 -0
- api/auth_middleware.py +129 -0
- api/auth_routes.py +117 -0
- api/monitoring.py +56 -0
- api/payload.py +253 -0
- api/ratelimit.py +9 -0
- api/routes.py +1565 -0
- api/server.py +162 -0
- api/validators.py +101 -0
- assets/__init__.py +1 -0
- assets/favicon-16x16.png +0 -0
- assets/favicon-32x32.png +0 -0
- assets/favicon-64x64.png +0 -0
- assets/favicon.ico +0 -0
- assets/icon.png +0 -0
- cli/.env.example +26 -0
- cli/__init__.py +1 -0
- cli/gitcast.py +79 -0
- config/__init__.py +0 -0
- config/settings.py +213 -0
- core/__init__.py +0 -0
- core/capture.py +258 -0
- core/codebase_reader.py +90 -0
- core/framing.py +86 -0
- core/hotkey.py +21 -0
- core/log_stream.py +50 -0
- core/ocr.py +173 -0
- core/screenshot_session.py +274 -0
- core/security.py +126 -0
- core/tray.py +54 -0
- gitcast-1.0.0.dist-info/LICENSE +21 -0
- gitcast-1.0.0.dist-info/METADATA +67 -0
- gitcast-1.0.0.dist-info/RECORD +61 -0
- gitcast-1.0.0.dist-info/WHEEL +5 -0
- gitcast-1.0.0.dist-info/entry_points.txt +2 -0
- gitcast-1.0.0.dist-info/top_level.txt +10 -0
- publisher/__init__.py +0 -0
- publisher/clipboard.py +44 -0
- publisher/twitter.py +100 -0
- storage/__init__.py +0 -0
- storage/cleanup.py +60 -0
- storage/engagement.py +114 -0
- storage/insights.py +203 -0
- storage/key_manager.py +45 -0
- storage/logger.py +208 -0
- storage/metrics.py +119 -0
- storage/sprint.py +40 -0
- storage/streak.py +0 -0
- storage/supabase_client.py +25 -0
- storage/tone_memory.py +139 -0
- ui/__init__.py +0 -0
- web/__init__.py +1 -0
- web/index.html +4994 -0
- web/landing.html +925 -0
web/landing.html
ADDED
|
@@ -0,0 +1,925 @@
|
|
|
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.0">
|
|
6
|
+
<title>GITCAST | captur_build_publish</title>
|
|
7
|
+
<link rel="icon" type="image/x-icon" href="/assets/favicon.ico">
|
|
8
|
+
<link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon-32x32.png">
|
|
9
|
+
<link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon-16x16.png">
|
|
10
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
11
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
12
|
+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,300;0,400;0,500;0,700;1,400&display=swap" rel="stylesheet">
|
|
13
|
+
<style>
|
|
14
|
+
:root {
|
|
15
|
+
/* Identical Brutalist Hacker Design Tokens */
|
|
16
|
+
--bg-root: #0a0a0a;
|
|
17
|
+
--bg-surface: #111111;
|
|
18
|
+
--bg-elevated: #1a1a1a;
|
|
19
|
+
--border: #2a2a2a;
|
|
20
|
+
--border-bright: #444444;
|
|
21
|
+
--text-primary: #e4e4e4;
|
|
22
|
+
--text-secondary: #666666;
|
|
23
|
+
--text-dim: #333333;
|
|
24
|
+
--accent-green: #00ff88;
|
|
25
|
+
--accent-amber: #ffb800;
|
|
26
|
+
--accent-red: #ff4444;
|
|
27
|
+
--accent-blue: #4488ff;
|
|
28
|
+
--accent-purple: #8866ff;
|
|
29
|
+
|
|
30
|
+
--text-xs: 11px;
|
|
31
|
+
--text-sm: 13px;
|
|
32
|
+
--text-base: 14px;
|
|
33
|
+
--text-lg: 16px;
|
|
34
|
+
--text-xl: 20px;
|
|
35
|
+
--text-2xl: 28px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
* {
|
|
39
|
+
box-sizing: border-box;
|
|
40
|
+
margin: 0;
|
|
41
|
+
padding: 0;
|
|
42
|
+
-webkit-font-smoothing: antialiased;
|
|
43
|
+
-moz-osx-font-smoothing: grayscale;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
body {
|
|
47
|
+
font-family: 'JetBrains Mono', monospace;
|
|
48
|
+
background-color: var(--bg-root);
|
|
49
|
+
color: var(--text-primary);
|
|
50
|
+
font-size: var(--text-base);
|
|
51
|
+
line-height: 1.6;
|
|
52
|
+
overflow-x: hidden;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* --- Scroll Fade-in Intersection Class --- */
|
|
56
|
+
.fade-in-section {
|
|
57
|
+
opacity: 0;
|
|
58
|
+
transform: translateY(20px);
|
|
59
|
+
transition: opacity 0.6s ease-out, transform 0.6s ease-out;
|
|
60
|
+
will-change: opacity, transform;
|
|
61
|
+
}
|
|
62
|
+
.fade-in-section.is-visible {
|
|
63
|
+
opacity: 1;
|
|
64
|
+
transform: translateY(0);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* --- Custom Responsive ASCII Box Panels --- */
|
|
68
|
+
.ascii-box {
|
|
69
|
+
display: flex;
|
|
70
|
+
flex-direction: column;
|
|
71
|
+
width: 100%;
|
|
72
|
+
margin-bottom: 24px;
|
|
73
|
+
}
|
|
74
|
+
.ascii-box-header {
|
|
75
|
+
display: flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
font-size: var(--text-xs);
|
|
78
|
+
color: var(--text-secondary);
|
|
79
|
+
height: 20px;
|
|
80
|
+
user-select: none;
|
|
81
|
+
}
|
|
82
|
+
.ascii-box-title {
|
|
83
|
+
padding-right: 4px;
|
|
84
|
+
white-space: nowrap;
|
|
85
|
+
}
|
|
86
|
+
.ascii-box-line {
|
|
87
|
+
flex: 1;
|
|
88
|
+
border-bottom: 1px solid var(--border);
|
|
89
|
+
height: 10px;
|
|
90
|
+
margin: 0 4px;
|
|
91
|
+
}
|
|
92
|
+
.ascii-box-limit {
|
|
93
|
+
padding-left: 4px;
|
|
94
|
+
white-space: nowrap;
|
|
95
|
+
}
|
|
96
|
+
.ascii-box-body {
|
|
97
|
+
border-left: 1px solid var(--border);
|
|
98
|
+
border-right: 1px solid var(--border);
|
|
99
|
+
border-bottom: 1px solid var(--border);
|
|
100
|
+
background: var(--bg-surface);
|
|
101
|
+
padding: 24px;
|
|
102
|
+
position: relative;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* --- Typography Details --- */
|
|
106
|
+
h1, h2, h3 {
|
|
107
|
+
font-weight: 700;
|
|
108
|
+
letter-spacing: -0.02em;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* --- Brutalist Buttons & Hover Animations --- */
|
|
112
|
+
.btn-brutalist {
|
|
113
|
+
font-family: 'JetBrains Mono', monospace;
|
|
114
|
+
font-size: var(--text-sm);
|
|
115
|
+
background: transparent;
|
|
116
|
+
border: 1px solid var(--border);
|
|
117
|
+
color: var(--text-primary);
|
|
118
|
+
padding: 12px 24px;
|
|
119
|
+
cursor: pointer;
|
|
120
|
+
transition: border-color 0.1s, color 0.1s;
|
|
121
|
+
outline: none;
|
|
122
|
+
display: inline-flex;
|
|
123
|
+
align-items: center;
|
|
124
|
+
justify-content: center;
|
|
125
|
+
gap: 8px;
|
|
126
|
+
text-decoration: none;
|
|
127
|
+
user-select: none;
|
|
128
|
+
}
|
|
129
|
+
.btn-brutalist:hover {
|
|
130
|
+
border-color: var(--accent-green) !important;
|
|
131
|
+
color: var(--accent-green) !important;
|
|
132
|
+
background: transparent !important;
|
|
133
|
+
}
|
|
134
|
+
.btn-primary-brutalist {
|
|
135
|
+
background: var(--accent-green);
|
|
136
|
+
color: var(--bg-root);
|
|
137
|
+
border-color: var(--accent-green);
|
|
138
|
+
font-weight: bold;
|
|
139
|
+
}
|
|
140
|
+
.btn-primary-brutalist:hover {
|
|
141
|
+
background: transparent !important;
|
|
142
|
+
color: var(--accent-green) !important;
|
|
143
|
+
border-color: var(--accent-green) !important;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* Subtle pulsing highlight boundary for core CTA */
|
|
147
|
+
.pulse-border {
|
|
148
|
+
animation: pulse-glow 2s infinite;
|
|
149
|
+
}
|
|
150
|
+
@keyframes pulse-glow {
|
|
151
|
+
0% { border-color: var(--border); }
|
|
152
|
+
50% { border-color: var(--accent-green); }
|
|
153
|
+
100% { border-color: var(--border); }
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* --- General Layout containers --- */
|
|
157
|
+
.container {
|
|
158
|
+
max-width: 960px;
|
|
159
|
+
margin: 0 auto;
|
|
160
|
+
padding: 48px 24px;
|
|
161
|
+
width: 100%;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* --- SECTION 1: HERO --- */
|
|
165
|
+
.hero-section {
|
|
166
|
+
min-height: 100vh;
|
|
167
|
+
display: flex;
|
|
168
|
+
flex-direction: column;
|
|
169
|
+
justify-content: center;
|
|
170
|
+
align-items: center;
|
|
171
|
+
padding: 40px 24px;
|
|
172
|
+
text-align: center;
|
|
173
|
+
border-bottom: 1px solid var(--border);
|
|
174
|
+
position: relative;
|
|
175
|
+
}
|
|
176
|
+
.hero-logo-box {
|
|
177
|
+
font-size: clamp(5px, 1.35vw, 14px);
|
|
178
|
+
line-height: 1.12;
|
|
179
|
+
color: var(--accent-green);
|
|
180
|
+
white-space: pre;
|
|
181
|
+
margin-bottom: 32px;
|
|
182
|
+
user-select: none;
|
|
183
|
+
font-family: 'JetBrains Mono', monospace;
|
|
184
|
+
text-align: left;
|
|
185
|
+
display: inline-block;
|
|
186
|
+
max-width: 100%;
|
|
187
|
+
overflow: hidden;
|
|
188
|
+
}
|
|
189
|
+
.hero-tagline {
|
|
190
|
+
font-size: var(--text-2xl);
|
|
191
|
+
color: var(--accent-green);
|
|
192
|
+
line-height: 1.3;
|
|
193
|
+
margin-bottom: 24px;
|
|
194
|
+
text-align: left;
|
|
195
|
+
display: inline-block;
|
|
196
|
+
}
|
|
197
|
+
.hero-subline {
|
|
198
|
+
font-size: var(--text-sm);
|
|
199
|
+
color: var(--text-secondary);
|
|
200
|
+
margin-bottom: 32px;
|
|
201
|
+
text-align: left;
|
|
202
|
+
display: inline-block;
|
|
203
|
+
}
|
|
204
|
+
.hero-ctas {
|
|
205
|
+
display: flex;
|
|
206
|
+
gap: 16px;
|
|
207
|
+
justify-content: center;
|
|
208
|
+
margin-bottom: 48px;
|
|
209
|
+
flex-wrap: wrap;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/* Terminal block emulator styling */
|
|
213
|
+
.terminal-emulator {
|
|
214
|
+
width: 100%;
|
|
215
|
+
max-width: 680px;
|
|
216
|
+
text-align: left;
|
|
217
|
+
box-shadow: none;
|
|
218
|
+
}
|
|
219
|
+
.term-body {
|
|
220
|
+
font-size: var(--text-xs);
|
|
221
|
+
color: var(--text-primary);
|
|
222
|
+
min-height: 280px;
|
|
223
|
+
white-space: pre-wrap;
|
|
224
|
+
word-break: break-all;
|
|
225
|
+
}
|
|
226
|
+
.cursor-blink {
|
|
227
|
+
animation: blink-caret 1s step-end infinite;
|
|
228
|
+
color: var(--accent-green);
|
|
229
|
+
}
|
|
230
|
+
@keyframes blink-caret {
|
|
231
|
+
0%, 100% { opacity: 1; }
|
|
232
|
+
50% { opacity: 0; }
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.scroll-indicator {
|
|
236
|
+
margin-top: auto;
|
|
237
|
+
font-size: var(--text-xs);
|
|
238
|
+
color: var(--text-secondary);
|
|
239
|
+
cursor: pointer;
|
|
240
|
+
text-decoration: none;
|
|
241
|
+
padding-top: 24px;
|
|
242
|
+
transition: color 0.1s;
|
|
243
|
+
}
|
|
244
|
+
.scroll-indicator:hover {
|
|
245
|
+
color: var(--accent-green);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/* --- SECTION 2: THE PROBLEM --- */
|
|
249
|
+
.problem-section {
|
|
250
|
+
border-bottom: 1px solid var(--border);
|
|
251
|
+
}
|
|
252
|
+
.problem-content {
|
|
253
|
+
font-size: var(--text-lg);
|
|
254
|
+
color: var(--text-primary);
|
|
255
|
+
line-height: 1.5;
|
|
256
|
+
text-align: left;
|
|
257
|
+
}
|
|
258
|
+
.problem-cards-grid {
|
|
259
|
+
display: grid;
|
|
260
|
+
grid-template-columns: repeat(3, 1fr);
|
|
261
|
+
gap: 16px;
|
|
262
|
+
margin-top: 24px;
|
|
263
|
+
}
|
|
264
|
+
.problem-card {
|
|
265
|
+
border: 1px solid var(--border);
|
|
266
|
+
padding: 24px;
|
|
267
|
+
background: var(--bg-surface);
|
|
268
|
+
transition: border-color 0.1s, color 0.1s;
|
|
269
|
+
}
|
|
270
|
+
.problem-card:hover {
|
|
271
|
+
border-color: var(--accent-green);
|
|
272
|
+
}
|
|
273
|
+
.problem-card-header {
|
|
274
|
+
font-weight: bold;
|
|
275
|
+
color: var(--accent-red);
|
|
276
|
+
margin-bottom: 12px;
|
|
277
|
+
font-size: var(--text-sm);
|
|
278
|
+
}
|
|
279
|
+
.problem-card-desc {
|
|
280
|
+
font-size: var(--text-sm);
|
|
281
|
+
color: var(--text-secondary);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* --- SECTION 3: THE SOLUTION --- */
|
|
285
|
+
.solution-section {
|
|
286
|
+
border-bottom: 1px solid var(--border);
|
|
287
|
+
}
|
|
288
|
+
.steps-container {
|
|
289
|
+
display: flex;
|
|
290
|
+
flex-direction: column;
|
|
291
|
+
gap: 32px;
|
|
292
|
+
margin-top: 32px;
|
|
293
|
+
}
|
|
294
|
+
.step-row {
|
|
295
|
+
display: flex;
|
|
296
|
+
gap: 24px;
|
|
297
|
+
}
|
|
298
|
+
.step-num {
|
|
299
|
+
font-size: var(--text-xl);
|
|
300
|
+
color: var(--accent-green);
|
|
301
|
+
font-weight: bold;
|
|
302
|
+
line-height: 1;
|
|
303
|
+
}
|
|
304
|
+
.step-details h3 {
|
|
305
|
+
font-size: var(--text-base);
|
|
306
|
+
color: var(--text-primary);
|
|
307
|
+
margin-bottom: 6px;
|
|
308
|
+
text-transform: uppercase;
|
|
309
|
+
}
|
|
310
|
+
.step-details p {
|
|
311
|
+
font-size: var(--text-sm);
|
|
312
|
+
color: var(--text-secondary);
|
|
313
|
+
}
|
|
314
|
+
.step-tag {
|
|
315
|
+
color: var(--accent-blue);
|
|
316
|
+
font-size: var(--text-xs);
|
|
317
|
+
margin-top: 4px;
|
|
318
|
+
display: inline-block;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/* --- SECTION 4: FEATURES GRID --- */
|
|
322
|
+
.features-section {
|
|
323
|
+
border-bottom: 1px solid var(--border);
|
|
324
|
+
}
|
|
325
|
+
.features-grid {
|
|
326
|
+
display: grid;
|
|
327
|
+
grid-template-columns: repeat(2, 1fr);
|
|
328
|
+
gap: 16px;
|
|
329
|
+
margin-top: 32px;
|
|
330
|
+
}
|
|
331
|
+
.feature-card {
|
|
332
|
+
border: 1px solid var(--border);
|
|
333
|
+
background: var(--bg-surface);
|
|
334
|
+
padding: 24px;
|
|
335
|
+
transition: border-color 0.1s;
|
|
336
|
+
}
|
|
337
|
+
.feature-card:hover {
|
|
338
|
+
border-color: var(--accent-green);
|
|
339
|
+
}
|
|
340
|
+
.feature-title {
|
|
341
|
+
color: var(--accent-green);
|
|
342
|
+
font-size: var(--text-sm);
|
|
343
|
+
font-weight: bold;
|
|
344
|
+
margin-bottom: 12px;
|
|
345
|
+
}
|
|
346
|
+
.feature-desc {
|
|
347
|
+
font-size: var(--text-sm);
|
|
348
|
+
color: var(--text-secondary);
|
|
349
|
+
line-height: 1.5;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/* --- SECTION 5: SOCIAL PROOF & WAITLIST --- */
|
|
353
|
+
.social-section {
|
|
354
|
+
border-bottom: 1px solid var(--border);
|
|
355
|
+
text-align: center;
|
|
356
|
+
}
|
|
357
|
+
.waitlist-container {
|
|
358
|
+
max-width: 480px;
|
|
359
|
+
margin: 32px auto 0 auto;
|
|
360
|
+
}
|
|
361
|
+
.waitlist-box {
|
|
362
|
+
border: 1px solid var(--border);
|
|
363
|
+
background: var(--bg-surface);
|
|
364
|
+
display: flex;
|
|
365
|
+
align-items: center;
|
|
366
|
+
padding: 6px 12px;
|
|
367
|
+
position: relative;
|
|
368
|
+
}
|
|
369
|
+
.waitlist-prompt {
|
|
370
|
+
color: var(--accent-green);
|
|
371
|
+
font-size: var(--text-sm);
|
|
372
|
+
margin-right: 8px;
|
|
373
|
+
user-select: none;
|
|
374
|
+
}
|
|
375
|
+
.waitlist-input {
|
|
376
|
+
flex: 1;
|
|
377
|
+
background: transparent;
|
|
378
|
+
border: none;
|
|
379
|
+
outline: none;
|
|
380
|
+
color: var(--text-primary);
|
|
381
|
+
font-family: 'JetBrains Mono', monospace;
|
|
382
|
+
font-size: var(--text-sm);
|
|
383
|
+
caret-color: var(--accent-green);
|
|
384
|
+
}
|
|
385
|
+
.waitlist-btn {
|
|
386
|
+
background: transparent;
|
|
387
|
+
border: none;
|
|
388
|
+
color: var(--text-secondary);
|
|
389
|
+
cursor: pointer;
|
|
390
|
+
font-family: 'JetBrains Mono', monospace;
|
|
391
|
+
font-weight: bold;
|
|
392
|
+
font-size: var(--text-sm);
|
|
393
|
+
padding: 6px;
|
|
394
|
+
outline: none;
|
|
395
|
+
transition: color 0.1s;
|
|
396
|
+
}
|
|
397
|
+
.waitlist-btn:hover {
|
|
398
|
+
color: var(--accent-green);
|
|
399
|
+
}
|
|
400
|
+
.waitlist-status-message {
|
|
401
|
+
font-size: var(--text-xs);
|
|
402
|
+
margin-top: 12px;
|
|
403
|
+
text-align: left;
|
|
404
|
+
min-height: 18px;
|
|
405
|
+
font-weight: bold;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/* --- SECTION 6: PRICING --- */
|
|
409
|
+
.pricing-section {
|
|
410
|
+
border-bottom: 1px solid var(--border);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/* Monospace High-Fidelity Table Layout */
|
|
414
|
+
.table-responsive {
|
|
415
|
+
width: 100%;
|
|
416
|
+
overflow-x: auto;
|
|
417
|
+
margin-top: 32px;
|
|
418
|
+
margin-bottom: 12px;
|
|
419
|
+
}
|
|
420
|
+
.terminal-table {
|
|
421
|
+
width: 100%;
|
|
422
|
+
border-collapse: collapse;
|
|
423
|
+
font-size: var(--text-xs);
|
|
424
|
+
color: var(--text-primary);
|
|
425
|
+
text-align: left;
|
|
426
|
+
white-space: nowrap;
|
|
427
|
+
}
|
|
428
|
+
.terminal-table th, .terminal-table td {
|
|
429
|
+
padding: 12px 16px;
|
|
430
|
+
border: 1px solid var(--border);
|
|
431
|
+
background: var(--bg-surface);
|
|
432
|
+
}
|
|
433
|
+
.terminal-table th {
|
|
434
|
+
color: var(--accent-green);
|
|
435
|
+
font-weight: bold;
|
|
436
|
+
}
|
|
437
|
+
.pricing-row-divider {
|
|
438
|
+
color: var(--text-secondary);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/* --- SECTION 7: FOOTER --- */
|
|
442
|
+
.footer-section {
|
|
443
|
+
padding: 48px 24px;
|
|
444
|
+
}
|
|
445
|
+
.footer-content {
|
|
446
|
+
font-size: var(--text-xs);
|
|
447
|
+
color: var(--text-secondary);
|
|
448
|
+
display: flex;
|
|
449
|
+
flex-direction: column;
|
|
450
|
+
gap: 12px;
|
|
451
|
+
}
|
|
452
|
+
.footer-links {
|
|
453
|
+
display: flex;
|
|
454
|
+
gap: 16px;
|
|
455
|
+
}
|
|
456
|
+
.footer-links a {
|
|
457
|
+
color: var(--accent-blue);
|
|
458
|
+
text-decoration: none;
|
|
459
|
+
transition: color 0.1s;
|
|
460
|
+
}
|
|
461
|
+
.footer-links a:hover {
|
|
462
|
+
color: var(--accent-green);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/* --- MOBILE LAYOUTS (Single column stacked) --- */
|
|
466
|
+
@media (max-width: 768px) {
|
|
467
|
+
.hero-logo-box {
|
|
468
|
+
font-size: 5px;
|
|
469
|
+
}
|
|
470
|
+
.hero-tagline {
|
|
471
|
+
font-size: var(--text-lg);
|
|
472
|
+
}
|
|
473
|
+
.problem-cards-grid {
|
|
474
|
+
grid-template-columns: 1fr;
|
|
475
|
+
}
|
|
476
|
+
.features-grid {
|
|
477
|
+
grid-template-columns: 1fr;
|
|
478
|
+
}
|
|
479
|
+
.term-body {
|
|
480
|
+
min-height: auto;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
</style>
|
|
484
|
+
</head>
|
|
485
|
+
<body>
|
|
486
|
+
|
|
487
|
+
<!-- Section 1: Hero Section -->
|
|
488
|
+
<header class="hero-section">
|
|
489
|
+
<pre class="hero-logo-box"> ██████╗ ██╗ ████████╗ ██████╗ █████╗ ███████╗ ████████╗
|
|
490
|
+
██╔════╝ ██║ ╚══██╔══╝ ██╔════╝ ██╔══██╗ ██╔════╝ ╚══██╔══╝
|
|
491
|
+
██║ ███╗ ██║ ██║ ██║ ███████║ ███████╗ ██║
|
|
492
|
+
██║ ██║ ██║ ██║ ██║ ██╔══██║ ╚════██║ ██║
|
|
493
|
+
╚██████╔╝ ██║ ██║ ╚██████╗ ██║ ██║ ███████║ ██║
|
|
494
|
+
╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝ ╚═╝ </pre>
|
|
495
|
+
|
|
496
|
+
<div style="text-align: left; max-width: 680px; width: 100%;">
|
|
497
|
+
<h1 class="hero-tagline">
|
|
498
|
+
> You shipped something.<br>
|
|
499
|
+
> Nobody knows.<br>
|
|
500
|
+
> Ctrl+Shift+P fixes that.
|
|
501
|
+
</h1>
|
|
502
|
+
<br>
|
|
503
|
+
<p class="hero-subline">
|
|
504
|
+
// capture → generate → publish. under 60 seconds.<br>
|
|
505
|
+
// privacy-first. runs local. no always-on recording.
|
|
506
|
+
</p>
|
|
507
|
+
</div>
|
|
508
|
+
|
|
509
|
+
<div class="hero-ctas">
|
|
510
|
+
<a href="/app" class="btn-brutalist btn-primary-brutalist pulse-border">[LAUNCH_APP ↗]</a>
|
|
511
|
+
<a href="#pricing" class="btn-brutalist">[DOWNLOAD_BETA ↓]</a>
|
|
512
|
+
<a href="https://github.com/drizzy765/gitcast" target="_blank" class="btn-brutalist">[VIEW_ON_GITHUB ↗]</a>
|
|
513
|
+
</div>
|
|
514
|
+
|
|
515
|
+
<!-- CLI Flow Terminal Simulator -->
|
|
516
|
+
<div class="ascii-box terminal-emulator">
|
|
517
|
+
<div class="ascii-box-header">
|
|
518
|
+
<span class="ascii-box-title">┌─ terminal</span>
|
|
519
|
+
<span class="ascii-box-line"></span>
|
|
520
|
+
<span class="ascii-box-limit">─┐</span>
|
|
521
|
+
</div>
|
|
522
|
+
<div class="ascii-box-body term-body" id="term-body">
|
|
523
|
+
<!-- Javascript loops the dynamic print here -->
|
|
524
|
+
</div>
|
|
525
|
+
</div>
|
|
526
|
+
|
|
527
|
+
<a href="#problem" class="scroll-indicator">[SCROLL_DOWN ↓]</a>
|
|
528
|
+
</header>
|
|
529
|
+
|
|
530
|
+
<!-- Section 2: The Problem -->
|
|
531
|
+
<section class="container problem-section fade-in-section" id="problem">
|
|
532
|
+
<div class="ascii-box">
|
|
533
|
+
<div class="ascii-box-header">
|
|
534
|
+
<span class="ascii-box-title">┌─ THE_PROBLEM</span>
|
|
535
|
+
<span class="ascii-box-line"></span>
|
|
536
|
+
<span class="ascii-box-limit">─┐</span>
|
|
537
|
+
</div>
|
|
538
|
+
<div class="ascii-box-body problem-content">
|
|
539
|
+
you fix a bug at 2am.<br>
|
|
540
|
+
it took 6 hours.<br>
|
|
541
|
+
you close the laptop.<br>
|
|
542
|
+
nobody ever knows it happened.<br>
|
|
543
|
+
<br>
|
|
544
|
+
<span style="color: var(--text-secondary);">// this is the content gap killing</span><br>
|
|
545
|
+
<span style="color: var(--text-secondary);">// developer personal brands.</span>
|
|
546
|
+
</div>
|
|
547
|
+
</div>
|
|
548
|
+
|
|
549
|
+
<div class="problem-cards-grid">
|
|
550
|
+
<div class="problem-card">
|
|
551
|
+
<div class="problem-card-header">[!!] CONTEXT_SWITCHING</div>
|
|
552
|
+
<div class="problem-card-desc">stopping to write a post kills your flow</div>
|
|
553
|
+
</div>
|
|
554
|
+
<div class="problem-card">
|
|
555
|
+
<div class="problem-card-header">[!!] ALWAYS_ON_RECORDERS</div>
|
|
556
|
+
<div class="problem-card-desc">privacy risk. kills battery. creepy.</div>
|
|
557
|
+
</div>
|
|
558
|
+
<div class="problem-card">
|
|
559
|
+
<div class="problem-card-header">[!!] CONTEXT_LOSS</div>
|
|
560
|
+
<div class="problem-card-desc">by the time you remember the detail is gone.</div>
|
|
561
|
+
</div>
|
|
562
|
+
</div>
|
|
563
|
+
</section>
|
|
564
|
+
|
|
565
|
+
<!-- Section 3: The Solution -->
|
|
566
|
+
<section class="container solution-section fade-in-section" id="solution">
|
|
567
|
+
<div class="ascii-box" style="margin-bottom: 12px;">
|
|
568
|
+
<div class="ascii-box-header">
|
|
569
|
+
<span class="ascii-box-title">┌─ THE_SOLUTION</span>
|
|
570
|
+
<span class="ascii-box-line"></span>
|
|
571
|
+
<span class="ascii-box-limit">─┐</span>
|
|
572
|
+
</div>
|
|
573
|
+
<div class="ascii-box-body" style="border-bottom: none; padding-bottom: 0;">
|
|
574
|
+
<p style="font-size: var(--text-lg); font-weight: bold;">how it works:</p>
|
|
575
|
+
</div>
|
|
576
|
+
</div>
|
|
577
|
+
|
|
578
|
+
<div class="steps-container">
|
|
579
|
+
<div class="step-row">
|
|
580
|
+
<div class="step-num">01.</div>
|
|
581
|
+
<div class="step-details">
|
|
582
|
+
<h3>TRIGGER</h3>
|
|
583
|
+
<p>press ctrl+shift+p at any moment of a win or struggle. that's it. don't stop coding.</p>
|
|
584
|
+
</div>
|
|
585
|
+
</div>
|
|
586
|
+
|
|
587
|
+
<div class="step-row">
|
|
588
|
+
<div class="step-num">02.</div>
|
|
589
|
+
<div class="step-details">
|
|
590
|
+
<h3>CAPTURE</h3>
|
|
591
|
+
<p>app grabs active window screenshot + git diff. ocr runs locally. nothing leaves your machine yet.</p>
|
|
592
|
+
<span class="step-tag">[privacy-first by design]</span>
|
|
593
|
+
</div>
|
|
594
|
+
</div>
|
|
595
|
+
|
|
596
|
+
<div class="step-row">
|
|
597
|
+
<div class="step-num">03.</div>
|
|
598
|
+
<div class="step-details">
|
|
599
|
+
<h3>CONTEXT</h3>
|
|
600
|
+
<p>a minimal terminal prompt asks one question:<br>
|
|
601
|
+
<span style="color: var(--accent-green); font-weight: bold;">> what was the struggle or win? _</span></p>
|
|
602
|
+
<p style="margin-top: 4px;">type a raw thought. hit enter. done.</p>
|
|
603
|
+
</div>
|
|
604
|
+
</div>
|
|
605
|
+
|
|
606
|
+
<div class="step-row">
|
|
607
|
+
<div class="step-num">04.</div>
|
|
608
|
+
<div class="step-details">
|
|
609
|
+
<h3>GENERATE</h3>
|
|
610
|
+
<p>groq + openrouter generate 4 post variations in parallel:</p>
|
|
611
|
+
<span class="step-tag">[X_POST] [LINKEDIN] [PR_DESC] [QUICK_WIN]</span>
|
|
612
|
+
<p style="margin-top: 4px;">task-specific models. under 4 seconds.</p>
|
|
613
|
+
</div>
|
|
614
|
+
</div>
|
|
615
|
+
|
|
616
|
+
<div class="step-row">
|
|
617
|
+
<div class="step-num">05.</div>
|
|
618
|
+
<div class="step-details">
|
|
619
|
+
<h3>PUBLISH</h3>
|
|
620
|
+
<p>review in the draft room. refine via ai chat. one click to x. done.</p>
|
|
621
|
+
</div>
|
|
622
|
+
</div>
|
|
623
|
+
</div>
|
|
624
|
+
</section>
|
|
625
|
+
|
|
626
|
+
<!-- Section 4: Features Grid -->
|
|
627
|
+
<section class="container features-section fade-in-section" id="features">
|
|
628
|
+
<div class="ascii-box" style="margin-bottom: 12px;">
|
|
629
|
+
<div class="ascii-box-header">
|
|
630
|
+
<span class="ascii-box-title">┌─ FEATURES_MANIFESTO</span>
|
|
631
|
+
<span class="ascii-box-line"></span>
|
|
632
|
+
<span class="ascii-box-limit">─┐</span>
|
|
633
|
+
</div>
|
|
634
|
+
</div>
|
|
635
|
+
|
|
636
|
+
<div class="features-grid">
|
|
637
|
+
<div class="feature-card">
|
|
638
|
+
<div class="feature-title">[BYOK — YOUR_KEYS]</div>
|
|
639
|
+
<div class="feature-desc">
|
|
640
|
+
Add your own AI keys (Groq, Gemini, Kimi, OpenRouter). No middleman, pay exactly what you use. Zero markups.
|
|
641
|
+
</div>
|
|
642
|
+
</div>
|
|
643
|
+
<div class="feature-card">
|
|
644
|
+
<div class="feature-title">[MULTI_SHOT_CAPTURE]</div>
|
|
645
|
+
<div class="feature-desc">
|
|
646
|
+
Capture up to 6 screenshots sequentially. Perfect for capturing multi-step debugging or design progression.
|
|
647
|
+
</div>
|
|
648
|
+
</div>
|
|
649
|
+
<div class="feature-card">
|
|
650
|
+
<div class="feature-title">[4_POST_FORMATS]</div>
|
|
651
|
+
<div class="feature-desc">
|
|
652
|
+
Generate X posts, LinkedIn updates, PR descriptions, and long-form articles simultaneously.
|
|
653
|
+
</div>
|
|
654
|
+
</div>
|
|
655
|
+
<div class="feature-card">
|
|
656
|
+
<div class="feature-title">[SPRINT_MODE]</div>
|
|
657
|
+
<div class="feature-desc">
|
|
658
|
+
Code heads-down. Let Gitcast silently capture your progress and write a comprehensive narrative when you resurface.
|
|
659
|
+
</div>
|
|
660
|
+
</div>
|
|
661
|
+
<div class="feature-card">
|
|
662
|
+
<div class="feature-title">[VIRAL_INTELLIGENCE]</div>
|
|
663
|
+
<div class="feature-desc">
|
|
664
|
+
Advanced pattern matching learns your voice and incorporates highly engaging templates into your drafts.
|
|
665
|
+
</div>
|
|
666
|
+
</div>
|
|
667
|
+
<div class="feature-card">
|
|
668
|
+
<div class="feature-title">[OPEN_SOURCE_FREE]</div>
|
|
669
|
+
<div class="feature-desc">
|
|
670
|
+
Fully open-source under the permissive MIT license. Privacy-first, local OCR, nothing leaves your system.
|
|
671
|
+
</div>
|
|
672
|
+
</div>
|
|
673
|
+
</div>
|
|
674
|
+
</section>
|
|
675
|
+
|
|
676
|
+
<!-- Section 5: Social Proof Placeholder & Waitlist -->
|
|
677
|
+
<section class="container social-section fade-in-section" id="social">
|
|
678
|
+
<div class="ascii-box">
|
|
679
|
+
<div class="ascii-box-header">
|
|
680
|
+
<span class="ascii-box-title">┌─ WHAT_DEVS_ARE_SAYING</span>
|
|
681
|
+
<span class="ascii-box-line"></span>
|
|
682
|
+
<span class="ascii-box-limit">─┐</span>
|
|
683
|
+
</div>
|
|
684
|
+
<div class="ascii-box-body" style="padding: 32px 24px;">
|
|
685
|
+
<p style="color: var(--text-secondary);">// testimonials will appear here</p>
|
|
686
|
+
<p style="color: var(--text-secondary); margin-top: 4px;">// be the first: download the beta</p>
|
|
687
|
+
</div>
|
|
688
|
+
</div>
|
|
689
|
+
|
|
690
|
+
<div class="waitlist-container" id="waitlist">
|
|
691
|
+
<div class="sidebar-section-label" style="text-align: left; margin-bottom: 8px;">GET_EARLY_BETA_ACCESS:</div>
|
|
692
|
+
<form onsubmit="submitWaitlist(event)">
|
|
693
|
+
<div class="waitlist-box">
|
|
694
|
+
<span class="waitlist-prompt">> </span>
|
|
695
|
+
<input type="email" id="waitlist-email" placeholder="enter_email@domain.com" class="waitlist-input" required>
|
|
696
|
+
<button type="submit" class="waitlist-btn">[JOIN →]</button>
|
|
697
|
+
</div>
|
|
698
|
+
</form>
|
|
699
|
+
<div class="waitlist-status-message" id="waitlist-msg"></div>
|
|
700
|
+
</div>
|
|
701
|
+
|
|
702
|
+
<div style="margin-top: 24px;">
|
|
703
|
+
<a href="#waitlist" class="btn-brutalist btn-primary-brutalist">[JOIN_BETA_WAITLIST →]</a>
|
|
704
|
+
</div>
|
|
705
|
+
</section>
|
|
706
|
+
|
|
707
|
+
<!-- Section 6: Pricing -->
|
|
708
|
+
<section class="container pricing-section fade-in-section" id="pricing">
|
|
709
|
+
<div class="ascii-box" style="margin-bottom: 12px;">
|
|
710
|
+
<div class="ascii-box-header">
|
|
711
|
+
<span class="ascii-box-title">┌─ PRICING_TERMS</span>
|
|
712
|
+
<span class="ascii-box-line"></span>
|
|
713
|
+
<span class="ascii-box-limit">─┐</span>
|
|
714
|
+
</div>
|
|
715
|
+
</div>
|
|
716
|
+
|
|
717
|
+
<div class="table-responsive">
|
|
718
|
+
<table class="terminal-table">
|
|
719
|
+
<thead>
|
|
720
|
+
<tr>
|
|
721
|
+
<th style="width: 50%;">[FREE — BYOK]</th>
|
|
722
|
+
<th style="width: 50%;">[PRO] $8/mo — COMING SOON</th>
|
|
723
|
+
</tr>
|
|
724
|
+
</thead>
|
|
725
|
+
<tbody>
|
|
726
|
+
<tr>
|
|
727
|
+
<td>Use your own API keys (Groq, OpenRouter, Gemini, etc.)</td>
|
|
728
|
+
<td>Managed high-speed AI access (no API keys required)</td>
|
|
729
|
+
</tr>
|
|
730
|
+
<tr>
|
|
731
|
+
<td>Up to 6 screenshots per capture session</td>
|
|
732
|
+
<td>Unlimited sequential screenshots</td>
|
|
733
|
+
</tr>
|
|
734
|
+
<tr>
|
|
735
|
+
<td>All 4 post formats (X, LinkedIn, PR, Article)</td>
|
|
736
|
+
<td>All formats + custom formatting styles</td>
|
|
737
|
+
</tr>
|
|
738
|
+
<tr>
|
|
739
|
+
<td>Local Tesseract OCR engine (100% private)</td>
|
|
740
|
+
<td>Advanced cloud vision & OCR parsing</td>
|
|
741
|
+
</tr>
|
|
742
|
+
<tr>
|
|
743
|
+
<td>Sprint Mode & Local History logs</td>
|
|
744
|
+
<td>Cloud backup, web editing dashboard, team sharing</td>
|
|
745
|
+
</tr>
|
|
746
|
+
<tr>
|
|
747
|
+
<td>MIT Licensed Open-Source</td>
|
|
748
|
+
<td>Priority support & team workspaces</td>
|
|
749
|
+
</tr>
|
|
750
|
+
<tr>
|
|
751
|
+
<td>
|
|
752
|
+
<a href="/app" class="btn-brutalist" style="padding: 6px 12px; font-size: 11px;">[LAUNCH_APP ↗]</a>
|
|
753
|
+
</td>
|
|
754
|
+
<td>
|
|
755
|
+
<a href="#waitlist" class="btn-brutalist btn-primary-brutalist" style="padding: 6px 12px; font-size: 11px;">[GET_NOTIFIED ↗]</a>
|
|
756
|
+
</td>
|
|
757
|
+
</tr>
|
|
758
|
+
</tbody>
|
|
759
|
+
</table>
|
|
760
|
+
</div>
|
|
761
|
+
<p style="font-size: var(--text-xs); color: var(--text-secondary); margin-top: 8px;">
|
|
762
|
+
// all plans include: local OCR, git diff, privacy-first
|
|
763
|
+
</p>
|
|
764
|
+
</section>
|
|
765
|
+
|
|
766
|
+
<!-- Section 7: Footer -->
|
|
767
|
+
<footer class="container footer-section fade-in-section">
|
|
768
|
+
<div class="ascii-box">
|
|
769
|
+
<div class="ascii-box-header">
|
|
770
|
+
<span class="ascii-box-title">┌─ GITCAST v1.0</span>
|
|
771
|
+
<span class="ascii-box-line"></span>
|
|
772
|
+
<span class="ascii-box-limit">─┐</span>
|
|
773
|
+
</div>
|
|
774
|
+
<div class="ascii-box-body footer-content">
|
|
775
|
+
<p>built by @drizzy765 · open source · MIT license</p>
|
|
776
|
+
<div class="footer-links">
|
|
777
|
+
<a href="https://github.com/drizzy765/gitcast" target="_blank">[github ↗]</a>
|
|
778
|
+
<a href="https://twitter.com/drizzy765" target="_blank">[twitter ↗]</a>
|
|
779
|
+
<a href="#pricing">[pricing ↓]</a>
|
|
780
|
+
</div>
|
|
781
|
+
<p style="color: var(--accent-green); font-weight: bold; margin-top: 8px;">
|
|
782
|
+
// shipping is the only metric that matters
|
|
783
|
+
</p>
|
|
784
|
+
</div>
|
|
785
|
+
</div>
|
|
786
|
+
</footer>
|
|
787
|
+
|
|
788
|
+
<script>
|
|
789
|
+
// --- Simulated Terminal stream flow ---
|
|
790
|
+
const terminalLines = [
|
|
791
|
+
"$ gitcast start",
|
|
792
|
+
"> [OK] hotkey registered: ctrl+shift+p",
|
|
793
|
+
"> [OK] capture engine ready",
|
|
794
|
+
"> [OK] groq connected",
|
|
795
|
+
"> listening...",
|
|
796
|
+
"",
|
|
797
|
+
"[HOTKEY DETECTED]",
|
|
798
|
+
"> capturing active window...",
|
|
799
|
+
"> ocr confidence: 72.4%",
|
|
800
|
+
"> git diff: 47 lines changed",
|
|
801
|
+
"> generating 4 post variations...",
|
|
802
|
+
"> [OK] deep_tech: ready",
|
|
803
|
+
"> [OK] quick_win: ready",
|
|
804
|
+
"> [OK] linkedin: ready",
|
|
805
|
+
"> opening draft room...",
|
|
806
|
+
"> published to @yourtwitterhandle ✓"
|
|
807
|
+
];
|
|
808
|
+
|
|
809
|
+
const termBody = document.getElementById('term-body');
|
|
810
|
+
let lineIdx = 0;
|
|
811
|
+
|
|
812
|
+
function printLines() {
|
|
813
|
+
if (!termBody) return;
|
|
814
|
+
termBody.innerHTML = '';
|
|
815
|
+
lineIdx = 0;
|
|
816
|
+
|
|
817
|
+
function showNextLine() {
|
|
818
|
+
if (lineIdx < terminalLines.length) {
|
|
819
|
+
const line = terminalLines[lineIdx];
|
|
820
|
+
const div = document.createElement('div');
|
|
821
|
+
div.style.minHeight = '1.6em';
|
|
822
|
+
termBody.appendChild(div);
|
|
823
|
+
|
|
824
|
+
let charIdx = 0;
|
|
825
|
+
function typeChar() {
|
|
826
|
+
if (charIdx < line.length) {
|
|
827
|
+
div.innerHTML = line.substring(0, charIdx + 1) + '<span class="cursor-blink">▋</span>';
|
|
828
|
+
charIdx++;
|
|
829
|
+
setTimeout(typeChar, 12);
|
|
830
|
+
} else {
|
|
831
|
+
div.innerHTML = line;
|
|
832
|
+
lineIdx++;
|
|
833
|
+
setTimeout(showNextLine, 120);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
typeChar();
|
|
837
|
+
} else {
|
|
838
|
+
// Loop typing simulation every 8 seconds
|
|
839
|
+
setTimeout(printLines, 8000);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
showNextLine();
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// --- Intersection Observer for Scroll Animations ---
|
|
847
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
848
|
+
// Typewriter mobile screen optimization
|
|
849
|
+
if (window.innerWidth <= 768) {
|
|
850
|
+
termBody.innerHTML = terminalLines.map(l => `<div style="min-height: 1.6em;">${l}</div>`).join('');
|
|
851
|
+
} else {
|
|
852
|
+
printLines();
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// Bind section fade-in observations
|
|
856
|
+
const observer = new IntersectionObserver((entries) => {
|
|
857
|
+
entries.forEach(entry => {
|
|
858
|
+
if (entry.isIntersecting) {
|
|
859
|
+
entry.target.classList.add('is-visible');
|
|
860
|
+
observer.unobserve(entry.target);
|
|
861
|
+
}
|
|
862
|
+
});
|
|
863
|
+
}, {
|
|
864
|
+
threshold: 0.15
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
document.querySelectorAll('.fade-in-section').forEach(section => {
|
|
868
|
+
observer.observe(section);
|
|
869
|
+
});
|
|
870
|
+
|
|
871
|
+
// Smooth scrolling to anchors
|
|
872
|
+
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
873
|
+
anchor.addEventListener('click', function (e) {
|
|
874
|
+
e.preventDefault();
|
|
875
|
+
const target = document.querySelector(this.getAttribute('href'));
|
|
876
|
+
if (target) {
|
|
877
|
+
target.scrollIntoView({
|
|
878
|
+
behavior: 'smooth'
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
});
|
|
882
|
+
});
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
// --- Waitlist asynchronous Form Submit ---
|
|
886
|
+
async function submitWaitlist(e) {
|
|
887
|
+
if (e) e.preventDefault();
|
|
888
|
+
const emailInput = document.getElementById('waitlist-email');
|
|
889
|
+
const msgEl = document.getElementById('waitlist-msg');
|
|
890
|
+
if (!emailInput || !msgEl) return;
|
|
891
|
+
|
|
892
|
+
const email = emailInput.value.trim();
|
|
893
|
+
if (!email) {
|
|
894
|
+
msgEl.innerText = "[!!] email is required";
|
|
895
|
+
msgEl.style.color = "var(--accent-red)";
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
msgEl.innerText = "[*] connecting to server...";
|
|
900
|
+
msgEl.style.color = "var(--accent-blue)";
|
|
901
|
+
|
|
902
|
+
try {
|
|
903
|
+
const res = await fetch('/api/waitlist', {
|
|
904
|
+
method: 'POST',
|
|
905
|
+
headers: { 'Content-Type': 'application/json' },
|
|
906
|
+
body: JSON.stringify({ email })
|
|
907
|
+
});
|
|
908
|
+
|
|
909
|
+
const data = await res.json();
|
|
910
|
+
if (res.status === 200 && data.success) {
|
|
911
|
+
msgEl.innerText = "[OK] you're on the list.";
|
|
912
|
+
msgEl.style.color = "var(--accent-green)";
|
|
913
|
+
emailInput.value = "";
|
|
914
|
+
} else {
|
|
915
|
+
msgEl.innerText = `[!!] ${data.detail || 'something went wrong. try again.'}`;
|
|
916
|
+
msgEl.style.color = "var(--accent-red)";
|
|
917
|
+
}
|
|
918
|
+
} catch (err) {
|
|
919
|
+
msgEl.innerText = "[!!] something went wrong. try again.";
|
|
920
|
+
msgEl.style.color = "var(--accent-red)";
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
</script>
|
|
924
|
+
</body>
|
|
925
|
+
</html>
|