@touchzada/claudinho 0.1.7 → 0.1.10
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/GUIA_INICIO.md +836 -836
- package/README.md +288 -208
- package/bin/claudinho.cmd +2 -0
- package/dist/Landing/_prompts/loading-screen-analysis.md +227 -0
- package/dist/Landing/_prompts/prompt-loading-screen.md +43 -0
- package/dist/Landing/dark-landing-analysis.md +266 -0
- package/dist/Landing/index.html +1152 -0
- package/dist/Landing/index.v1.html +607 -0
- package/dist/Landing/index.v3.html +604 -0
- package/dist/Landing/index.v4.html +512 -0
- package/dist/Landing/index.v5.html +513 -0
- package/dist/cli.mjs +322 -242
- package/dist/cli.mjs.map +15 -15
- package/docs/advanced-setup.md +276 -276
- package/docs/quick-start-mac-linux.md +110 -110
- package/docs/quick-start-windows.md +106 -106
- package/package.json +2 -2
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# Loading Screen Technical Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Fullscreen loading screen with rotating text, animated counter, and progress bar. Uses Framer Motion for transitions and `requestAnimationFrame` for the counter.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Layout & Container
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
fixed inset-0
|
|
12
|
+
background: #0a0a0a (near-black)
|
|
13
|
+
z-index: above all content
|
|
14
|
+
font: Instrument Serif, italic
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The container uses CSS `position: fixed` with `inset: 0` to fill the viewport. Children are centered with flexbox.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Timing Sequence
|
|
22
|
+
|
|
23
|
+
| Phase | Duration | Description |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| Counter animation | 2700ms | 000 to 100 via rAF |
|
|
26
|
+
| Word rotation interval | 900ms | Each word displayed for 900ms |
|
|
27
|
+
| Post-complete delay | 400ms | Wait after counter hits 100 |
|
|
28
|
+
| **Total minimum** | **~3100ms** | Until `onComplete` fires |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Word Rotation (Framer Motion AnimatePresence)
|
|
33
|
+
|
|
34
|
+
- Words: `["Design", "Create", "Inspire"]`
|
|
35
|
+
- Cycle interval: 900ms per word via `setInterval` / `setTimeout`
|
|
36
|
+
- Animation: `AnimatePresence` with `mode="wait"` (ensures exit finishes before enter)
|
|
37
|
+
- Each word animates in and out; no crossfade overlap
|
|
38
|
+
|
|
39
|
+
Implementation pattern:
|
|
40
|
+
```tsx
|
|
41
|
+
function RotatingText({ words, intervalMs }) {
|
|
42
|
+
const [index, setIndex] = useState(0);
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const timer = setInterval(() => setIndex(i => (i + 1) % words.length), intervalMs);
|
|
46
|
+
return () => clearInterval(timer);
|
|
47
|
+
}, []);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<AnimatePresence mode="wait">
|
|
51
|
+
<motion.span
|
|
52
|
+
key={words[index]}
|
|
53
|
+
initial={{ opacity: 0, y: 20 }}
|
|
54
|
+
animate={{ opacity: 1, y: 0 }}
|
|
55
|
+
exit={{ opacity: 0, y: -20 }}
|
|
56
|
+
transition={{ duration: 0.4 }}
|
|
57
|
+
>
|
|
58
|
+
{words[index]}
|
|
59
|
+
</motion.span>
|
|
60
|
+
</AnimatePresence>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Counter Logic (requestAnimationFrame)
|
|
68
|
+
|
|
69
|
+
- Range: 0 to 100 (zero-padded to 3 digits: `000` to `100`)
|
|
70
|
+
- Duration: 2700ms
|
|
71
|
+
- Uses `requestAnimationFrame` for smooth 60fps updates
|
|
72
|
+
- Elapsed-time based calculation (not frame-count based) for accuracy
|
|
73
|
+
|
|
74
|
+
Core pattern:
|
|
75
|
+
```tsx
|
|
76
|
+
function Counter({ duration = 2700, onComplete }) {
|
|
77
|
+
const [count, setCount] = useState(0);
|
|
78
|
+
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
let startTime: number;
|
|
81
|
+
let rafId: number;
|
|
82
|
+
|
|
83
|
+
const animate = (timestamp: number) => {
|
|
84
|
+
if (!startTime) startTime = timestamp;
|
|
85
|
+
const elapsed = timestamp - startTime;
|
|
86
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
87
|
+
const value = Math.floor(progress * 100);
|
|
88
|
+
setCount(value);
|
|
89
|
+
|
|
90
|
+
if (progress < 1) {
|
|
91
|
+
rafId = requestAnimationFrame(animate);
|
|
92
|
+
} else {
|
|
93
|
+
// Reached 100
|
|
94
|
+
setTimeout(() => onComplete?.(), 400);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
rafId = requestAnimationFrame(animate);
|
|
99
|
+
return () => cancelAnimationFrame(rafId);
|
|
100
|
+
}, [duration, onComplete]);
|
|
101
|
+
|
|
102
|
+
return String(count).padStart(3, '0');
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Key details:
|
|
107
|
+
- Zero-padding via `String(count).padStart(3, '0')`
|
|
108
|
+
- Progress is `elapsed / duration`, clamped to max 1.0
|
|
109
|
+
- `Math.floor` ensures integer steps 0..100
|
|
110
|
+
- Cleanup cancels the rAF on unmount
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Progress Bar
|
|
115
|
+
|
|
116
|
+
- Position: fixed at bottom of viewport
|
|
117
|
+
- Fill uses linear gradient: `#89AACC -> #4E85BF` (light blue to darker blue)
|
|
118
|
+
- Glow effect applied (CSS `box-shadow` or `filter: drop-shadow`)
|
|
119
|
+
- Width animated from 0% to 100% in sync with counter (2700ms, linear easing)
|
|
120
|
+
|
|
121
|
+
Implementation pattern:
|
|
122
|
+
```tsx
|
|
123
|
+
function ProgressBar({ duration = 2700 }) {
|
|
124
|
+
const [width, setWidth] = useState(0);
|
|
125
|
+
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
let startTime: number;
|
|
128
|
+
let rafId: number;
|
|
129
|
+
|
|
130
|
+
const animate = (timestamp: number) => {
|
|
131
|
+
if (!startTime) startTime = timestamp;
|
|
132
|
+
const elapsed = timestamp - startTime;
|
|
133
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
134
|
+
setWidth(progress * 100);
|
|
135
|
+
|
|
136
|
+
if (progress < 1) {
|
|
137
|
+
rafId = requestAnimationFrame(animate);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
rafId = requestAnimationFrame(animate);
|
|
142
|
+
return () => cancelAnimationFrame(rafId);
|
|
143
|
+
}, [duration]);
|
|
144
|
+
|
|
145
|
+
return (
|
|
146
|
+
<div className="fixed bottom-0 left-0 right-0 h-1">
|
|
147
|
+
<div
|
|
148
|
+
style={{
|
|
149
|
+
width: `${width}%`,
|
|
150
|
+
height: '100%',
|
|
151
|
+
background: 'linear-gradient(90deg, #89AACC, #4E85BF)',
|
|
152
|
+
boxShadow: '0 0 8px rgba(137, 170, 204, 0.6)',
|
|
153
|
+
}}
|
|
154
|
+
/>
|
|
155
|
+
</div>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Exit Flow (Parent AnimatePresence)
|
|
163
|
+
|
|
164
|
+
The parent component wraps the loader and main page in `AnimatePresence` with `mode="wait"`:
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
function App() {
|
|
168
|
+
const [loaded, setLoaded] = useState(false);
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<AnimatePresence mode="wait">
|
|
172
|
+
{!loaded ? (
|
|
173
|
+
<LoadingScreen key="loader" onComplete={() => setLoaded(true)} />
|
|
174
|
+
) : (
|
|
175
|
+
<HomePage key="page" />
|
|
176
|
+
)}
|
|
177
|
+
</AnimatePresence>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
- `mode="wait"` ensures the loading screen exit animation completes before the page mounts
|
|
183
|
+
- Each child must have a unique `key` for AnimatePresence to track identity
|
|
184
|
+
- LoadingScreen triggers `onComplete` 400ms after counter reaches 100, causing state change
|
|
185
|
+
- React re-renders, AnimatePresence runs exit animation on loader, then mounts page
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Component Hierarchy
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
Parent (AnimatePresence mode="wait")
|
|
193
|
+
LoadingScreen (fixed inset-0, bg #0a0a0a)
|
|
194
|
+
Container (flex, centered)
|
|
195
|
+
RotatingText (AnimatePresence mode="wait", words cycle 900ms)
|
|
196
|
+
Counter (rAF, 0->100, 2700ms, padStart(3,'0'))
|
|
197
|
+
ProgressBar (fixed bottom, gradient #89AACC->#4E85BF, glow)
|
|
198
|
+
<-onComplete after 400ms delay->
|
|
199
|
+
PageContent (fades in)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Reusable Parameters
|
|
205
|
+
|
|
206
|
+
| Parameter | Default | Purpose |
|
|
207
|
+
|---|---|---|
|
|
208
|
+
| `backgroundColor` | `#0a0a0a` | Screen background |
|
|
209
|
+
| `fontFamily` | `Instrument Serif` | Typography |
|
|
210
|
+
| `fontStyle` | `italic` | Text weight |
|
|
211
|
+
| `counterDuration` | `2700ms` | 0-100 animation length |
|
|
212
|
+
| `wordInterval` | `900ms` | Text rotation speed |
|
|
213
|
+
| `words` | `["Design","Create","Inspire"]` | Rotating text array |
|
|
214
|
+
| `postCompleteDelay` | `400ms` | Delay before onComplete |
|
|
215
|
+
| `gradientStart` | `#89AACC` | Progress bar start color |
|
|
216
|
+
| `gradientEnd` | `#4E85BF` | Progress bar end color |
|
|
217
|
+
| `counterPadding` | `3` | Zero-pad digit count |
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Notes for Recreation
|
|
222
|
+
|
|
223
|
+
1. The counter and progress bar share the same duration (2700ms) and should use the same timing source for perfect sync
|
|
224
|
+
2. `AnimatePresence mode="wait"` is critical -- without it, the page would mount before the loader fully exits, causing a flash
|
|
225
|
+
3. The 400ms post-complete delay creates a natural pause that makes the transition feel intentional rather than abrupt
|
|
226
|
+
4. Word rotation continues throughout the entire counter animation; at 900ms intervals and 2700ms total, exactly 3 words cycle (one full rotation)
|
|
227
|
+
5. The glow on the progress bar uses a semi-transparent variant of the gradient start color (`rgba(137, 170, 204, 0.6)`)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Prompt 1: Loading Screen (Framer Motion + Counter)
|
|
2
|
+
|
|
3
|
+
Build a fullscreen loading screen component in React (Next.js 14, TypeScript). Uses Framer Motion for animations.
|
|
4
|
+
|
|
5
|
+
**Theme:**
|
|
6
|
+
- --bg: #0a0a0a; --text: #f5f5f5; --muted: #888888; --stroke: #1f1f1f
|
|
7
|
+
- Fonts: Instrument Serif (Google Fonts, italic, 400)
|
|
8
|
+
|
|
9
|
+
**Component: LoadingScreen**
|
|
10
|
+
- Receives one prop: onComplete: () => void
|
|
11
|
+
- Container: fixed inset-0 z-[9999] bg-bg. Exit animation: 0.6s, ease [0.4, 0, 0.2, 1]
|
|
12
|
+
|
|
13
|
+
**Element 1: Label (Top-Left)**
|
|
14
|
+
- "Portfolio" text, xs uppercase tracking-[0.3em]
|
|
15
|
+
- Entrance: y: -20 → 0, 0.6s, delay 0.1s
|
|
16
|
+
|
|
17
|
+
**Element 2: Rotating Words (Center)**
|
|
18
|
+
- Three words cycle: "Design" → "Create" → "Inspire" every 900ms
|
|
19
|
+
- Each is AnimatePresence mode="wait" keyed by wordIndex
|
|
20
|
+
- initial: {opacity:0, y:20} → animate: {opacity:1, y:0} → exit: {opacity:0, y:-20}
|
|
21
|
+
- Stops at last word (doesn't loop)
|
|
22
|
+
- text-4xl md:text-6xl lg:text-7xl italic serif text/80
|
|
23
|
+
|
|
24
|
+
**Element 3: Counter (Bottom-Right)**
|
|
25
|
+
- Counts 000 → 100 over 2.7s using requestAnimationFrame
|
|
26
|
+
- progress = elapsed / 2700 * 100
|
|
27
|
+
- Zero-padded to 3 digits
|
|
28
|
+
- text-6xl md:text-8xl lg:text-9xl serif tabular-nums
|
|
29
|
+
- When reaches 100: wait 400ms, then call onComplete()
|
|
30
|
+
|
|
31
|
+
**Element 4: Progress Bar (Bottom Edge)**
|
|
32
|
+
- 3px tall track, full width
|
|
33
|
+
- Fill: linear-gradient(90deg, #89AACC → #4E85BF), glow
|
|
34
|
+
- initial: scaleX 0, animate: scaleX: progress/100
|
|
35
|
+
|
|
36
|
+
**Timing:**
|
|
37
|
+
- 0.0s: Loader appears, brand slides in, counter starts, "Design"
|
|
38
|
+
- 0.9s: "Create" replaces "Design"
|
|
39
|
+
- 1.8s: "Inspire" replaces "Create"
|
|
40
|
+
- 2.7s: Counter hits 100, bar full
|
|
41
|
+
- 3.1s: onComplete fires (400ms pause)
|
|
42
|
+
- 3.1s: Loader fades out (0.6s exit)
|
|
43
|
+
- 3.7s: Page content fades in (0.5s)
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# Dark Landing Page — Technical Analysis
|
|
2
|
+
|
|
3
|
+
> Extracted from specification + existing `index.html` reference implementation.
|
|
4
|
+
> Target stack: React + Tailwind CSS v4 + Vite + hls.js + motion/react + lucide-react.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Design System
|
|
9
|
+
|
|
10
|
+
### Color Tokens
|
|
11
|
+
|
|
12
|
+
| Token | Value | Usage |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| `bg` | `#010101` | Page background (dark-first) |
|
|
15
|
+
| Primary gradient | `from-[#FA93FA] via-[#C967E8] to-[#983AD6]` | CTAs, accents, brand marks |
|
|
16
|
+
| Gradient text | white to purple/pink | H1 highlights, stat numbers |
|
|
17
|
+
| Glass border | `rgba(255,255,255,0.06-0.08)` | Card borders, navbar |
|
|
18
|
+
| Glass bg | `rgba(240,243,250,0.03-0.04)` | Card surfaces |
|
|
19
|
+
| Muted text | `hsl(240 5% 64.9%)` | Body copy, labels |
|
|
20
|
+
|
|
21
|
+
### Typography
|
|
22
|
+
|
|
23
|
+
- **Font:** Inter (via Google Fonts), fallback `system-ui, sans-serif`
|
|
24
|
+
- **Weights:** 400 (body), 500 (medium), 600 (semibold), 700 (bold), 800 (extrabold), 900 (black)
|
|
25
|
+
- **H1 scale:** `text-5xl / md:text-7xl / lg:text-8xl` with `font-black tracking-tight`
|
|
26
|
+
- **H2 scale:** `text-3xl / md:text-4xl / lg:text-5xl` with `font-bold`
|
|
27
|
+
- **Body:** `text-lg / md:text-xl text-muted-foreground`
|
|
28
|
+
|
|
29
|
+
### Animation Keyframes (all CSS-driven in current build; migrate to motion/react)
|
|
30
|
+
|
|
31
|
+
| Name | Duration | Easing | Purpose |
|
|
32
|
+
|---|---|---|---|
|
|
33
|
+
| `gradient-shift` | 4-15s ease infinite | Gradient position cycling |
|
|
34
|
+
| `float` | 6s ease-in-out | Decorative element hover |
|
|
35
|
+
| `pulse-glow` | 3s ease-in-out | Orb glow breathing |
|
|
36
|
+
| `slide-up` | 0.6s ease-out | Section entrance on scroll |
|
|
37
|
+
| `slide-in` | 0.4s ease-out | Horizontal entrance |
|
|
38
|
+
| `marquee` | 30s linear infinite | Logo/provider infinite scroll |
|
|
39
|
+
| `border-shimmer` | 3s linear infinite | Glass border glow sweep |
|
|
40
|
+
| `blink` | 1s step-end | Terminal cursor |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 2. Core Design Patterns
|
|
45
|
+
|
|
46
|
+
### 2.1 Glassmorphism
|
|
47
|
+
|
|
48
|
+
```css
|
|
49
|
+
.glass {
|
|
50
|
+
background: rgba(240, 243, 250, 0.03);
|
|
51
|
+
backdrop-filter: blur(16px);
|
|
52
|
+
border: 1px solid rgba(255, 255, 255, 0.06);
|
|
53
|
+
}
|
|
54
|
+
.glass-card {
|
|
55
|
+
background: rgba(240, 243, 250, 0.04);
|
|
56
|
+
backdrop-filter: blur(12px);
|
|
57
|
+
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
58
|
+
transition: all 0.3s ease;
|
|
59
|
+
}
|
|
60
|
+
.glass-card:hover {
|
|
61
|
+
background: rgba(240, 243, 250, 0.07);
|
|
62
|
+
border-color: rgba(167, 139, 250, 0.3);
|
|
63
|
+
transform: translateY(-4px);
|
|
64
|
+
box-shadow: 0 8px 32px rgba(167, 139, 250, 0.1);
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Usage:** navbar, feature cards, provider panels, terminal demo frame, CTA boxes, pill badges, provider tabs.
|
|
69
|
+
|
|
70
|
+
**Tailwind v4 equivalent:** `bg-black/20 backdrop-blur-sm border border-white/5`
|
|
71
|
+
|
|
72
|
+
### 2.2 Gradient Text
|
|
73
|
+
|
|
74
|
+
```css
|
|
75
|
+
.gradient-text {
|
|
76
|
+
background: linear-gradient(135deg, #a78bfa, #f472b6, #22d3ee);
|
|
77
|
+
background-size: 200% 200%;
|
|
78
|
+
animation: gradient-shift 4s ease infinite;
|
|
79
|
+
-webkit-background-clip: text;
|
|
80
|
+
-webkit-text-fill-color: transparent;
|
|
81
|
+
background-clip: text;
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Usage:** H1 sub-spans, stat numbers, provider name highlights.
|
|
86
|
+
|
|
87
|
+
**Spec gradient:** `from-[#FA93FA] via-[#C967E8] to-[#983AD6]` (newer pink-to-purple palette, replacing the current purple-pink-cyan).
|
|
88
|
+
|
|
89
|
+
### 2.3 Video Overlay (Hero)
|
|
90
|
+
|
|
91
|
+
- **Native `<video>` tag** (no react-player dependency)
|
|
92
|
+
- **HLS stream** via `hls.js` with MP4 fallback
|
|
93
|
+
- **mix-blend-screen** for light-on-dark compositing
|
|
94
|
+
- **Negative margin overlap:** `-mt-[150px]` pulls video up behind text content
|
|
95
|
+
- **Gradient overlay:** `from-[#010101] via-transparent to-[#010101]` fades video edges into bg
|
|
96
|
+
- **Z-index layering:** video at `z-0`, text content at `z-10` or higher
|
|
97
|
+
|
|
98
|
+
### 2.4 Infinite Slider (Logo Cloud / Provider Marquee)
|
|
99
|
+
|
|
100
|
+
```css
|
|
101
|
+
.marquee-track {
|
|
102
|
+
animation: marquee 30s linear infinite;
|
|
103
|
+
}
|
|
104
|
+
@keyframes marquee {
|
|
105
|
+
0% { transform: translateX(0); }
|
|
106
|
+
100% { transform: translateX(-50%); }
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Implementation detail:** Content is duplicated (rendered twice) inside a `whitespace-nowrap` container. The CSS animation translates X from 0 to -50%, then snaps back to 0, creating a seamless loop.
|
|
111
|
+
|
|
112
|
+
**Styling:** `bg-black/20 backdrop-blur-sm` glass surface, `border-y border-white/5`.
|
|
113
|
+
|
|
114
|
+
**Brands referenced:** OpenAI, Nvidia, GitHub, etc. with SVG logos or text pills.
|
|
115
|
+
|
|
116
|
+
**motion/react migration:** Consider `motion.div` with `animate={{ x: ["0%", "-50%"] }}` for smoother control and pause-on-hover.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 3. Layout Decisions
|
|
121
|
+
|
|
122
|
+
### 3.1 Negative Margin Overlap
|
|
123
|
+
|
|
124
|
+
The hero uses `-mt-[150px]` on the video element to create a layered composition where the video bleeds behind the text content. This produces depth without requiring absolute positioning for the text layer.
|
|
125
|
+
|
|
126
|
+
### 3.2 Z-Index Layering
|
|
127
|
+
|
|
128
|
+
| Layer | Z-index | Element |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| Background orbs | `z-0` | Decorative blurred circles |
|
|
131
|
+
| Video | `z-0` | Hero video (mix-blend-screen) |
|
|
132
|
+
| Content | `z-10` | Hero text, CTAs, stats |
|
|
133
|
+
| Navbar | `z-50` | Fixed top navigation |
|
|
134
|
+
| Gradient overlay | `z-[1]` | Video-to-bg fade |
|
|
135
|
+
|
|
136
|
+
### 3.3 Section Spacing
|
|
137
|
+
|
|
138
|
+
- All sections: `py-24` (~96px vertical padding)
|
|
139
|
+
- Max content width: `max-w-7xl` (80rem / 1280px) or `max-w-4xl` for focused sections
|
|
140
|
+
- Grid gaps: `gap-6` for cards, `gap-3` for compact items
|
|
141
|
+
- Responsive breakpoints: `md:` (768px) for 2-col, `lg:` (1024px) for 3-4 col
|
|
142
|
+
|
|
143
|
+
### 3.4 Responsive Grid Patterns
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
Features: grid-cols-1 → md:grid-cols-2 → lg:grid-cols-3
|
|
147
|
+
Tools: grid-cols-2 → md:grid-cols-4 → lg:grid-cols-6
|
|
148
|
+
Commands: grid-cols-1 → md:grid-cols-2 → lg:grid-cols-4
|
|
149
|
+
Stats: grid-cols-2 → md:grid-cols-4
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 4. Component Architecture
|
|
155
|
+
|
|
156
|
+
### 4.1 Proposed File Structure
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
src/
|
|
160
|
+
App.tsx # Root layout, scroll sections
|
|
161
|
+
components/
|
|
162
|
+
Hero.tsx # Announcement pill, H1, CTA, video, stats
|
|
163
|
+
InfiniteSlider.tsx # Marquee logo/provider cloud
|
|
164
|
+
Navbar.tsx # Fixed glass nav with links
|
|
165
|
+
Features.tsx # Feature card grid
|
|
166
|
+
ProviderTabs.tsx # Interactive provider selector
|
|
167
|
+
TerminalDemo.tsx # Animated terminal window
|
|
168
|
+
ToolsGrid.tsx # Tool icon grid
|
|
169
|
+
CommandsGrid.tsx # Slash command pills
|
|
170
|
+
ArchitectureCards.tsx # Technical stats
|
|
171
|
+
SecurityCards.tsx # Vulnerability audit display
|
|
172
|
+
CTASection.tsx # Final call-to-action + install code
|
|
173
|
+
Footer.tsx # Copyright, links
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 4.2 Hero.tsx Responsibilities
|
|
177
|
+
|
|
178
|
+
1. **Announcement pill** — gradient glow box, Zap icon (lucide), "Used by founders. Loved by devs."
|
|
179
|
+
2. **H1 heading** — "Your Vision / Our Digital Reality." with gradient text on secondary line
|
|
180
|
+
3. **Subheadline** — turning bold ideas into modern designs
|
|
181
|
+
4. **CTA button** — "Book a 15-min call", white bg, black text, glass border
|
|
182
|
+
5. **Video element** — native `<video>` with hls.js initialization, MP4 fallback, `mix-blend-screen`, `-mt-[150px]`, gradient overlay
|
|
183
|
+
6. **Scroll indicator** — animated chevron or line
|
|
184
|
+
|
|
185
|
+
### 4.3 InfiniteSlider.tsx Responsibilities
|
|
186
|
+
|
|
187
|
+
- Accepts `logos: { src: string; alt: string; width: number }[]`
|
|
188
|
+
- Renders duplicated set for seamless loop
|
|
189
|
+
- Glass surface: `bg-black/20 backdrop-blur-sm`
|
|
190
|
+
- Label: "Powering the best teams"
|
|
191
|
+
- motion/react: consider `AnimatePresence` for hover states
|
|
192
|
+
|
|
193
|
+
### 4.4 State Management
|
|
194
|
+
|
|
195
|
+
- **Provider selector:** `useState<string>` for active tab, `AnimatePresence` for card transitions
|
|
196
|
+
- **Scroll animations:** `IntersectionObserver` or motion/react `whileInView`
|
|
197
|
+
- **Video:** HLS instance stored in `useRef`, initialized on mount, destroyed on unmount
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## 5. Technical Requirements
|
|
202
|
+
|
|
203
|
+
### 5.1 Dependencies
|
|
204
|
+
|
|
205
|
+
| Package | Purpose |
|
|
206
|
+
|---|---|
|
|
207
|
+
| `react` ^19 | UI framework |
|
|
208
|
+
| `tailwindcss` ^4 | Styling engine |
|
|
209
|
+
| `vite` | Build tool |
|
|
210
|
+
| `hls.js` | HLS video streaming |
|
|
211
|
+
| `motion/react` | Animations (Framer Motion v12) |
|
|
212
|
+
| `lucide-react` | Icon library |
|
|
213
|
+
|
|
214
|
+
### 5.2 Video Handling
|
|
215
|
+
|
|
216
|
+
- Use native `<video>` element (no react-player)
|
|
217
|
+
- Initialize `hls.js` in `useEffect` on video ref mount
|
|
218
|
+
- Check `Hls.isSupported()` before instantiating
|
|
219
|
+
- Set `src` to fallback MP4 for browsers with native HLS (Safari)
|
|
220
|
+
- Clean up `hls.destroy()` on component unmount
|
|
221
|
+
- Apply `mix-blend-screen` CSS class for compositing
|
|
222
|
+
- Parent container: `overflow-hidden` to contain negative margin bleed
|
|
223
|
+
|
|
224
|
+
### 5.3 Animation Strategy
|
|
225
|
+
|
|
226
|
+
**Prefer motion/react over CSS keyframes** for React components:
|
|
227
|
+
- `motion.div` with `initial/animate/exit` for section entrances
|
|
228
|
+
- `whileInView` + `viewport={{ once: true }}` for scroll-triggered reveals
|
|
229
|
+
- `layout` prop for provider card transitions
|
|
230
|
+
- `AnimatePresence` for crossfade between provider detail panels
|
|
231
|
+
- CSS keyframes only for: marquee infinite loop, cursor blink, background gradient shift
|
|
232
|
+
|
|
233
|
+
### 5.4 Accessibility
|
|
234
|
+
|
|
235
|
+
- All `lucide-react` icons need `aria-hidden` or `title` props
|
|
236
|
+
- Video element: `playsInline muted loop autoPlay` with fallback content
|
|
237
|
+
- Focus states on interactive elements (CTA buttons, provider tabs)
|
|
238
|
+
- Semantic HTML: `<section>`, `<nav>`, `<main>`, `<h1>`-`<h4>` hierarchy
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## 6. Risks & Gotchas
|
|
243
|
+
|
|
244
|
+
| Risk | Mitigation |
|
|
245
|
+
|---|---|
|
|
246
|
+
| HLS not supported in Safari natively via hls.js | Use native `<video src>` fallback for Safari (it supports HLS natively) |
|
|
247
|
+
| `mix-blend-screen` behavior varies across browsers | Test on Chrome, Firefox, Safari; fallback to `opacity` if needed |
|
|
248
|
+
| Negative margin `-mt-[150px]` may cause overflow clipping | Ensure parent has `overflow-hidden`, not `overflow-auto` |
|
|
249
|
+
| Marquee animation jank on low-end devices | Use `will-change: transform` or `transform: translate3d()` for GPU compositing |
|
|
250
|
+
| Tailwind v4 syntax differs from v3 | v4 uses CSS-first config; `@theme` directive instead of `tailwind.config.js` |
|
|
251
|
+
| motion/react bundle size | Tree-shake properly; only import needed components |
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## 7. Quick-Reference: Key Tailwind Utilities
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
Glass card: bg-black/20 backdrop-blur-sm border border-white/5 rounded-xl
|
|
259
|
+
Gradient text: bg-gradient-to-r from-[#FA93FA] via-[#C967E8] to-[#983AD6] bg-clip-text text-transparent
|
|
260
|
+
CTA button: bg-white text-black glass border border-white/10 hover:bg-white/90
|
|
261
|
+
Glass border: border border-white/5 or border-white/10
|
|
262
|
+
Section: py-24 max-w-7xl mx-auto px-6
|
|
263
|
+
Nav: fixed inset-x-0 top-0 z-50 glass border-b border-white/5
|
|
264
|
+
Video wrapper: relative overflow-hidden -mt-[150px]
|
|
265
|
+
Orb decoration: absolute w-64 h-64 rounded-full blur-[100px] opacity-10
|
|
266
|
+
```
|