@hustle-together/api-dev-tools 1.8.0 → 2.0.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 +45 -2
- package/demo/hustle-together/blog/gemini-vs-claude-widgets.html +957 -0
- package/demo/hustle-together/blog/interview-driven-api-development.html +1132 -0
- package/demo/hustle-together/blog/tdd-for-ai.html +982 -0
- package/demo/hustle-together/index.html +1279 -0
- package/demo/workflow-demo.html +881 -157
- package/hooks/enforce-interview.py +52 -2
- package/hooks/track-tool-use.py +51 -2
- package/package.json +1 -1
package/demo/workflow-demo.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>API Dev Tools -
|
|
6
|
+
<title>API Dev Tools - Interview-Driven API Development Demo</title>
|
|
7
7
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
|
|
8
8
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
|
|
9
9
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/TextPlugin.min.js"></script>
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
--dark-grey: #444;
|
|
26
26
|
--black: #0a0a0a;
|
|
27
27
|
--glow: rgba(255, 255, 255, 0.3);
|
|
28
|
+
--accent-red: #BA0C2F;
|
|
29
|
+
--accent-red-glow: rgba(186, 12, 47, 0.4);
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
body {
|
|
@@ -35,6 +37,439 @@
|
|
|
35
37
|
overflow-x: hidden;
|
|
36
38
|
}
|
|
37
39
|
|
|
40
|
+
/* ============================================
|
|
41
|
+
ANIMATED BACKGROUND
|
|
42
|
+
============================================ */
|
|
43
|
+
.background-pattern {
|
|
44
|
+
position: fixed;
|
|
45
|
+
top: 0;
|
|
46
|
+
left: 0;
|
|
47
|
+
width: 100%;
|
|
48
|
+
height: 100%;
|
|
49
|
+
pointer-events: none;
|
|
50
|
+
z-index: -1;
|
|
51
|
+
overflow: hidden;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.grid-svg {
|
|
55
|
+
width: 100%;
|
|
56
|
+
height: 100%;
|
|
57
|
+
opacity: 0.15;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.grid-line {
|
|
61
|
+
stroke: var(--grey);
|
|
62
|
+
stroke-width: 0.5;
|
|
63
|
+
fill: none;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* Floating particles */
|
|
67
|
+
.particles {
|
|
68
|
+
position: fixed;
|
|
69
|
+
top: 0;
|
|
70
|
+
left: 0;
|
|
71
|
+
width: 100%;
|
|
72
|
+
height: 100%;
|
|
73
|
+
pointer-events: none;
|
|
74
|
+
z-index: -1;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.particle {
|
|
78
|
+
position: absolute;
|
|
79
|
+
width: 4px;
|
|
80
|
+
height: 4px;
|
|
81
|
+
background: var(--grey);
|
|
82
|
+
opacity: 0.3;
|
|
83
|
+
border-radius: 50%;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.particle.square {
|
|
87
|
+
border-radius: 0;
|
|
88
|
+
border: 1px solid var(--grey);
|
|
89
|
+
background: transparent;
|
|
90
|
+
width: 8px;
|
|
91
|
+
height: 8px;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.particle.plus {
|
|
95
|
+
border-radius: 0;
|
|
96
|
+
background: transparent;
|
|
97
|
+
width: 12px;
|
|
98
|
+
height: 12px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.particle.plus::before,
|
|
102
|
+
.particle.plus::after {
|
|
103
|
+
content: '';
|
|
104
|
+
position: absolute;
|
|
105
|
+
background: var(--grey);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.particle.plus::before {
|
|
109
|
+
width: 12px;
|
|
110
|
+
height: 1px;
|
|
111
|
+
top: 5.5px;
|
|
112
|
+
left: 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.particle.plus::after {
|
|
116
|
+
width: 1px;
|
|
117
|
+
height: 12px;
|
|
118
|
+
left: 5.5px;
|
|
119
|
+
top: 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* X shape particle */
|
|
123
|
+
.particle.x-shape {
|
|
124
|
+
border-radius: 0;
|
|
125
|
+
background: transparent;
|
|
126
|
+
width: 14px;
|
|
127
|
+
height: 14px;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.particle.x-shape::before,
|
|
131
|
+
.particle.x-shape::after {
|
|
132
|
+
content: '';
|
|
133
|
+
position: absolute;
|
|
134
|
+
background: var(--grey);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.particle.x-shape::before {
|
|
138
|
+
width: 14px;
|
|
139
|
+
height: 1px;
|
|
140
|
+
top: 6.5px;
|
|
141
|
+
left: 0;
|
|
142
|
+
transform: rotate(45deg);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.particle.x-shape::after {
|
|
146
|
+
width: 14px;
|
|
147
|
+
height: 1px;
|
|
148
|
+
top: 6.5px;
|
|
149
|
+
left: 0;
|
|
150
|
+
transform: rotate(-45deg);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* Line/dash particle */
|
|
154
|
+
.particle.line {
|
|
155
|
+
border-radius: 0;
|
|
156
|
+
width: 20px;
|
|
157
|
+
height: 1px;
|
|
158
|
+
background: var(--grey);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.particle.line-v {
|
|
162
|
+
border-radius: 0;
|
|
163
|
+
width: 1px;
|
|
164
|
+
height: 20px;
|
|
165
|
+
background: var(--grey);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/* Circle outline particle */
|
|
169
|
+
.particle.circle-outline {
|
|
170
|
+
width: 16px;
|
|
171
|
+
height: 16px;
|
|
172
|
+
border-radius: 50%;
|
|
173
|
+
background: transparent;
|
|
174
|
+
border: 1px solid var(--grey);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* Triangle particle */
|
|
178
|
+
.particle.triangle {
|
|
179
|
+
width: 0;
|
|
180
|
+
height: 0;
|
|
181
|
+
background: transparent;
|
|
182
|
+
border-left: 6px solid transparent;
|
|
183
|
+
border-right: 6px solid transparent;
|
|
184
|
+
border-bottom: 10px solid var(--grey);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* Cursor glow effect */
|
|
188
|
+
.cursor-glow {
|
|
189
|
+
position: fixed;
|
|
190
|
+
width: 300px;
|
|
191
|
+
height: 300px;
|
|
192
|
+
background: radial-gradient(circle, rgba(255,255,255,0.08) 0%, transparent 70%);
|
|
193
|
+
pointer-events: none;
|
|
194
|
+
z-index: 0;
|
|
195
|
+
transform: translate(-50%, -50%);
|
|
196
|
+
transition: opacity 0.3s;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* Scanlines overlay */
|
|
200
|
+
.scanlines {
|
|
201
|
+
position: fixed;
|
|
202
|
+
top: 0;
|
|
203
|
+
left: 0;
|
|
204
|
+
width: 100%;
|
|
205
|
+
height: 100%;
|
|
206
|
+
pointer-events: none;
|
|
207
|
+
z-index: 9999;
|
|
208
|
+
background: repeating-linear-gradient(
|
|
209
|
+
0deg,
|
|
210
|
+
transparent,
|
|
211
|
+
transparent 2px,
|
|
212
|
+
rgba(0, 0, 0, 0.1) 2px,
|
|
213
|
+
rgba(0, 0, 0, 0.1) 4px
|
|
214
|
+
);
|
|
215
|
+
opacity: 0.3;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* Animated corner decorations */
|
|
219
|
+
.corner-decoration {
|
|
220
|
+
position: fixed;
|
|
221
|
+
width: 60px;
|
|
222
|
+
height: 60px;
|
|
223
|
+
border: 1px dashed var(--dark-grey);
|
|
224
|
+
opacity: 0.4;
|
|
225
|
+
z-index: 1;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.corner-decoration.top-left {
|
|
229
|
+
top: 20px;
|
|
230
|
+
left: 20px;
|
|
231
|
+
border-right: none;
|
|
232
|
+
border-bottom: none;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.corner-decoration.top-right {
|
|
236
|
+
top: 20px;
|
|
237
|
+
right: 80px;
|
|
238
|
+
border-left: none;
|
|
239
|
+
border-bottom: none;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.corner-decoration.bottom-left {
|
|
243
|
+
bottom: 20px;
|
|
244
|
+
left: 20px;
|
|
245
|
+
border-right: none;
|
|
246
|
+
border-top: none;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.corner-decoration.bottom-right {
|
|
250
|
+
bottom: 20px;
|
|
251
|
+
right: 20px;
|
|
252
|
+
border-left: none;
|
|
253
|
+
border-top: none;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/* Visual flow lines between sections */
|
|
257
|
+
.flow-connector-line {
|
|
258
|
+
position: absolute;
|
|
259
|
+
width: 2px;
|
|
260
|
+
background: linear-gradient(to bottom, transparent, var(--dark-grey), transparent);
|
|
261
|
+
left: 50%;
|
|
262
|
+
bottom: -60px;
|
|
263
|
+
height: 60px;
|
|
264
|
+
opacity: 0.3;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* Status badge animations */
|
|
268
|
+
.status-badge {
|
|
269
|
+
display: inline-flex;
|
|
270
|
+
align-items: center;
|
|
271
|
+
gap: 8px;
|
|
272
|
+
padding: 6px 14px;
|
|
273
|
+
border: 1px dashed var(--grey);
|
|
274
|
+
font-size: 0.75rem;
|
|
275
|
+
text-transform: uppercase;
|
|
276
|
+
letter-spacing: 2px;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.status-badge .pulse {
|
|
280
|
+
width: 8px;
|
|
281
|
+
height: 8px;
|
|
282
|
+
border-radius: 50%;
|
|
283
|
+
background: var(--grey);
|
|
284
|
+
animation: pulse 2s infinite;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.status-badge.active .pulse {
|
|
288
|
+
background: var(--accent-red);
|
|
289
|
+
box-shadow: 0 0 10px var(--accent-red);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
@keyframes pulse {
|
|
293
|
+
0%, 100% { transform: scale(1); opacity: 1; }
|
|
294
|
+
50% { transform: scale(1.2); opacity: 0.5; }
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/* Visual data flow diagram */
|
|
298
|
+
.data-flow {
|
|
299
|
+
display: flex;
|
|
300
|
+
align-items: center;
|
|
301
|
+
justify-content: center;
|
|
302
|
+
gap: 20px;
|
|
303
|
+
margin: 30px 0;
|
|
304
|
+
flex-wrap: wrap;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.data-node {
|
|
308
|
+
border: 1px dashed var(--grey);
|
|
309
|
+
padding: 15px 25px;
|
|
310
|
+
text-align: center;
|
|
311
|
+
position: relative;
|
|
312
|
+
min-width: 120px;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.data-node-icon {
|
|
316
|
+
font-size: 1.5rem;
|
|
317
|
+
margin-bottom: 8px;
|
|
318
|
+
display: block;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.data-node-label {
|
|
322
|
+
font-size: 0.75rem;
|
|
323
|
+
text-transform: uppercase;
|
|
324
|
+
letter-spacing: 1px;
|
|
325
|
+
color: var(--grey);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.data-arrow {
|
|
329
|
+
color: var(--grey);
|
|
330
|
+
font-size: 1.5rem;
|
|
331
|
+
animation: arrowPulse 1.5s infinite;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
@keyframes arrowPulse {
|
|
335
|
+
0%, 100% { opacity: 0.3; transform: translateX(0); }
|
|
336
|
+
50% { opacity: 1; transform: translateX(5px); }
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/* Visual checkmarks for completed items */
|
|
340
|
+
.visual-check {
|
|
341
|
+
display: inline-flex;
|
|
342
|
+
align-items: center;
|
|
343
|
+
justify-content: center;
|
|
344
|
+
width: 24px;
|
|
345
|
+
height: 24px;
|
|
346
|
+
border: 2px solid var(--grey);
|
|
347
|
+
margin-right: 12px;
|
|
348
|
+
font-size: 0.8rem;
|
|
349
|
+
transition: all 0.3s;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.visual-check.checked {
|
|
353
|
+
border-color: var(--accent-red);
|
|
354
|
+
background: rgba(186, 12, 47, 0.2);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.visual-check.checked::after {
|
|
358
|
+
content: '✓';
|
|
359
|
+
color: var(--accent-red);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/* Animated underline effect */
|
|
363
|
+
.highlight-underline {
|
|
364
|
+
position: relative;
|
|
365
|
+
display: inline-block;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.highlight-underline::after {
|
|
369
|
+
content: '';
|
|
370
|
+
position: absolute;
|
|
371
|
+
bottom: -4px;
|
|
372
|
+
left: 0;
|
|
373
|
+
width: 0;
|
|
374
|
+
height: 2px;
|
|
375
|
+
background: var(--accent-red);
|
|
376
|
+
transition: width 0.3s ease;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.highlight-underline:hover::after {
|
|
380
|
+
width: 100%;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/* Visual timeline indicator */
|
|
384
|
+
.timeline-indicator {
|
|
385
|
+
position: absolute;
|
|
386
|
+
left: -40px;
|
|
387
|
+
top: 0;
|
|
388
|
+
bottom: 0;
|
|
389
|
+
width: 2px;
|
|
390
|
+
background: var(--dark-grey);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.timeline-indicator::before {
|
|
394
|
+
content: '';
|
|
395
|
+
position: absolute;
|
|
396
|
+
top: 50%;
|
|
397
|
+
left: -4px;
|
|
398
|
+
width: 10px;
|
|
399
|
+
height: 10px;
|
|
400
|
+
border: 2px solid var(--grey);
|
|
401
|
+
border-radius: 50%;
|
|
402
|
+
background: var(--black);
|
|
403
|
+
transform: translateY(-50%);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.timeline-indicator.active::before {
|
|
407
|
+
border-color: var(--accent-red);
|
|
408
|
+
box-shadow: 0 0 10px var(--accent-red-glow);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/* Animated typing indicator */
|
|
412
|
+
.typing-indicator {
|
|
413
|
+
display: inline-flex;
|
|
414
|
+
gap: 4px;
|
|
415
|
+
padding: 10px 15px;
|
|
416
|
+
background: rgba(255,255,255,0.03);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
.typing-indicator span {
|
|
420
|
+
width: 6px;
|
|
421
|
+
height: 6px;
|
|
422
|
+
background: var(--grey);
|
|
423
|
+
border-radius: 50%;
|
|
424
|
+
animation: typing 1.4s infinite both;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.typing-indicator span:nth-child(2) { animation-delay: 0.2s; }
|
|
428
|
+
.typing-indicator span:nth-child(3) { animation-delay: 0.4s; }
|
|
429
|
+
|
|
430
|
+
@keyframes typing {
|
|
431
|
+
0%, 100% { transform: translateY(0); opacity: 0.3; }
|
|
432
|
+
50% { transform: translateY(-8px); opacity: 1; }
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/* Phase connection arrows */
|
|
436
|
+
.phase-arrow {
|
|
437
|
+
display: none;
|
|
438
|
+
position: absolute;
|
|
439
|
+
right: -22px;
|
|
440
|
+
top: 50%;
|
|
441
|
+
transform: translateY(-50%);
|
|
442
|
+
color: var(--dark-grey);
|
|
443
|
+
font-size: 1rem;
|
|
444
|
+
z-index: 2;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.phase-box:not(:nth-child(5n)) .phase-arrow {
|
|
448
|
+
display: block;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/* Glowing border effect for active elements */
|
|
452
|
+
.glow-border {
|
|
453
|
+
position: relative;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.glow-border::before {
|
|
457
|
+
content: '';
|
|
458
|
+
position: absolute;
|
|
459
|
+
top: -2px;
|
|
460
|
+
left: -2px;
|
|
461
|
+
right: -2px;
|
|
462
|
+
bottom: -2px;
|
|
463
|
+
background: linear-gradient(45deg, transparent, var(--white), transparent);
|
|
464
|
+
opacity: 0;
|
|
465
|
+
transition: opacity 0.3s;
|
|
466
|
+
z-index: -1;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
.glow-border:hover::before {
|
|
470
|
+
opacity: 0.1;
|
|
471
|
+
}
|
|
472
|
+
|
|
38
473
|
/* Navigation */
|
|
39
474
|
.nav {
|
|
40
475
|
position: fixed;
|
|
@@ -56,9 +491,10 @@
|
|
|
56
491
|
}
|
|
57
492
|
|
|
58
493
|
.nav-btn:hover {
|
|
59
|
-
background: var(--
|
|
60
|
-
color:
|
|
61
|
-
|
|
494
|
+
background: var(--accent-red);
|
|
495
|
+
color: #fff;
|
|
496
|
+
border-color: var(--accent-red);
|
|
497
|
+
box-shadow: 0 0 15px var(--accent-red-glow);
|
|
62
498
|
}
|
|
63
499
|
|
|
64
500
|
/* Progress indicator */
|
|
@@ -67,7 +503,7 @@
|
|
|
67
503
|
top: 0;
|
|
68
504
|
left: 0;
|
|
69
505
|
height: 3px;
|
|
70
|
-
background: var(--
|
|
506
|
+
background: var(--accent-red);
|
|
71
507
|
width: 0%;
|
|
72
508
|
z-index: 1001;
|
|
73
509
|
}
|
|
@@ -90,6 +526,10 @@
|
|
|
90
526
|
position: relative;
|
|
91
527
|
max-width: 1000px;
|
|
92
528
|
width: 100%;
|
|
529
|
+
/* Blurred glass backdrop so boxes don't interfere with background animation */
|
|
530
|
+
background: rgba(10, 10, 10, 0.85);
|
|
531
|
+
backdrop-filter: blur(12px);
|
|
532
|
+
-webkit-backdrop-filter: blur(12px);
|
|
93
533
|
}
|
|
94
534
|
|
|
95
535
|
.ascii-border::before {
|
|
@@ -312,8 +752,8 @@
|
|
|
312
752
|
}
|
|
313
753
|
|
|
314
754
|
.gap-item:hover {
|
|
315
|
-
border-color: var(--
|
|
316
|
-
box-shadow: 0 0 25px
|
|
755
|
+
border-color: var(--accent-red);
|
|
756
|
+
box-shadow: 0 0 25px var(--accent-red-glow);
|
|
317
757
|
}
|
|
318
758
|
|
|
319
759
|
.gap-item::before {
|
|
@@ -322,7 +762,7 @@
|
|
|
322
762
|
left: -35px;
|
|
323
763
|
top: 50%;
|
|
324
764
|
transform: translateY(-50%);
|
|
325
|
-
color: var(--
|
|
765
|
+
color: var(--accent-red);
|
|
326
766
|
font-size: 1.2rem;
|
|
327
767
|
}
|
|
328
768
|
|
|
@@ -381,8 +821,8 @@
|
|
|
381
821
|
}
|
|
382
822
|
|
|
383
823
|
.solution-card:hover {
|
|
384
|
-
border-color: var(--
|
|
385
|
-
box-shadow: 0 0 25px
|
|
824
|
+
border-color: var(--accent-red);
|
|
825
|
+
box-shadow: 0 0 25px var(--accent-red-glow);
|
|
386
826
|
}
|
|
387
827
|
|
|
388
828
|
.solution-icon {
|
|
@@ -422,8 +862,9 @@
|
|
|
422
862
|
}
|
|
423
863
|
|
|
424
864
|
.flow-box:hover {
|
|
425
|
-
background: rgba(
|
|
426
|
-
box-shadow: 0 0 20px var(--glow);
|
|
865
|
+
background: rgba(186, 12, 47, 0.1);
|
|
866
|
+
box-shadow: 0 0 20px var(--accent-red-glow);
|
|
867
|
+
border-color: var(--accent-red);
|
|
427
868
|
}
|
|
428
869
|
|
|
429
870
|
.flow-arrow {
|
|
@@ -461,8 +902,8 @@
|
|
|
461
902
|
}
|
|
462
903
|
|
|
463
904
|
.hook-file:hover {
|
|
464
|
-
border-left-color: var(--
|
|
465
|
-
background: rgba(
|
|
905
|
+
border-left-color: var(--accent-red);
|
|
906
|
+
background: rgba(186, 12, 47, 0.1);
|
|
466
907
|
padding-left: 25px;
|
|
467
908
|
}
|
|
468
909
|
|
|
@@ -494,7 +935,8 @@
|
|
|
494
935
|
}
|
|
495
936
|
|
|
496
937
|
.result-blocked {
|
|
497
|
-
border-color: var(--
|
|
938
|
+
border-color: var(--accent-red);
|
|
939
|
+
color: var(--accent-red);
|
|
498
940
|
}
|
|
499
941
|
|
|
500
942
|
.result-allowed:hover, .result-blocked:hover {
|
|
@@ -523,14 +965,14 @@
|
|
|
523
965
|
}
|
|
524
966
|
|
|
525
967
|
.phase-box:hover {
|
|
526
|
-
border-color: var(--
|
|
527
|
-
box-shadow: 0 0 25px
|
|
968
|
+
border-color: var(--accent-red);
|
|
969
|
+
box-shadow: 0 0 25px var(--accent-red-glow);
|
|
528
970
|
transform: scale(1.02);
|
|
529
971
|
}
|
|
530
972
|
|
|
531
973
|
.phase-box.active {
|
|
532
|
-
border-color: var(--
|
|
533
|
-
background: rgba(
|
|
974
|
+
border-color: var(--accent-red);
|
|
975
|
+
background: rgba(186, 12, 47, 0.1);
|
|
534
976
|
}
|
|
535
977
|
|
|
536
978
|
.phase-number {
|
|
@@ -585,7 +1027,8 @@
|
|
|
585
1027
|
}
|
|
586
1028
|
|
|
587
1029
|
.walkthrough-step.active {
|
|
588
|
-
border-color: var(--
|
|
1030
|
+
border-color: var(--accent-red);
|
|
1031
|
+
box-shadow: 0 0 20px var(--accent-red-glow);
|
|
589
1032
|
}
|
|
590
1033
|
|
|
591
1034
|
.walkthrough-header {
|
|
@@ -692,10 +1135,10 @@
|
|
|
692
1135
|
}
|
|
693
1136
|
|
|
694
1137
|
.terminal-blocked {
|
|
695
|
-
color: var(--
|
|
696
|
-
border-left: 3px solid var(--
|
|
1138
|
+
color: var(--accent-red);
|
|
1139
|
+
border-left: 3px solid var(--accent-red);
|
|
697
1140
|
padding-left: 15px;
|
|
698
|
-
background: rgba(
|
|
1141
|
+
background: rgba(186, 12, 47, 0.1);
|
|
699
1142
|
}
|
|
700
1143
|
|
|
701
1144
|
.terminal-allowed {
|
|
@@ -746,10 +1189,11 @@
|
|
|
746
1189
|
}
|
|
747
1190
|
|
|
748
1191
|
.json-line.highlight {
|
|
749
|
-
background: rgba(
|
|
1192
|
+
background: rgba(186, 12, 47, 0.15);
|
|
750
1193
|
margin: 0 -25px;
|
|
751
1194
|
padding-left: 25px;
|
|
752
1195
|
padding-right: 25px;
|
|
1196
|
+
border-left: 2px solid var(--accent-red);
|
|
753
1197
|
}
|
|
754
1198
|
|
|
755
1199
|
.json-comment {
|
|
@@ -854,9 +1298,10 @@
|
|
|
854
1298
|
}
|
|
855
1299
|
|
|
856
1300
|
.credit-link:hover {
|
|
857
|
-
background: var(--
|
|
858
|
-
color:
|
|
859
|
-
|
|
1301
|
+
background: var(--accent-red);
|
|
1302
|
+
color: #fff;
|
|
1303
|
+
border-color: var(--accent-red);
|
|
1304
|
+
box-shadow: 0 0 25px var(--accent-red-glow);
|
|
860
1305
|
}
|
|
861
1306
|
|
|
862
1307
|
.made-with {
|
|
@@ -892,8 +1337,9 @@
|
|
|
892
1337
|
|
|
893
1338
|
.section-dot:hover,
|
|
894
1339
|
.section-dot.active {
|
|
895
|
-
background: var(--
|
|
896
|
-
|
|
1340
|
+
background: var(--accent-red);
|
|
1341
|
+
border-color: var(--accent-red);
|
|
1342
|
+
box-shadow: 0 0 12px var(--accent-red-glow);
|
|
897
1343
|
}
|
|
898
1344
|
|
|
899
1345
|
/* ============================================
|
|
@@ -938,6 +1384,37 @@
|
|
|
938
1384
|
</head>
|
|
939
1385
|
<body>
|
|
940
1386
|
|
|
1387
|
+
<!-- Animated Background Grid -->
|
|
1388
|
+
<div class="background-pattern">
|
|
1389
|
+
<svg class="grid-svg" id="gridSvg">
|
|
1390
|
+
<defs>
|
|
1391
|
+
<pattern id="smallGrid" width="40" height="40" patternUnits="userSpaceOnUse">
|
|
1392
|
+
<path d="M 40 0 L 0 0 0 40" class="grid-line" stroke-dasharray="2,4"/>
|
|
1393
|
+
</pattern>
|
|
1394
|
+
<pattern id="grid" width="200" height="200" patternUnits="userSpaceOnUse">
|
|
1395
|
+
<rect width="200" height="200" fill="url(#smallGrid)"/>
|
|
1396
|
+
<path d="M 200 0 L 0 0 0 200" class="grid-line" stroke-width="1"/>
|
|
1397
|
+
</pattern>
|
|
1398
|
+
</defs>
|
|
1399
|
+
<rect id="gridRect" width="100%" height="100%" fill="url(#grid)"/>
|
|
1400
|
+
</svg>
|
|
1401
|
+
</div>
|
|
1402
|
+
|
|
1403
|
+
<!-- Floating Particles -->
|
|
1404
|
+
<div class="particles" id="particles"></div>
|
|
1405
|
+
|
|
1406
|
+
<!-- Cursor Glow Effect -->
|
|
1407
|
+
<div class="cursor-glow" id="cursorGlow"></div>
|
|
1408
|
+
|
|
1409
|
+
<!-- Scanlines Overlay -->
|
|
1410
|
+
<div class="scanlines"></div>
|
|
1411
|
+
|
|
1412
|
+
<!-- Corner Decorations -->
|
|
1413
|
+
<div class="corner-decoration top-left"></div>
|
|
1414
|
+
<div class="corner-decoration top-right"></div>
|
|
1415
|
+
<div class="corner-decoration bottom-left"></div>
|
|
1416
|
+
<div class="corner-decoration bottom-right"></div>
|
|
1417
|
+
|
|
941
1418
|
<!-- Progress Bar -->
|
|
942
1419
|
<div class="progress-bar" id="progressBar"></div>
|
|
943
1420
|
|
|
@@ -957,21 +1434,49 @@
|
|
|
957
1434
|
<div class="ascii-border">
|
|
958
1435
|
<h1 id="titleText">INTERVIEW-DRIVEN API DEVELOPMENT</h1>
|
|
959
1436
|
<div class="package-name" id="packageName">@hustle-together/api-dev-tools</div>
|
|
960
|
-
<div class="version" id="versionText">v1.
|
|
1437
|
+
<div class="version" id="versionText">v1.9.0</div>
|
|
961
1438
|
<p class="tagline">"Interview first, test first, document always"<span class="cursor"></span></p>
|
|
962
1439
|
|
|
963
1440
|
<div class="intro-text">
|
|
964
1441
|
<p>
|
|
965
1442
|
This tool helps you build APIs the right way by <strong>enforcing a structured workflow</strong>.
|
|
966
|
-
Instead of letting AI assistants jump straight to code, it ensures they first
|
|
967
|
-
|
|
1443
|
+
Instead of letting AI assistants jump straight to code, it ensures they first research,
|
|
1444
|
+
then ask YOU questions with <strong>multiple-choice options</strong> based on what they found.
|
|
968
1445
|
</p>
|
|
969
1446
|
<p style="margin-top: 20px;">
|
|
970
1447
|
<strong>Scroll down</strong> to see how it works, step by step, using a real example:
|
|
971
|
-
|
|
1448
|
+
creating a <strong>Brandfetch API endpoint</strong> from scratch.
|
|
972
1449
|
</p>
|
|
973
1450
|
</div>
|
|
974
1451
|
|
|
1452
|
+
<!-- Visual Quick Overview -->
|
|
1453
|
+
<div class="data-flow" style="margin-top: 40px; opacity: 0;" id="introFlow">
|
|
1454
|
+
<div class="data-node glow-border">
|
|
1455
|
+
<span class="data-node-icon">[R]</span>
|
|
1456
|
+
<span class="data-node-label">Research</span>
|
|
1457
|
+
</div>
|
|
1458
|
+
<span class="data-arrow">→</span>
|
|
1459
|
+
<div class="data-node glow-border">
|
|
1460
|
+
<span class="data-node-icon">[?]</span>
|
|
1461
|
+
<span class="data-node-label">Interview</span>
|
|
1462
|
+
</div>
|
|
1463
|
+
<span class="data-arrow">→</span>
|
|
1464
|
+
<div class="data-node glow-border">
|
|
1465
|
+
<span class="data-node-icon">[T]</span>
|
|
1466
|
+
<span class="data-node-label">Test</span>
|
|
1467
|
+
</div>
|
|
1468
|
+
<span class="data-arrow">→</span>
|
|
1469
|
+
<div class="data-node glow-border">
|
|
1470
|
+
<span class="data-node-icon">[C]</span>
|
|
1471
|
+
<span class="data-node-label">Code</span>
|
|
1472
|
+
</div>
|
|
1473
|
+
<span class="data-arrow">→</span>
|
|
1474
|
+
<div class="data-node glow-border">
|
|
1475
|
+
<span class="data-node-icon">[D]</span>
|
|
1476
|
+
<span class="data-node-label">Docs</span>
|
|
1477
|
+
</div>
|
|
1478
|
+
</div>
|
|
1479
|
+
|
|
975
1480
|
<div class="scroll-hint">[ SCROLL TO BEGIN ]</div>
|
|
976
1481
|
</div>
|
|
977
1482
|
</section>
|
|
@@ -1180,31 +1685,35 @@
|
|
|
1180
1685
|
</div>
|
|
1181
1686
|
|
|
1182
1687
|
<div class="phase-grid">
|
|
1183
|
-
<div class="phase-box" data-phase="1">
|
|
1688
|
+
<div class="phase-box glow-border" data-phase="1">
|
|
1184
1689
|
<div class="phase-status"></div>
|
|
1185
1690
|
<div class="phase-number">01</div>
|
|
1186
1691
|
<div class="phase-name">Scope</div>
|
|
1187
1692
|
<div class="phase-desc">Define what we're building</div>
|
|
1693
|
+
<span class="phase-arrow">→</span>
|
|
1188
1694
|
</div>
|
|
1189
|
-
<div class="phase-box" data-phase="2">
|
|
1695
|
+
<div class="phase-box glow-border" data-phase="2">
|
|
1190
1696
|
<div class="phase-status"></div>
|
|
1191
1697
|
<div class="phase-number">02</div>
|
|
1192
1698
|
<div class="phase-name">Research</div>
|
|
1193
1699
|
<div class="phase-desc">Find live documentation</div>
|
|
1700
|
+
<span class="phase-arrow">→</span>
|
|
1194
1701
|
</div>
|
|
1195
|
-
<div class="phase-box" data-phase="3">
|
|
1702
|
+
<div class="phase-box glow-border" data-phase="3">
|
|
1196
1703
|
<div class="phase-status"></div>
|
|
1197
1704
|
<div class="phase-number">03</div>
|
|
1198
1705
|
<div class="phase-name">Interview</div>
|
|
1199
1706
|
<div class="phase-desc">Ask user questions</div>
|
|
1707
|
+
<span class="phase-arrow">→</span>
|
|
1200
1708
|
</div>
|
|
1201
|
-
<div class="phase-box" data-phase="4">
|
|
1709
|
+
<div class="phase-box glow-border" data-phase="4">
|
|
1202
1710
|
<div class="phase-status"></div>
|
|
1203
1711
|
<div class="phase-number">04</div>
|
|
1204
1712
|
<div class="phase-name">Deep Research</div>
|
|
1205
1713
|
<div class="phase-desc">Based on interview answers</div>
|
|
1714
|
+
<span class="phase-arrow">→</span>
|
|
1206
1715
|
</div>
|
|
1207
|
-
<div class="phase-box" data-phase="5">
|
|
1716
|
+
<div class="phase-box glow-border" data-phase="5">
|
|
1208
1717
|
<div class="phase-status"></div>
|
|
1209
1718
|
<div class="phase-number">05</div>
|
|
1210
1719
|
<div class="phase-name">Schema</div>
|
|
@@ -1213,31 +1722,35 @@
|
|
|
1213
1722
|
|
|
1214
1723
|
<div class="phase-connector">- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -</div>
|
|
1215
1724
|
|
|
1216
|
-
<div class="phase-box" data-phase="6">
|
|
1725
|
+
<div class="phase-box glow-border" data-phase="6">
|
|
1217
1726
|
<div class="phase-status"></div>
|
|
1218
1727
|
<div class="phase-number">06</div>
|
|
1219
1728
|
<div class="phase-name">Environment</div>
|
|
1220
1729
|
<div class="phase-desc">Check API keys exist</div>
|
|
1730
|
+
<span class="phase-arrow">→</span>
|
|
1221
1731
|
</div>
|
|
1222
|
-
<div class="phase-box" data-phase="7">
|
|
1732
|
+
<div class="phase-box glow-border" data-phase="7">
|
|
1223
1733
|
<div class="phase-status"></div>
|
|
1224
1734
|
<div class="phase-number">07</div>
|
|
1225
1735
|
<div class="phase-name">TDD Red</div>
|
|
1226
1736
|
<div class="phase-desc">Write failing tests</div>
|
|
1737
|
+
<span class="phase-arrow">→</span>
|
|
1227
1738
|
</div>
|
|
1228
|
-
<div class="phase-box" data-phase="8">
|
|
1739
|
+
<div class="phase-box glow-border" data-phase="8">
|
|
1229
1740
|
<div class="phase-status"></div>
|
|
1230
1741
|
<div class="phase-number">08</div>
|
|
1231
1742
|
<div class="phase-name">TDD Green</div>
|
|
1232
1743
|
<div class="phase-desc">Make tests pass</div>
|
|
1744
|
+
<span class="phase-arrow">→</span>
|
|
1233
1745
|
</div>
|
|
1234
|
-
<div class="phase-box" data-phase="9">
|
|
1746
|
+
<div class="phase-box glow-border" data-phase="9">
|
|
1235
1747
|
<div class="phase-status"></div>
|
|
1236
1748
|
<div class="phase-number">09</div>
|
|
1237
1749
|
<div class="phase-name">Refactor</div>
|
|
1238
1750
|
<div class="phase-desc">Clean up the code</div>
|
|
1751
|
+
<span class="phase-arrow">→</span>
|
|
1239
1752
|
</div>
|
|
1240
|
-
<div class="phase-box" data-phase="10">
|
|
1753
|
+
<div class="phase-box glow-border" data-phase="10">
|
|
1241
1754
|
<div class="phase-status"></div>
|
|
1242
1755
|
<div class="phase-number">10</div>
|
|
1243
1756
|
<div class="phase-name">Documentation</div>
|
|
@@ -1253,31 +1766,30 @@
|
|
|
1253
1766
|
<section id="walkthrough">
|
|
1254
1767
|
<div class="ascii-border">
|
|
1255
1768
|
<h2>REAL EXAMPLE</h2>
|
|
1256
|
-
<h3>
|
|
1769
|
+
<h3>Creating a Brandfetch API</h3>
|
|
1257
1770
|
|
|
1258
1771
|
<div class="explanation">
|
|
1259
|
-
<div class="explanation-title">
|
|
1772
|
+
<div class="explanation-title">The Complete Flow</div>
|
|
1260
1773
|
<p>
|
|
1261
|
-
Let's walk through what
|
|
1262
|
-
|
|
1263
|
-
|
|
1774
|
+
Let's walk through what happens when you run <code>/api-create brandfetch</code>.
|
|
1775
|
+
This shows the full interview-driven workflow, from research to implementation,
|
|
1776
|
+
with <strong>structured questions based on real documentation</strong>.
|
|
1264
1777
|
</p>
|
|
1265
1778
|
</div>
|
|
1266
1779
|
|
|
1267
1780
|
<div class="walkthrough-step">
|
|
1268
1781
|
<div class="walkthrough-header">
|
|
1269
1782
|
<div class="walkthrough-num">1</div>
|
|
1270
|
-
<div class="walkthrough-title">
|
|
1783
|
+
<div class="walkthrough-title">You Run the Command</div>
|
|
1271
1784
|
</div>
|
|
1272
1785
|
<div class="walkthrough-content">
|
|
1273
1786
|
<div class="walkthrough-desc">
|
|
1274
|
-
|
|
1275
|
-
|
|
1787
|
+
You type the command to create a new Brandfetch API endpoint.
|
|
1788
|
+
The workflow immediately begins.
|
|
1276
1789
|
</div>
|
|
1277
1790
|
<div class="walkthrough-example">
|
|
1278
|
-
<div class="label">
|
|
1279
|
-
|
|
1280
|
-
so I only need one API key instead of four."
|
|
1791
|
+
<div class="label">Your Command:</div>
|
|
1792
|
+
/api-create brandfetch
|
|
1281
1793
|
</div>
|
|
1282
1794
|
</div>
|
|
1283
1795
|
</div>
|
|
@@ -1285,19 +1797,19 @@
|
|
|
1285
1797
|
<div class="walkthrough-step">
|
|
1286
1798
|
<div class="walkthrough-header">
|
|
1287
1799
|
<div class="walkthrough-num">2</div>
|
|
1288
|
-
<div class="walkthrough-title">Research Phase</div>
|
|
1800
|
+
<div class="walkthrough-title">Research Phase (Automatic)</div>
|
|
1289
1801
|
</div>
|
|
1290
1802
|
<div class="walkthrough-content">
|
|
1291
1803
|
<div class="walkthrough-desc">
|
|
1292
|
-
|
|
1293
|
-
It
|
|
1804
|
+
Before asking any questions, the AI is <strong>required</strong> to research.
|
|
1805
|
+
It fetches live documentation from Context7 and searches the web.
|
|
1294
1806
|
</div>
|
|
1295
1807
|
<div class="walkthrough-example">
|
|
1296
|
-
<div class="label">Research
|
|
1297
|
-
- Context7:
|
|
1298
|
-
- WebSearch:
|
|
1299
|
-
- WebSearch:
|
|
1300
|
-
- Context7:
|
|
1808
|
+
<div class="label">Research Logged to State File:</div>
|
|
1809
|
+
- Context7: Brandfetch SDK docs → found logos, colors, fonts endpoints<br>
|
|
1810
|
+
- WebSearch: "Brandfetch API rate limits 2025" → 5 req/second<br>
|
|
1811
|
+
- WebSearch: "Brandfetch API response format" → JSON with asset URLs<br>
|
|
1812
|
+
- Context7: Authentication → Bearer token required
|
|
1301
1813
|
</div>
|
|
1302
1814
|
</div>
|
|
1303
1815
|
</div>
|
|
@@ -1305,75 +1817,87 @@
|
|
|
1305
1817
|
<div class="walkthrough-step">
|
|
1306
1818
|
<div class="walkthrough-header">
|
|
1307
1819
|
<div class="walkthrough-num">3</div>
|
|
1308
|
-
<div class="walkthrough-title">Interview
|
|
1820
|
+
<div class="walkthrough-title">Structured Interview (Based on Research)</div>
|
|
1309
1821
|
</div>
|
|
1310
1822
|
<div class="walkthrough-content">
|
|
1311
1823
|
<div class="walkthrough-desc">
|
|
1312
|
-
AI
|
|
1313
|
-
|
|
1824
|
+
Now the AI asks YOU questions - but with <strong>multiple-choice options</strong>
|
|
1825
|
+
derived from what it actually found in the documentation. No guessing!
|
|
1314
1826
|
</div>
|
|
1315
1827
|
<div class="walkthrough-example">
|
|
1316
|
-
<div class="label">
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1828
|
+
<div class="label">Question 1 (with options from research):</div>
|
|
1829
|
+
"What's the primary purpose of this endpoint?"<br><br>
|
|
1830
|
+
<strong>1.</strong> Brand lookup (get brand by domain)<br>
|
|
1831
|
+
<strong>2.</strong> Logo extraction (get logo assets)<br>
|
|
1832
|
+
<strong>3.</strong> Color palette extraction<br>
|
|
1833
|
+
<strong>4.</strong> Full brand kit (all assets)<br>
|
|
1834
|
+
<strong>5.</strong> Type something else...<br><br>
|
|
1835
|
+
<em>You select: "4. Full brand kit (all assets)"</em>
|
|
1320
1836
|
</div>
|
|
1321
1837
|
</div>
|
|
1322
1838
|
</div>
|
|
1323
1839
|
|
|
1324
|
-
<div class="walkthrough-step"
|
|
1840
|
+
<div class="walkthrough-step">
|
|
1325
1841
|
<div class="walkthrough-header">
|
|
1326
|
-
<div class="walkthrough-num"
|
|
1327
|
-
<div class="walkthrough-title">
|
|
1842
|
+
<div class="walkthrough-num">4</div>
|
|
1843
|
+
<div class="walkthrough-title">More Questions, All Tracked</div>
|
|
1328
1844
|
</div>
|
|
1329
1845
|
<div class="walkthrough-content">
|
|
1330
1846
|
<div class="walkthrough-desc">
|
|
1331
|
-
|
|
1332
|
-
|
|
1847
|
+
Each question is tracked with your answer. These decisions are stored
|
|
1848
|
+
in the state file and <strong>injected during implementation</strong> to ensure consistency.
|
|
1333
1849
|
</div>
|
|
1334
1850
|
<div class="walkthrough-example">
|
|
1335
|
-
<div class="label">
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1851
|
+
<div class="label">Decisions Captured:</div>
|
|
1852
|
+
• Purpose: full_brand_kit<br>
|
|
1853
|
+
• Response Format: JSON with asset URLs<br>
|
|
1854
|
+
• API Key Handling: server environment variables only<br>
|
|
1855
|
+
• Error Handling: detailed (error, code, details)<br>
|
|
1856
|
+
• Required Params: domain (string)<br>
|
|
1857
|
+
• Optional Params: include_colors, include_fonts
|
|
1339
1858
|
</div>
|
|
1340
1859
|
</div>
|
|
1341
1860
|
</div>
|
|
1342
1861
|
|
|
1343
1862
|
<div class="walkthrough-step">
|
|
1344
1863
|
<div class="walkthrough-header">
|
|
1345
|
-
<div class="walkthrough-num">
|
|
1346
|
-
<div class="walkthrough-title">
|
|
1864
|
+
<div class="walkthrough-num">5</div>
|
|
1865
|
+
<div class="walkthrough-title">Implementation (With Decision Reminders)</div>
|
|
1347
1866
|
</div>
|
|
1348
1867
|
<div class="walkthrough-content">
|
|
1349
1868
|
<div class="walkthrough-desc">
|
|
1350
|
-
|
|
1351
|
-
|
|
1869
|
+
When the AI writes code, the hook <strong>injects your decisions</strong> as a reminder.
|
|
1870
|
+
This ensures the implementation matches what you actually asked for.
|
|
1352
1871
|
</div>
|
|
1353
1872
|
<div class="walkthrough-example">
|
|
1354
|
-
<div class="label">
|
|
1355
|
-
|
|
1356
|
-
|
|
1873
|
+
<div class="label">Injected on Every Write:</div>
|
|
1874
|
+
✅ Interview complete. REMEMBER THE USER'S DECISIONS:<br><br>
|
|
1875
|
+
• Purpose: Full brand kit (all assets)<br>
|
|
1876
|
+
• Response Format: JSON with asset URLs<br>
|
|
1877
|
+
• API Key Handling: server environment variables only<br>
|
|
1878
|
+
• Error Handling: detailed (error, code, details)<br><br>
|
|
1879
|
+
<em>Your implementation MUST align with these choices.</em>
|
|
1357
1880
|
</div>
|
|
1358
1881
|
</div>
|
|
1359
1882
|
</div>
|
|
1360
1883
|
|
|
1361
1884
|
<div class="walkthrough-step">
|
|
1362
1885
|
<div class="walkthrough-header">
|
|
1363
|
-
<div class="walkthrough-num">
|
|
1364
|
-
<div class="walkthrough-title">Final Result</div>
|
|
1886
|
+
<div class="walkthrough-num">6</div>
|
|
1887
|
+
<div class="walkthrough-title">TDD + Final Result</div>
|
|
1365
1888
|
</div>
|
|
1366
1889
|
<div class="walkthrough-content">
|
|
1367
1890
|
<div class="walkthrough-desc">
|
|
1368
|
-
|
|
1369
|
-
|
|
1891
|
+
Tests are written first (TDD), then implementation, then docs.
|
|
1892
|
+
Everything is tracked and verified against your interview decisions.
|
|
1370
1893
|
</div>
|
|
1371
1894
|
<div class="walkthrough-example">
|
|
1372
1895
|
<div class="label">Files Created:</div>
|
|
1373
|
-
- src/lib/
|
|
1374
|
-
- src/lib/
|
|
1375
|
-
- src/app/api/v2/
|
|
1376
|
-
-
|
|
1896
|
+
- src/lib/schemas/brandfetch.ts (Zod validation)<br>
|
|
1897
|
+
- src/lib/__tests__/brandfetch.test.ts (tests first!)<br>
|
|
1898
|
+
- src/app/api/v2/brandfetch/route.ts<br>
|
|
1899
|
+
- Interview doc: src/v2/docs/endpoints/brandfetch.md<br>
|
|
1900
|
+
- All tests passing ✓
|
|
1377
1901
|
</div>
|
|
1378
1902
|
</div>
|
|
1379
1903
|
</div>
|
|
@@ -1386,14 +1910,14 @@
|
|
|
1386
1910
|
<section id="demo">
|
|
1387
1911
|
<div class="ascii-border">
|
|
1388
1912
|
<h2>LIVE SIMULATION</h2>
|
|
1389
|
-
<h3>
|
|
1913
|
+
<h3>The Interview Flow</h3>
|
|
1390
1914
|
|
|
1391
1915
|
<div class="explanation">
|
|
1392
|
-
<div class="explanation-title">
|
|
1916
|
+
<div class="explanation-title">Structured Questions in Action</div>
|
|
1393
1917
|
<p>
|
|
1394
|
-
This simulates
|
|
1395
|
-
|
|
1396
|
-
|
|
1918
|
+
This simulates the interview phase. Notice how the AI uses
|
|
1919
|
+
<strong>AskUserQuestion with options</strong> based on research findings.
|
|
1920
|
+
Your answers are captured and used throughout implementation.
|
|
1397
1921
|
</p>
|
|
1398
1922
|
</div>
|
|
1399
1923
|
|
|
@@ -1402,70 +1926,93 @@
|
|
|
1402
1926
|
<div class="terminal-dot"></div>
|
|
1403
1927
|
<div class="terminal-dot"></div>
|
|
1404
1928
|
<div class="terminal-dot"></div>
|
|
1405
|
-
<div class="terminal-title">claude-code session</div>
|
|
1929
|
+
<div class="terminal-title">claude-code session: /api-create brandfetch</div>
|
|
1930
|
+
<div class="status-badge active" style="margin-left: auto;">
|
|
1931
|
+
<span class="pulse"></span>
|
|
1932
|
+
<span>Live</span>
|
|
1933
|
+
</div>
|
|
1406
1934
|
</div>
|
|
1407
1935
|
|
|
1408
|
-
<div class="terminal-comment" data-step="0">//
|
|
1936
|
+
<div class="terminal-comment" data-step="0">// Step 1: Research phase starts automatically</div>
|
|
1409
1937
|
<div class="terminal-line" data-step="1">
|
|
1410
1938
|
<span class="terminal-prompt">claude></span>
|
|
1411
|
-
<span class="terminal-command">
|
|
1939
|
+
<span class="terminal-command">mcp__context7__get-library-docs("brandfetch")</span>
|
|
1412
1940
|
</div>
|
|
1413
1941
|
<div class="terminal-line terminal-result" data-step="2">
|
|
1414
|
-
<span class="terminal-
|
|
1942
|
+
<span class="terminal-logged">[LOGGED] Context7 source: brandfetch SDK documentation</span>
|
|
1415
1943
|
</div>
|
|
1416
1944
|
|
|
1417
|
-
<div class="terminal-
|
|
1418
|
-
<div class="terminal-line" data-step="4">
|
|
1945
|
+
<div class="terminal-line" data-step="3">
|
|
1419
1946
|
<span class="terminal-prompt">claude></span>
|
|
1420
|
-
<span class="terminal-command">WebSearch "
|
|
1947
|
+
<span class="terminal-command">WebSearch "Brandfetch API endpoints 2025"</span>
|
|
1421
1948
|
</div>
|
|
1422
|
-
<div class="terminal-line terminal-result" data-step="
|
|
1423
|
-
<span class="terminal-logged">[LOGGED]
|
|
1949
|
+
<div class="terminal-line terminal-result" data-step="4">
|
|
1950
|
+
<span class="terminal-logged">[LOGGED] WebSearch: found /v2/brands, /v2/search, /v2/logos</span>
|
|
1424
1951
|
</div>
|
|
1425
1952
|
|
|
1426
|
-
<div class="terminal-comment" data-step="
|
|
1427
|
-
<div class="terminal-line" data-step="
|
|
1953
|
+
<div class="terminal-comment" data-step="5">// Step 2: Interview with structured options (from research)</div>
|
|
1954
|
+
<div class="terminal-line" data-step="6">
|
|
1428
1955
|
<span class="terminal-prompt">claude></span>
|
|
1429
|
-
<span class="terminal-command">
|
|
1956
|
+
<span class="terminal-command">AskUserQuestion(<br>
|
|
1957
|
+
question: "What's the primary purpose?"<br>
|
|
1958
|
+
options: [<br>
|
|
1959
|
+
{value: "lookup", label: "Brand lookup by domain"},<br>
|
|
1960
|
+
{value: "logos", label: "Logo extraction only"},<br>
|
|
1961
|
+
{value: "full_kit", label: "Full brand kit"},<br>
|
|
1962
|
+
{value: "custom", label: "Type something..."}<br>
|
|
1963
|
+
]<br>
|
|
1964
|
+
)</span>
|
|
1430
1965
|
</div>
|
|
1431
|
-
<div class="terminal-line terminal-result" data-step="
|
|
1432
|
-
<span class="terminal-
|
|
1966
|
+
<div class="terminal-line terminal-result" data-step="7">
|
|
1967
|
+
<span class="terminal-allowed">[USER] Selected: "full_kit"<br>[TRACKED] decisions.purpose = "full_kit"</span>
|
|
1433
1968
|
</div>
|
|
1434
1969
|
|
|
1435
|
-
<div class="terminal-
|
|
1436
|
-
<div class="terminal-line" data-step="10">
|
|
1970
|
+
<div class="terminal-line" data-step="8">
|
|
1437
1971
|
<span class="terminal-prompt">claude></span>
|
|
1438
|
-
<span class="terminal-command">AskUserQuestion
|
|
1972
|
+
<span class="terminal-command">AskUserQuestion(<br>
|
|
1973
|
+
question: "How should API keys be handled?"<br>
|
|
1974
|
+
options: [<br>
|
|
1975
|
+
{value: "server_only", label: "Server env vars only"},<br>
|
|
1976
|
+
{value: "header", label: "Custom header override"},<br>
|
|
1977
|
+
{value: "both", label: "Both methods"},<br>
|
|
1978
|
+
]<br>
|
|
1979
|
+
)</span>
|
|
1439
1980
|
</div>
|
|
1440
|
-
<div class="terminal-line terminal-result" data-step="
|
|
1441
|
-
<span class="terminal-
|
|
1981
|
+
<div class="terminal-line terminal-result" data-step="9">
|
|
1982
|
+
<span class="terminal-allowed">[USER] Selected: "server_only"<br>[TRACKED] decisions.api_key_handling = "server_only"</span>
|
|
1442
1983
|
</div>
|
|
1443
1984
|
|
|
1444
|
-
<div class="terminal-comment" data-step="
|
|
1445
|
-
<div class="terminal-line" data-step="
|
|
1985
|
+
<div class="terminal-comment" data-step="10">// Step 3: Interview complete, now writing code</div>
|
|
1986
|
+
<div class="terminal-line" data-step="11">
|
|
1446
1987
|
<span class="terminal-prompt">claude></span>
|
|
1447
|
-
<span class="terminal-command">Write src/app/api/v2/
|
|
1988
|
+
<span class="terminal-command">Write src/app/api/v2/brandfetch/route.ts</span>
|
|
1448
1989
|
</div>
|
|
1449
|
-
<div class="terminal-line terminal-result" data-step="
|
|
1450
|
-
<span class="terminal-allowed"
|
|
1990
|
+
<div class="terminal-line terminal-result" data-step="12">
|
|
1991
|
+
<span class="terminal-allowed">✅ Interview complete. REMEMBER THE USER'S DECISIONS:<br>
|
|
1992
|
+
• Purpose: full_kit<br>
|
|
1993
|
+
• API Key Handling: server_only<br>
|
|
1994
|
+
ALLOWED: Writing file...</span>
|
|
1451
1995
|
</div>
|
|
1452
1996
|
|
|
1453
|
-
<div class="terminal-comment" data-step="
|
|
1454
|
-
<div class="terminal-line" data-step="
|
|
1997
|
+
<div class="terminal-comment" data-step="13">// Decisions are injected on EVERY write operation</div>
|
|
1998
|
+
<div class="terminal-line" data-step="14">
|
|
1455
1999
|
<span class="terminal-prompt">claude></span>
|
|
1456
|
-
<span class="terminal-command">
|
|
2000
|
+
<span class="terminal-command">Write src/lib/schemas/brandfetch.ts</span>
|
|
1457
2001
|
</div>
|
|
1458
|
-
<div class="terminal-line terminal-result" data-step="
|
|
1459
|
-
<span class="terminal-
|
|
2002
|
+
<div class="terminal-line terminal-result" data-step="15">
|
|
2003
|
+
<span class="terminal-allowed">✅ REMEMBER THE USER'S DECISIONS:<br>
|
|
2004
|
+
• Purpose: full_kit<br>
|
|
2005
|
+
• API Key Handling: server_only<br>
|
|
2006
|
+
ALLOWED: Writing schema file...</span>
|
|
1460
2007
|
</div>
|
|
1461
2008
|
|
|
1462
|
-
<div class="terminal-
|
|
1463
|
-
<div class="terminal-line" data-step="19">
|
|
2009
|
+
<div class="terminal-line" data-step="16" style="margin-top: 15px;">
|
|
1464
2010
|
<span class="terminal-prompt">claude></span>
|
|
1465
|
-
<
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
2011
|
+
<div class="typing-indicator">
|
|
2012
|
+
<span></span>
|
|
2013
|
+
<span></span>
|
|
2014
|
+
<span></span>
|
|
2015
|
+
</div>
|
|
1469
2016
|
</div>
|
|
1470
2017
|
</div>
|
|
1471
2018
|
</div>
|
|
@@ -1483,33 +2030,41 @@
|
|
|
1483
2030
|
<div class="explanation-title">Everything Gets Recorded</div>
|
|
1484
2031
|
<p>
|
|
1485
2032
|
All progress is saved to <code>.claude/api-dev-state.json</code>.
|
|
1486
|
-
This
|
|
1487
|
-
|
|
2033
|
+
This includes <strong>your interview decisions</strong>, which are injected
|
|
2034
|
+
during implementation to ensure consistency.
|
|
1488
2035
|
</p>
|
|
1489
2036
|
</div>
|
|
1490
2037
|
|
|
1491
2038
|
<div class="json-viewer">
|
|
1492
2039
|
<div class="json-line"><span class="json-key">{</span></div>
|
|
1493
|
-
<div class="json-line"> <span class="json-key">"endpoint":</span> <span class="json-string">"
|
|
1494
|
-
<div class="json-line"> <span class="json-key">"library":</span> <span class="json-string">"Vercel AI SDK"</span>,</div>
|
|
2040
|
+
<div class="json-line"> <span class="json-key">"endpoint":</span> <span class="json-string">"brandfetch"</span>,</div>
|
|
1495
2041
|
<div class="json-line"> <span class="json-key">"phases":</span> {</div>
|
|
1496
|
-
<div class="json-line highlight"> <span class="json-key">"research_initial":</span> {
|
|
2042
|
+
<div class="json-line highlight"> <span class="json-key">"research_initial":</span> {</div>
|
|
2043
|
+
<div class="json-line highlight"> <span class="json-key">"status":</span> <span class="json-value">"complete"</span>,</div>
|
|
2044
|
+
<div class="json-line highlight"> <span class="json-key">"sources":</span> [<span class="json-string">"context7"</span>, <span class="json-string">"websearch"</span>, <span class="json-string">"websearch"</span>]</div>
|
|
2045
|
+
<div class="json-line highlight"> },</div>
|
|
1497
2046
|
<div class="json-line highlight"> <span class="json-key">"interview":</span> {</div>
|
|
1498
2047
|
<div class="json-line highlight"> <span class="json-key">"status":</span> <span class="json-value">"complete"</span>,</div>
|
|
1499
|
-
<div class="json-line highlight"> <span class="json-key">"user_question_count":</span> <span class="json-value">6</span
|
|
2048
|
+
<div class="json-line highlight"> <span class="json-key">"user_question_count":</span> <span class="json-value">6</span>,</div>
|
|
2049
|
+
<div class="json-line highlight"> <span class="json-key">"structured_question_count":</span> <span class="json-value">5</span>, <span class="json-comment">// Questions with options</span></div>
|
|
2050
|
+
<div class="json-line highlight"> <span class="json-key">"decisions":</span> { <span class="json-comment">// YOUR CHOICES - INJECTED ON WRITES</span></div>
|
|
2051
|
+
<div class="json-line highlight"> <span class="json-key">"purpose":</span> {<span class="json-key">"value":</span> <span class="json-string">"full_kit"</span>},</div>
|
|
2052
|
+
<div class="json-line highlight"> <span class="json-key">"api_key_handling":</span> {<span class="json-key">"value":</span> <span class="json-string">"server_only"</span>},</div>
|
|
2053
|
+
<div class="json-line highlight"> <span class="json-key">"response_format":</span> {<span class="json-key">"value":</span> <span class="json-string">"json"</span>},</div>
|
|
2054
|
+
<div class="json-line highlight"> <span class="json-key">"error_handling":</span> {<span class="json-key">"value":</span> <span class="json-string">"detailed"</span>}</div>
|
|
2055
|
+
<div class="json-line highlight"> },</div>
|
|
2056
|
+
<div class="json-line highlight"> <span class="json-key">"questions":</span> [</div>
|
|
2057
|
+
<div class="json-line highlight"> {<span class="json-key">"tool_used":</span> <span class="json-value">true</span>, <span class="json-key">"has_options":</span> <span class="json-value">true</span>, <span class="json-key">"user_response":</span> <span class="json-string">"full_kit"</span>},</div>
|
|
2058
|
+
<div class="json-line highlight"> <span class="json-comment">// ... more questions tracked</span></div>
|
|
2059
|
+
<div class="json-line highlight"> ]</div>
|
|
1500
2060
|
<div class="json-line highlight"> },</div>
|
|
1501
|
-
<div class="json-line
|
|
1502
|
-
<div class="json-line
|
|
1503
|
-
<div class="json-line"> },</div>
|
|
1504
|
-
<div class="json-line"> <span class="json-key">"verification":</span> {</div>
|
|
1505
|
-
<div class="json-line"> <span class="json-key">"all_sources_fetched":</span> <span class="json-value">true</span>,</div>
|
|
1506
|
-
<div class="json-line"> <span class="json-key">"all_tests_passing":</span> <span class="json-value">true</span></div>
|
|
2061
|
+
<div class="json-line"> <span class="json-key">"tdd_red":</span> { <span class="json-key">"status":</span> <span class="json-value">"complete"</span> },</div>
|
|
2062
|
+
<div class="json-line"> <span class="json-key">"tdd_green":</span> { <span class="json-key">"status":</span> <span class="json-value">"complete"</span> }</div>
|
|
1507
2063
|
<div class="json-line"> },</div>
|
|
1508
2064
|
<div class="json-line"> <span class="json-key">"files_created":</span> [</div>
|
|
1509
|
-
<div class="json-line"> <span class="json-string">"src/lib/
|
|
1510
|
-
<div class="json-line"> <span class="json-string">"src/
|
|
1511
|
-
<div class="json-line"> <span class="json-string">"src/
|
|
1512
|
-
<div class="json-line"> <span class="json-string">"... and 9 more"</span></div>
|
|
2065
|
+
<div class="json-line"> <span class="json-string">"src/lib/schemas/brandfetch.ts"</span>,</div>
|
|
2066
|
+
<div class="json-line"> <span class="json-string">"src/app/api/v2/brandfetch/route.ts"</span>,</div>
|
|
2067
|
+
<div class="json-line"> <span class="json-string">"src/v2/docs/endpoints/brandfetch.md"</span></div>
|
|
1513
2068
|
<div class="json-line"> ]</div>
|
|
1514
2069
|
<div class="json-line"><span class="json-key">}</span></div>
|
|
1515
2070
|
</div>
|
|
@@ -1587,13 +2142,28 @@
|
|
|
1587
2142
|
|
|
1588
2143
|
<div class="explanation" style="text-align: left;">
|
|
1589
2144
|
<div class="explanation-title">What You Get</div>
|
|
1590
|
-
<
|
|
1591
|
-
<
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
<
|
|
1596
|
-
|
|
2145
|
+
<div style="display: flex; flex-direction: column; gap: 12px;">
|
|
2146
|
+
<div style="display: flex; align-items: center;">
|
|
2147
|
+
<span class="visual-check checked"></span>
|
|
2148
|
+
<span><strong>Structured workflow</strong> - No more skipped steps or assumptions</span>
|
|
2149
|
+
</div>
|
|
2150
|
+
<div style="display: flex; align-items: center;">
|
|
2151
|
+
<span class="visual-check checked"></span>
|
|
2152
|
+
<span><strong>Real enforcement</strong> - Hooks that actually block bad behavior</span>
|
|
2153
|
+
</div>
|
|
2154
|
+
<div style="display: flex; align-items: center;">
|
|
2155
|
+
<span class="visual-check checked"></span>
|
|
2156
|
+
<span><strong>Audit trail</strong> - Every action logged to state file</span>
|
|
2157
|
+
</div>
|
|
2158
|
+
<div style="display: flex; align-items: center;">
|
|
2159
|
+
<span class="visual-check checked"></span>
|
|
2160
|
+
<span><strong>Gap detection</strong> - Catches mismatches between requirements and code</span>
|
|
2161
|
+
</div>
|
|
2162
|
+
<div style="display: flex; align-items: center;">
|
|
2163
|
+
<span class="visual-check checked"></span>
|
|
2164
|
+
<span><strong>TDD built-in</strong> - Tests written before implementation</span>
|
|
2165
|
+
</div>
|
|
2166
|
+
</div>
|
|
1597
2167
|
</div>
|
|
1598
2168
|
|
|
1599
2169
|
<div class="credit-links">
|
|
@@ -1604,7 +2174,7 @@
|
|
|
1604
2174
|
<div class="made-with">
|
|
1605
2175
|
<p>Made for developers who want AI assistants<br>that actually follow instructions.</p>
|
|
1606
2176
|
<p style="margin-top: 20px; color: var(--dark-grey);">
|
|
1607
|
-
v1.
|
|
2177
|
+
v1.9.0 | MIT License<br>
|
|
1608
2178
|
"Interview first, test first, document always"
|
|
1609
2179
|
</p>
|
|
1610
2180
|
</div>
|
|
@@ -1667,6 +2237,9 @@
|
|
|
1667
2237
|
.to('#packageName', { opacity: 1, duration: 0.5 }, '-=0.3')
|
|
1668
2238
|
.to('#versionText', { opacity: 1, duration: 0.3 })
|
|
1669
2239
|
.to('.intro-text', { opacity: 1, duration: 0.6 }, '-=0.2')
|
|
2240
|
+
.to('#introFlow', { opacity: 1, duration: 0.6 })
|
|
2241
|
+
.to('#introFlow .data-node', { opacity: 1, y: 0, stagger: 0.15, duration: 0.4 }, '-=0.3')
|
|
2242
|
+
.to('#introFlow .data-arrow', { opacity: 1, stagger: 0.1, duration: 0.2 }, '-=0.5')
|
|
1670
2243
|
.to('.scroll-hint', { opacity: 1, duration: 0.4 });
|
|
1671
2244
|
|
|
1672
2245
|
// ============================================
|
|
@@ -1939,6 +2512,157 @@
|
|
|
1939
2512
|
});
|
|
1940
2513
|
});
|
|
1941
2514
|
});
|
|
2515
|
+
|
|
2516
|
+
// ============================================
|
|
2517
|
+
// ANIMATED BACKGROUND - FLOATING PARTICLES (ENHANCED)
|
|
2518
|
+
// ============================================
|
|
2519
|
+
const particleContainer = document.getElementById('particles');
|
|
2520
|
+
// More particle types: circles, squares, X's, plus signs, lines, triangles
|
|
2521
|
+
const particleTypes = ['', 'square', 'plus', 'x-shape', 'line', 'line-v', 'circle-outline', 'triangle'];
|
|
2522
|
+
const particleCount = 50; // More particles
|
|
2523
|
+
|
|
2524
|
+
// Create particles
|
|
2525
|
+
for (let i = 0; i < particleCount; i++) {
|
|
2526
|
+
const particle = document.createElement('div');
|
|
2527
|
+
const type = particleTypes[Math.floor(Math.random() * particleTypes.length)];
|
|
2528
|
+
particle.className = `particle ${type}`;
|
|
2529
|
+
particle.style.left = `${Math.random() * 100}%`;
|
|
2530
|
+
particle.style.top = `${Math.random() * 100}%`;
|
|
2531
|
+
particleContainer.appendChild(particle);
|
|
2532
|
+
|
|
2533
|
+
// FASTER, MORE VISIBLE MOVEMENT
|
|
2534
|
+
const speed = 4 + Math.random() * 8; // Much faster: 4-12 seconds
|
|
2535
|
+
const distance = 150 + Math.random() * 250; // Larger movement range
|
|
2536
|
+
|
|
2537
|
+
// Animate each particle with GSAP - MORE MOTION
|
|
2538
|
+
gsap.to(particle, {
|
|
2539
|
+
x: `${(Math.random() - 0.5) * distance}`,
|
|
2540
|
+
y: `${(Math.random() - 0.5) * distance}`,
|
|
2541
|
+
rotation: (Math.random() - 0.5) * 720, // More rotation
|
|
2542
|
+
duration: speed,
|
|
2543
|
+
repeat: -1,
|
|
2544
|
+
yoyo: true,
|
|
2545
|
+
ease: 'sine.inOut',
|
|
2546
|
+
delay: Math.random() * 2
|
|
2547
|
+
});
|
|
2548
|
+
|
|
2549
|
+
// Fade in/out animation - more visible
|
|
2550
|
+
gsap.to(particle, {
|
|
2551
|
+
opacity: 0.15 + Math.random() * 0.4, // Higher opacity
|
|
2552
|
+
duration: 2 + Math.random() * 3,
|
|
2553
|
+
repeat: -1,
|
|
2554
|
+
yoyo: true,
|
|
2555
|
+
ease: 'sine.inOut',
|
|
2556
|
+
delay: Math.random() * 2
|
|
2557
|
+
});
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2560
|
+
// Add some CONSTANTLY MOVING particles that drift across the screen
|
|
2561
|
+
for (let i = 0; i < 10; i++) {
|
|
2562
|
+
const drifter = document.createElement('div');
|
|
2563
|
+
const type = particleTypes[Math.floor(Math.random() * particleTypes.length)];
|
|
2564
|
+
drifter.className = `particle ${type}`;
|
|
2565
|
+
drifter.style.left = `-20px`;
|
|
2566
|
+
drifter.style.top = `${Math.random() * 100}%`;
|
|
2567
|
+
drifter.style.opacity = '0.3';
|
|
2568
|
+
particleContainer.appendChild(drifter);
|
|
2569
|
+
|
|
2570
|
+
// Drift across the screen continuously
|
|
2571
|
+
gsap.to(drifter, {
|
|
2572
|
+
x: window.innerWidth + 40,
|
|
2573
|
+
y: (Math.random() - 0.5) * 200,
|
|
2574
|
+
rotation: Math.random() * 360,
|
|
2575
|
+
duration: 15 + Math.random() * 15,
|
|
2576
|
+
repeat: -1,
|
|
2577
|
+
ease: 'none',
|
|
2578
|
+
delay: i * 3
|
|
2579
|
+
});
|
|
2580
|
+
}
|
|
2581
|
+
|
|
2582
|
+
// ============================================
|
|
2583
|
+
// ANIMATED BACKGROUND - GRID MOTION (FASTER)
|
|
2584
|
+
// ============================================
|
|
2585
|
+
const gridRect = document.getElementById('gridRect');
|
|
2586
|
+
let gridOffset = { x: 0, y: 0 };
|
|
2587
|
+
|
|
2588
|
+
// Faster, more noticeable grid drift
|
|
2589
|
+
gsap.to(gridOffset, {
|
|
2590
|
+
x: 40,
|
|
2591
|
+
y: 40,
|
|
2592
|
+
duration: 10, // Faster: was 30
|
|
2593
|
+
repeat: -1,
|
|
2594
|
+
yoyo: true, // Added yoyo for back-and-forth
|
|
2595
|
+
ease: 'sine.inOut',
|
|
2596
|
+
onUpdate: () => {
|
|
2597
|
+
gridRect.setAttribute('transform', `translate(${gridOffset.x}, ${gridOffset.y})`);
|
|
2598
|
+
}
|
|
2599
|
+
});
|
|
2600
|
+
|
|
2601
|
+
// Add subtle grid pulsing
|
|
2602
|
+
gsap.to('.grid-svg', {
|
|
2603
|
+
opacity: 0.2,
|
|
2604
|
+
duration: 4,
|
|
2605
|
+
repeat: -1,
|
|
2606
|
+
yoyo: true,
|
|
2607
|
+
ease: 'sine.inOut'
|
|
2608
|
+
});
|
|
2609
|
+
|
|
2610
|
+
// ============================================
|
|
2611
|
+
// CURSOR GLOW EFFECT
|
|
2612
|
+
// ============================================
|
|
2613
|
+
const cursorGlow = document.getElementById('cursorGlow');
|
|
2614
|
+
let mouseX = 0, mouseY = 0;
|
|
2615
|
+
let glowX = 0, glowY = 0;
|
|
2616
|
+
|
|
2617
|
+
document.addEventListener('mousemove', (e) => {
|
|
2618
|
+
mouseX = e.clientX;
|
|
2619
|
+
mouseY = e.clientY;
|
|
2620
|
+
});
|
|
2621
|
+
|
|
2622
|
+
// Smooth cursor follow
|
|
2623
|
+
function updateCursorGlow() {
|
|
2624
|
+
const dx = mouseX - glowX;
|
|
2625
|
+
const dy = mouseY - glowY;
|
|
2626
|
+
glowX += dx * 0.08;
|
|
2627
|
+
glowY += dy * 0.08;
|
|
2628
|
+
cursorGlow.style.left = `${glowX}px`;
|
|
2629
|
+
cursorGlow.style.top = `${glowY}px`;
|
|
2630
|
+
requestAnimationFrame(updateCursorGlow);
|
|
2631
|
+
}
|
|
2632
|
+
updateCursorGlow();
|
|
2633
|
+
|
|
2634
|
+
// ============================================
|
|
2635
|
+
// CORNER DECORATIONS ANIMATION
|
|
2636
|
+
// ============================================
|
|
2637
|
+
gsap.to('.corner-decoration', {
|
|
2638
|
+
opacity: 0.2,
|
|
2639
|
+
duration: 2,
|
|
2640
|
+
repeat: -1,
|
|
2641
|
+
yoyo: true,
|
|
2642
|
+
ease: 'sine.inOut',
|
|
2643
|
+
stagger: 0.5
|
|
2644
|
+
});
|
|
2645
|
+
|
|
2646
|
+
// ============================================
|
|
2647
|
+
// SECTION TRANSITION EFFECTS
|
|
2648
|
+
// ============================================
|
|
2649
|
+
sections.forEach(sectionId => {
|
|
2650
|
+
ScrollTrigger.create({
|
|
2651
|
+
trigger: `#${sectionId}`,
|
|
2652
|
+
start: 'top center',
|
|
2653
|
+
end: 'bottom center',
|
|
2654
|
+
onEnter: () => {
|
|
2655
|
+
// Pulse the grid when entering a new section
|
|
2656
|
+
gsap.to('.grid-svg', {
|
|
2657
|
+
opacity: 0.25,
|
|
2658
|
+
duration: 0.3,
|
|
2659
|
+
yoyo: true,
|
|
2660
|
+
repeat: 1,
|
|
2661
|
+
ease: 'power2.out'
|
|
2662
|
+
});
|
|
2663
|
+
}
|
|
2664
|
+
});
|
|
2665
|
+
});
|
|
1942
2666
|
</script>
|
|
1943
2667
|
|
|
1944
2668
|
</body>
|