@soederpop/luca 0.2.1 → 0.2.2
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/.github/workflows/release.yaml +2 -0
- package/CNAME +1 -0
- package/docs/CNAME +1 -0
- package/index.html +1430 -0
- package/package.json +1 -1
- package/src/bootstrap/generated.ts +1 -1
- package/src/cli/build-info.ts +2 -2
- package/src/introspection/generated.agi.ts +1805 -1018
- package/src/introspection/generated.node.ts +862 -95
- package/src/introspection/generated.web.ts +1 -1
- package/src/python/generated.ts +1 -1
- package/src/scaffolds/generated.ts +1 -1
package/index.html
ADDED
|
@@ -0,0 +1,1430 @@
|
|
|
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>Luca — One Container, Everything You Need</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=Sora:wght@300;400;500;600;700;800&family=IBM+Plex+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
|
10
|
+
<style>
|
|
11
|
+
/* ============ THEME (dark-first) ============ */
|
|
12
|
+
:root {
|
|
13
|
+
--font-body: 'Sora', system-ui, sans-serif;
|
|
14
|
+
--font-mono: 'IBM Plex Mono', 'SF Mono', Consolas, monospace;
|
|
15
|
+
|
|
16
|
+
--bg: #09090b;
|
|
17
|
+
--bg-subtle: #0f0f13;
|
|
18
|
+
--surface: #131318;
|
|
19
|
+
--surface2: #1a1a22;
|
|
20
|
+
--surface-elevated: #1f1f2a;
|
|
21
|
+
--border: rgba(255, 255, 255, 0.06);
|
|
22
|
+
--border-bright: rgba(255, 255, 255, 0.12);
|
|
23
|
+
--text: #ececf1;
|
|
24
|
+
--text-dim: #71717a;
|
|
25
|
+
--text-muted: #52525b;
|
|
26
|
+
|
|
27
|
+
--cyan: #06b6d4;
|
|
28
|
+
--cyan-bright: #22d3ee;
|
|
29
|
+
--cyan-dim: rgba(6, 182, 212, 0.12);
|
|
30
|
+
--cyan-glow: rgba(6, 182, 212, 0.25);
|
|
31
|
+
|
|
32
|
+
--purple: #a855f7;
|
|
33
|
+
--purple-bright: #c084fc;
|
|
34
|
+
--purple-dim: rgba(168, 85, 247, 0.12);
|
|
35
|
+
|
|
36
|
+
--amber: #f59e0b;
|
|
37
|
+
--amber-bright: #fbbf24;
|
|
38
|
+
--amber-dim: rgba(245, 158, 11, 0.1);
|
|
39
|
+
|
|
40
|
+
--green: #10b981;
|
|
41
|
+
--green-dim: rgba(16, 185, 129, 0.1);
|
|
42
|
+
|
|
43
|
+
--rose: #f43f5e;
|
|
44
|
+
--rose-dim: rgba(244, 63, 94, 0.1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@media (prefers-color-scheme: light) {
|
|
48
|
+
:root {
|
|
49
|
+
--bg: #fafafa;
|
|
50
|
+
--bg-subtle: #f4f4f5;
|
|
51
|
+
--surface: #ffffff;
|
|
52
|
+
--surface2: #f4f4f5;
|
|
53
|
+
--surface-elevated: #ffffff;
|
|
54
|
+
--border: rgba(0, 0, 0, 0.07);
|
|
55
|
+
--border-bright: rgba(0, 0, 0, 0.14);
|
|
56
|
+
--text: #18181b;
|
|
57
|
+
--text-dim: #71717a;
|
|
58
|
+
--text-muted: #a1a1aa;
|
|
59
|
+
--cyan: #0891b2;
|
|
60
|
+
--cyan-bright: #06b6d4;
|
|
61
|
+
--cyan-dim: rgba(8, 145, 178, 0.08);
|
|
62
|
+
--cyan-glow: rgba(8, 145, 178, 0.15);
|
|
63
|
+
--purple: #9333ea;
|
|
64
|
+
--purple-bright: #a855f7;
|
|
65
|
+
--purple-dim: rgba(147, 51, 234, 0.08);
|
|
66
|
+
--amber: #d97706;
|
|
67
|
+
--amber-bright: #f59e0b;
|
|
68
|
+
--amber-dim: rgba(217, 119, 6, 0.08);
|
|
69
|
+
--green: #059669;
|
|
70
|
+
--green-dim: rgba(5, 150, 105, 0.08);
|
|
71
|
+
--rose: #e11d48;
|
|
72
|
+
--rose-dim: rgba(225, 29, 72, 0.08);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* ============ RESET ============ */
|
|
77
|
+
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
|
78
|
+
html { scroll-behavior: smooth; }
|
|
79
|
+
|
|
80
|
+
body {
|
|
81
|
+
background: var(--bg);
|
|
82
|
+
color: var(--text);
|
|
83
|
+
font-family: var(--font-body);
|
|
84
|
+
line-height: 1.6;
|
|
85
|
+
overflow-x: hidden;
|
|
86
|
+
-webkit-font-smoothing: antialiased;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* ============ BACKGROUND ATMOSPHERE ============ */
|
|
90
|
+
body::before {
|
|
91
|
+
content: '';
|
|
92
|
+
position: fixed;
|
|
93
|
+
inset: 0;
|
|
94
|
+
background:
|
|
95
|
+
radial-gradient(ellipse 80% 50% at 50% -10%, var(--cyan-glow) 0%, transparent 60%),
|
|
96
|
+
radial-gradient(ellipse 60% 40% at 80% 50%, var(--purple-dim) 0%, transparent 50%),
|
|
97
|
+
radial-gradient(ellipse 50% 30% at 10% 80%, var(--amber-dim) 0%, transparent 40%);
|
|
98
|
+
pointer-events: none;
|
|
99
|
+
z-index: 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Dot grid overlay */
|
|
103
|
+
body::after {
|
|
104
|
+
content: '';
|
|
105
|
+
position: fixed;
|
|
106
|
+
inset: 0;
|
|
107
|
+
background-image: radial-gradient(circle, var(--border) 0.5px, transparent 0.5px);
|
|
108
|
+
background-size: 32px 32px;
|
|
109
|
+
pointer-events: none;
|
|
110
|
+
z-index: 0;
|
|
111
|
+
opacity: 0.5;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* ============ ANIMATIONS ============ */
|
|
115
|
+
@keyframes fadeUp {
|
|
116
|
+
from { opacity: 0; transform: translateY(20px); }
|
|
117
|
+
to { opacity: 1; transform: translateY(0); }
|
|
118
|
+
}
|
|
119
|
+
@keyframes fadeScale {
|
|
120
|
+
from { opacity: 0; transform: scale(0.95); }
|
|
121
|
+
to { opacity: 1; transform: scale(1); }
|
|
122
|
+
}
|
|
123
|
+
@keyframes float {
|
|
124
|
+
0%, 100% { transform: translateY(0); }
|
|
125
|
+
50% { transform: translateY(-6px); }
|
|
126
|
+
}
|
|
127
|
+
@keyframes pulse-glow {
|
|
128
|
+
0%, 100% { box-shadow: 0 0 20px var(--cyan-dim), 0 0 60px rgba(6,182,212,0.05); }
|
|
129
|
+
50% { box-shadow: 0 0 30px var(--cyan-glow), 0 0 80px rgba(6,182,212,0.1); }
|
|
130
|
+
}
|
|
131
|
+
@keyframes gradient-shift {
|
|
132
|
+
0% { background-position: 0% 50%; }
|
|
133
|
+
50% { background-position: 100% 50%; }
|
|
134
|
+
100% { background-position: 0% 50%; }
|
|
135
|
+
}
|
|
136
|
+
@keyframes typing {
|
|
137
|
+
from { width: 0; }
|
|
138
|
+
to { width: 100%; }
|
|
139
|
+
}
|
|
140
|
+
@keyframes blink {
|
|
141
|
+
50% { border-color: transparent; }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.anim { animation: fadeUp 0.5s ease-out both; animation-delay: calc(var(--i, 0) * 0.08s); }
|
|
145
|
+
.anim-scale { animation: fadeScale 0.4s ease-out both; animation-delay: calc(var(--i, 0) * 0.06s); }
|
|
146
|
+
|
|
147
|
+
@media (prefers-reduced-motion: reduce) {
|
|
148
|
+
*, *::before, *::after {
|
|
149
|
+
animation-duration: 0.01ms !important;
|
|
150
|
+
animation-delay: 0ms !important;
|
|
151
|
+
transition-duration: 0.01ms !important;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* ============ LAYOUT ============ */
|
|
156
|
+
.wrap {
|
|
157
|
+
max-width: 1200px;
|
|
158
|
+
margin: 0 auto;
|
|
159
|
+
padding: 0 40px;
|
|
160
|
+
position: relative;
|
|
161
|
+
z-index: 1;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
section { padding: 100px 0; }
|
|
165
|
+
|
|
166
|
+
/* ============ NAV ============ */
|
|
167
|
+
nav {
|
|
168
|
+
position: fixed;
|
|
169
|
+
top: 0;
|
|
170
|
+
left: 0;
|
|
171
|
+
right: 0;
|
|
172
|
+
z-index: 100;
|
|
173
|
+
padding: 0 40px;
|
|
174
|
+
backdrop-filter: blur(16px) saturate(1.4);
|
|
175
|
+
-webkit-backdrop-filter: blur(16px) saturate(1.4);
|
|
176
|
+
background: color-mix(in srgb, var(--bg) 80%, transparent);
|
|
177
|
+
border-bottom: 1px solid var(--border);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
nav .nav-inner {
|
|
181
|
+
max-width: 1200px;
|
|
182
|
+
margin: 0 auto;
|
|
183
|
+
display: flex;
|
|
184
|
+
align-items: center;
|
|
185
|
+
justify-content: space-between;
|
|
186
|
+
height: 60px;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.nav-logo {
|
|
190
|
+
font-weight: 800;
|
|
191
|
+
font-size: 20px;
|
|
192
|
+
letter-spacing: -0.5px;
|
|
193
|
+
display: flex;
|
|
194
|
+
align-items: center;
|
|
195
|
+
gap: 8px;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.nav-logo .logo-mark {
|
|
199
|
+
width: 28px;
|
|
200
|
+
height: 28px;
|
|
201
|
+
border-radius: 7px;
|
|
202
|
+
background: linear-gradient(135deg, var(--cyan), var(--purple));
|
|
203
|
+
display: flex;
|
|
204
|
+
align-items: center;
|
|
205
|
+
justify-content: center;
|
|
206
|
+
font-size: 14px;
|
|
207
|
+
font-weight: 700;
|
|
208
|
+
color: white;
|
|
209
|
+
font-family: var(--font-mono);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.nav-links {
|
|
213
|
+
display: flex;
|
|
214
|
+
gap: 8px;
|
|
215
|
+
list-style: none;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.nav-links a {
|
|
219
|
+
font-size: 13px;
|
|
220
|
+
font-weight: 500;
|
|
221
|
+
color: var(--text-dim);
|
|
222
|
+
text-decoration: none;
|
|
223
|
+
padding: 6px 14px;
|
|
224
|
+
border-radius: 6px;
|
|
225
|
+
transition: all 0.2s;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.nav-links a:hover { color: var(--text); background: var(--border); }
|
|
229
|
+
.nav-links a.active { color: var(--cyan-bright); }
|
|
230
|
+
|
|
231
|
+
.nav-cta {
|
|
232
|
+
font-size: 13px;
|
|
233
|
+
font-weight: 600;
|
|
234
|
+
color: var(--bg) !important;
|
|
235
|
+
background: linear-gradient(135deg, var(--cyan), var(--cyan-bright));
|
|
236
|
+
padding: 8px 20px !important;
|
|
237
|
+
border-radius: 8px !important;
|
|
238
|
+
transition: all 0.2s !important;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.nav-cta:hover {
|
|
242
|
+
opacity: 0.9;
|
|
243
|
+
transform: translateY(-1px);
|
|
244
|
+
color: var(--bg) !important;
|
|
245
|
+
background: linear-gradient(135deg, var(--cyan), var(--cyan-bright)) !important;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/* ============ HERO ============ */
|
|
249
|
+
.hero {
|
|
250
|
+
padding-top: 160px;
|
|
251
|
+
padding-bottom: 80px;
|
|
252
|
+
text-align: center;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.hero-badge {
|
|
256
|
+
display: inline-flex;
|
|
257
|
+
align-items: center;
|
|
258
|
+
gap: 8px;
|
|
259
|
+
padding: 6px 16px;
|
|
260
|
+
border-radius: 100px;
|
|
261
|
+
background: var(--cyan-dim);
|
|
262
|
+
border: 1px solid color-mix(in srgb, var(--cyan) 30%, transparent);
|
|
263
|
+
font-family: var(--font-mono);
|
|
264
|
+
font-size: 12px;
|
|
265
|
+
font-weight: 500;
|
|
266
|
+
color: var(--cyan-bright);
|
|
267
|
+
margin-bottom: 32px;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.hero-badge .dot {
|
|
271
|
+
width: 6px;
|
|
272
|
+
height: 6px;
|
|
273
|
+
border-radius: 50%;
|
|
274
|
+
background: var(--cyan-bright);
|
|
275
|
+
animation: pulse-glow 2s ease-in-out infinite;
|
|
276
|
+
box-shadow: 0 0 6px var(--cyan);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.hero h1 {
|
|
280
|
+
font-size: clamp(40px, 6vw, 72px);
|
|
281
|
+
font-weight: 800;
|
|
282
|
+
letter-spacing: -2px;
|
|
283
|
+
line-height: 1.05;
|
|
284
|
+
margin-bottom: 24px;
|
|
285
|
+
text-wrap: balance;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.hero h1 .gradient-text {
|
|
289
|
+
background: linear-gradient(135deg, var(--cyan-bright), var(--purple-bright), var(--amber-bright));
|
|
290
|
+
background-size: 200% 200%;
|
|
291
|
+
-webkit-background-clip: text;
|
|
292
|
+
-webkit-text-fill-color: transparent;
|
|
293
|
+
background-clip: text;
|
|
294
|
+
animation: gradient-shift 4s ease-in-out infinite;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.hero-sub {
|
|
298
|
+
font-size: clamp(16px, 2vw, 20px);
|
|
299
|
+
color: var(--text-dim);
|
|
300
|
+
max-width: 600px;
|
|
301
|
+
margin: 0 auto 48px;
|
|
302
|
+
font-weight: 400;
|
|
303
|
+
line-height: 1.6;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.hero-actions {
|
|
307
|
+
display: flex;
|
|
308
|
+
gap: 16px;
|
|
309
|
+
justify-content: center;
|
|
310
|
+
flex-wrap: wrap;
|
|
311
|
+
margin-bottom: 64px;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.btn {
|
|
315
|
+
display: inline-flex;
|
|
316
|
+
align-items: center;
|
|
317
|
+
gap: 8px;
|
|
318
|
+
padding: 14px 28px;
|
|
319
|
+
border-radius: 12px;
|
|
320
|
+
font-size: 15px;
|
|
321
|
+
font-weight: 600;
|
|
322
|
+
text-decoration: none;
|
|
323
|
+
transition: all 0.25s;
|
|
324
|
+
cursor: pointer;
|
|
325
|
+
border: none;
|
|
326
|
+
font-family: var(--font-body);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.btn-primary {
|
|
330
|
+
background: linear-gradient(135deg, var(--cyan), color-mix(in srgb, var(--cyan) 80%, var(--purple)));
|
|
331
|
+
color: #000;
|
|
332
|
+
box-shadow: 0 4px 20px var(--cyan-dim), 0 0 60px rgba(6,182,212,0.08);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.btn-primary:hover {
|
|
336
|
+
transform: translateY(-2px);
|
|
337
|
+
box-shadow: 0 6px 30px var(--cyan-glow), 0 0 80px rgba(6,182,212,0.12);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.btn-secondary {
|
|
341
|
+
background: var(--surface2);
|
|
342
|
+
color: var(--text);
|
|
343
|
+
border: 1px solid var(--border-bright);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.btn-secondary:hover {
|
|
347
|
+
transform: translateY(-2px);
|
|
348
|
+
background: var(--surface-elevated);
|
|
349
|
+
border-color: var(--cyan);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/* ============ TERMINAL ============ */
|
|
353
|
+
.terminal {
|
|
354
|
+
background: var(--surface);
|
|
355
|
+
border: 1px solid var(--border-bright);
|
|
356
|
+
border-radius: 16px;
|
|
357
|
+
max-width: 720px;
|
|
358
|
+
margin: 0 auto;
|
|
359
|
+
overflow: hidden;
|
|
360
|
+
text-align: left;
|
|
361
|
+
box-shadow:
|
|
362
|
+
0 0 0 1px var(--border),
|
|
363
|
+
0 20px 60px rgba(0, 0, 0, 0.4),
|
|
364
|
+
0 0 100px var(--cyan-dim);
|
|
365
|
+
animation: pulse-glow 3s ease-in-out infinite;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.terminal-bar {
|
|
369
|
+
display: flex;
|
|
370
|
+
align-items: center;
|
|
371
|
+
gap: 8px;
|
|
372
|
+
padding: 14px 20px;
|
|
373
|
+
border-bottom: 1px solid var(--border);
|
|
374
|
+
background: var(--surface2);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.terminal-dot {
|
|
378
|
+
width: 12px;
|
|
379
|
+
height: 12px;
|
|
380
|
+
border-radius: 50%;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.terminal-dot:nth-child(1) { background: #ff5f57; }
|
|
384
|
+
.terminal-dot:nth-child(2) { background: #febc2e; }
|
|
385
|
+
.terminal-dot:nth-child(3) { background: #28c840; }
|
|
386
|
+
|
|
387
|
+
.terminal-title {
|
|
388
|
+
flex: 1;
|
|
389
|
+
text-align: center;
|
|
390
|
+
font-family: var(--font-mono);
|
|
391
|
+
font-size: 12px;
|
|
392
|
+
color: var(--text-muted);
|
|
393
|
+
margin-right: 44px;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.terminal-body {
|
|
397
|
+
padding: 24px;
|
|
398
|
+
font-family: var(--font-mono);
|
|
399
|
+
font-size: 13px;
|
|
400
|
+
line-height: 2;
|
|
401
|
+
overflow-x: auto;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.terminal-body .line {
|
|
405
|
+
white-space: nowrap;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.t-prompt { color: var(--cyan-bright); }
|
|
409
|
+
.t-cmd { color: var(--text); }
|
|
410
|
+
.t-flag { color: var(--purple-bright); }
|
|
411
|
+
.t-str { color: var(--amber-bright); }
|
|
412
|
+
.t-comment { color: var(--text-muted); font-style: italic; }
|
|
413
|
+
.t-output { color: var(--text-dim); }
|
|
414
|
+
.t-key { color: var(--cyan-bright); }
|
|
415
|
+
.t-val { color: var(--green); }
|
|
416
|
+
.t-method { color: var(--purple-bright); }
|
|
417
|
+
.t-bracket { color: var(--text-dim); }
|
|
418
|
+
.t-kw { color: var(--rose); }
|
|
419
|
+
.t-fn { color: var(--amber-bright); }
|
|
420
|
+
|
|
421
|
+
/* ============ SECTION HEADERS ============ */
|
|
422
|
+
.sec-label {
|
|
423
|
+
font-family: var(--font-mono);
|
|
424
|
+
font-size: 12px;
|
|
425
|
+
font-weight: 600;
|
|
426
|
+
text-transform: uppercase;
|
|
427
|
+
letter-spacing: 2px;
|
|
428
|
+
color: var(--cyan);
|
|
429
|
+
margin-bottom: 16px;
|
|
430
|
+
display: flex;
|
|
431
|
+
align-items: center;
|
|
432
|
+
gap: 10px;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
.sec-label::before {
|
|
436
|
+
content: '';
|
|
437
|
+
width: 20px;
|
|
438
|
+
height: 1px;
|
|
439
|
+
background: var(--cyan);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.sec-title {
|
|
443
|
+
font-size: clamp(28px, 4vw, 44px);
|
|
444
|
+
font-weight: 700;
|
|
445
|
+
letter-spacing: -1.5px;
|
|
446
|
+
margin-bottom: 16px;
|
|
447
|
+
text-wrap: balance;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.sec-desc {
|
|
451
|
+
font-size: 17px;
|
|
452
|
+
color: var(--text-dim);
|
|
453
|
+
max-width: 600px;
|
|
454
|
+
margin-bottom: 56px;
|
|
455
|
+
line-height: 1.7;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/* ============ FEATURES GRID ============ */
|
|
459
|
+
.features-grid {
|
|
460
|
+
display: grid;
|
|
461
|
+
grid-template-columns: repeat(3, 1fr);
|
|
462
|
+
gap: 16px;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.feature-card {
|
|
466
|
+
background: var(--surface);
|
|
467
|
+
border: 1px solid var(--border);
|
|
468
|
+
border-radius: 16px;
|
|
469
|
+
padding: 28px;
|
|
470
|
+
transition: all 0.3s;
|
|
471
|
+
position: relative;
|
|
472
|
+
overflow: hidden;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
.feature-card::before {
|
|
476
|
+
content: '';
|
|
477
|
+
position: absolute;
|
|
478
|
+
top: 0;
|
|
479
|
+
left: 0;
|
|
480
|
+
right: 0;
|
|
481
|
+
height: 2px;
|
|
482
|
+
background: linear-gradient(90deg, var(--card-accent, var(--cyan)), transparent);
|
|
483
|
+
opacity: 0;
|
|
484
|
+
transition: opacity 0.3s;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
.feature-card:hover {
|
|
488
|
+
border-color: var(--border-bright);
|
|
489
|
+
transform: translateY(-2px);
|
|
490
|
+
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
.feature-card:hover::before { opacity: 1; }
|
|
494
|
+
|
|
495
|
+
.feature-icon {
|
|
496
|
+
width: 44px;
|
|
497
|
+
height: 44px;
|
|
498
|
+
border-radius: 12px;
|
|
499
|
+
display: flex;
|
|
500
|
+
align-items: center;
|
|
501
|
+
justify-content: center;
|
|
502
|
+
font-size: 20px;
|
|
503
|
+
margin-bottom: 18px;
|
|
504
|
+
background: var(--icon-bg, var(--cyan-dim));
|
|
505
|
+
color: var(--icon-color, var(--cyan-bright));
|
|
506
|
+
border: 1px solid color-mix(in srgb, var(--icon-color, var(--cyan)) 20%, transparent);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
.feature-card h3 {
|
|
510
|
+
font-size: 16px;
|
|
511
|
+
font-weight: 600;
|
|
512
|
+
margin-bottom: 8px;
|
|
513
|
+
letter-spacing: -0.3px;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
.feature-card p {
|
|
517
|
+
font-size: 13px;
|
|
518
|
+
color: var(--text-dim);
|
|
519
|
+
line-height: 1.6;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
.feature-card code {
|
|
523
|
+
font-family: var(--font-mono);
|
|
524
|
+
font-size: 11px;
|
|
525
|
+
background: var(--cyan-dim);
|
|
526
|
+
color: var(--cyan-bright);
|
|
527
|
+
padding: 2px 6px;
|
|
528
|
+
border-radius: 4px;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/* Feature card color variants */
|
|
532
|
+
.fc-cyan { --card-accent: var(--cyan); --icon-bg: var(--cyan-dim); --icon-color: var(--cyan-bright); }
|
|
533
|
+
.fc-purple { --card-accent: var(--purple); --icon-bg: var(--purple-dim); --icon-color: var(--purple-bright); }
|
|
534
|
+
.fc-amber { --card-accent: var(--amber); --icon-bg: var(--amber-dim); --icon-color: var(--amber-bright); }
|
|
535
|
+
.fc-green { --card-accent: var(--green); --icon-bg: var(--green-dim); --icon-color: var(--green); }
|
|
536
|
+
.fc-rose { --card-accent: var(--rose); --icon-bg: var(--rose-dim); --icon-color: var(--rose); }
|
|
537
|
+
|
|
538
|
+
/* ============ ARCHITECTURE ============ */
|
|
539
|
+
.arch-visual {
|
|
540
|
+
background: var(--surface);
|
|
541
|
+
border: 1px solid var(--border);
|
|
542
|
+
border-radius: 20px;
|
|
543
|
+
padding: 48px 40px;
|
|
544
|
+
position: relative;
|
|
545
|
+
overflow: hidden;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
.arch-visual::before {
|
|
549
|
+
content: '';
|
|
550
|
+
position: absolute;
|
|
551
|
+
inset: 0;
|
|
552
|
+
background:
|
|
553
|
+
radial-gradient(ellipse at 50% 30%, var(--cyan-dim) 0%, transparent 60%),
|
|
554
|
+
radial-gradient(ellipse at 20% 80%, var(--purple-dim) 0%, transparent 40%);
|
|
555
|
+
pointer-events: none;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
.arch-container-box {
|
|
559
|
+
position: relative;
|
|
560
|
+
border: 2px solid color-mix(in srgb, var(--cyan) 40%, transparent);
|
|
561
|
+
border-radius: 16px;
|
|
562
|
+
padding: 32px 24px 24px;
|
|
563
|
+
background: color-mix(in srgb, var(--surface) 90%, var(--cyan) 3%);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
.arch-container-label {
|
|
567
|
+
position: absolute;
|
|
568
|
+
top: -13px;
|
|
569
|
+
left: 24px;
|
|
570
|
+
background: var(--surface);
|
|
571
|
+
padding: 2px 14px;
|
|
572
|
+
font-family: var(--font-mono);
|
|
573
|
+
font-size: 13px;
|
|
574
|
+
font-weight: 600;
|
|
575
|
+
color: var(--cyan-bright);
|
|
576
|
+
border: 1px solid color-mix(in srgb, var(--cyan) 30%, transparent);
|
|
577
|
+
border-radius: 6px;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
.arch-row {
|
|
581
|
+
display: grid;
|
|
582
|
+
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
|
583
|
+
gap: 12px;
|
|
584
|
+
margin-bottom: 16px;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
.arch-row:last-child { margin-bottom: 0; }
|
|
588
|
+
|
|
589
|
+
.arch-item {
|
|
590
|
+
background: var(--surface2);
|
|
591
|
+
border: 1px solid var(--border);
|
|
592
|
+
border-radius: 10px;
|
|
593
|
+
padding: 14px 16px;
|
|
594
|
+
text-align: center;
|
|
595
|
+
transition: all 0.2s;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
.arch-item:hover {
|
|
599
|
+
border-color: var(--border-bright);
|
|
600
|
+
background: var(--surface-elevated);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
.arch-item .arch-type {
|
|
604
|
+
font-family: var(--font-mono);
|
|
605
|
+
font-size: 9px;
|
|
606
|
+
font-weight: 600;
|
|
607
|
+
text-transform: uppercase;
|
|
608
|
+
letter-spacing: 1.5px;
|
|
609
|
+
margin-bottom: 6px;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
.arch-item .arch-name {
|
|
613
|
+
font-size: 13px;
|
|
614
|
+
font-weight: 600;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
.arch-item .arch-detail {
|
|
618
|
+
font-size: 11px;
|
|
619
|
+
color: var(--text-dim);
|
|
620
|
+
margin-top: 3px;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
.at-feature .arch-type { color: var(--cyan-bright); }
|
|
624
|
+
.at-client .arch-type { color: var(--purple-bright); }
|
|
625
|
+
.at-server .arch-type { color: var(--amber-bright); }
|
|
626
|
+
.at-cmd .arch-type { color: var(--green); }
|
|
627
|
+
|
|
628
|
+
.arch-section-title {
|
|
629
|
+
font-family: var(--font-mono);
|
|
630
|
+
font-size: 10px;
|
|
631
|
+
font-weight: 600;
|
|
632
|
+
text-transform: uppercase;
|
|
633
|
+
letter-spacing: 1.5px;
|
|
634
|
+
color: var(--text-muted);
|
|
635
|
+
margin-bottom: 12px;
|
|
636
|
+
padding-bottom: 8px;
|
|
637
|
+
border-bottom: 1px solid var(--border);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
.arch-divider {
|
|
641
|
+
display: flex;
|
|
642
|
+
align-items: center;
|
|
643
|
+
gap: 12px;
|
|
644
|
+
margin: 20px 0;
|
|
645
|
+
font-family: var(--font-mono);
|
|
646
|
+
font-size: 11px;
|
|
647
|
+
color: var(--text-muted);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
.arch-divider::before,
|
|
651
|
+
.arch-divider::after {
|
|
652
|
+
content: '';
|
|
653
|
+
flex: 1;
|
|
654
|
+
height: 1px;
|
|
655
|
+
background: var(--border);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/* ============ CODE EXAMPLES ============ */
|
|
659
|
+
.code-tabs {
|
|
660
|
+
display: flex;
|
|
661
|
+
gap: 4px;
|
|
662
|
+
margin-bottom: 0;
|
|
663
|
+
padding: 0 4px;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
.code-tab {
|
|
667
|
+
font-family: var(--font-mono);
|
|
668
|
+
font-size: 12px;
|
|
669
|
+
font-weight: 500;
|
|
670
|
+
color: var(--text-muted);
|
|
671
|
+
background: transparent;
|
|
672
|
+
border: none;
|
|
673
|
+
padding: 10px 18px;
|
|
674
|
+
border-radius: 10px 10px 0 0;
|
|
675
|
+
cursor: pointer;
|
|
676
|
+
transition: all 0.2s;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
.code-tab:hover { color: var(--text-dim); }
|
|
680
|
+
.code-tab.active {
|
|
681
|
+
color: var(--text);
|
|
682
|
+
background: var(--surface);
|
|
683
|
+
border: 1px solid var(--border);
|
|
684
|
+
border-bottom-color: var(--surface);
|
|
685
|
+
position: relative;
|
|
686
|
+
z-index: 2;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
.code-panels {
|
|
690
|
+
background: var(--surface);
|
|
691
|
+
border: 1px solid var(--border);
|
|
692
|
+
border-radius: 0 16px 16px 16px;
|
|
693
|
+
overflow: hidden;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
.code-panel {
|
|
697
|
+
display: none;
|
|
698
|
+
padding: 28px;
|
|
699
|
+
font-family: var(--font-mono);
|
|
700
|
+
font-size: 13px;
|
|
701
|
+
line-height: 1.9;
|
|
702
|
+
overflow-x: auto;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
.code-panel.active { display: block; }
|
|
706
|
+
|
|
707
|
+
.code-panel .line {
|
|
708
|
+
white-space: pre;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/* ============ STATS ROW ============ */
|
|
712
|
+
.stats-row {
|
|
713
|
+
display: grid;
|
|
714
|
+
grid-template-columns: repeat(4, 1fr);
|
|
715
|
+
gap: 24px;
|
|
716
|
+
padding: 64px 0;
|
|
717
|
+
border-top: 1px solid var(--border);
|
|
718
|
+
border-bottom: 1px solid var(--border);
|
|
719
|
+
margin: 0;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
.stat {
|
|
723
|
+
text-align: center;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
.stat-value {
|
|
727
|
+
font-size: 40px;
|
|
728
|
+
font-weight: 800;
|
|
729
|
+
letter-spacing: -2px;
|
|
730
|
+
line-height: 1;
|
|
731
|
+
margin-bottom: 8px;
|
|
732
|
+
font-variant-numeric: tabular-nums;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
.stat-value .accent { color: var(--cyan-bright); }
|
|
736
|
+
|
|
737
|
+
.stat-label {
|
|
738
|
+
font-size: 13px;
|
|
739
|
+
color: var(--text-dim);
|
|
740
|
+
font-weight: 500;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
/* ============ CLI SHOWCASE ============ */
|
|
744
|
+
.cli-grid {
|
|
745
|
+
display: grid;
|
|
746
|
+
grid-template-columns: 1fr 1fr;
|
|
747
|
+
gap: 20px;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
.cli-card {
|
|
751
|
+
background: var(--surface);
|
|
752
|
+
border: 1px solid var(--border);
|
|
753
|
+
border-radius: 14px;
|
|
754
|
+
padding: 24px;
|
|
755
|
+
transition: all 0.25s;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
.cli-card:hover {
|
|
759
|
+
border-color: var(--border-bright);
|
|
760
|
+
transform: translateY(-1px);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
.cli-cmd {
|
|
764
|
+
font-family: var(--font-mono);
|
|
765
|
+
font-size: 14px;
|
|
766
|
+
font-weight: 600;
|
|
767
|
+
color: var(--cyan-bright);
|
|
768
|
+
margin-bottom: 8px;
|
|
769
|
+
display: flex;
|
|
770
|
+
align-items: center;
|
|
771
|
+
gap: 8px;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
.cli-cmd::before {
|
|
775
|
+
content: '$';
|
|
776
|
+
color: var(--text-muted);
|
|
777
|
+
font-weight: 400;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
.cli-desc {
|
|
781
|
+
font-size: 13px;
|
|
782
|
+
color: var(--text-dim);
|
|
783
|
+
line-height: 1.6;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
/* ============ CTA ============ */
|
|
787
|
+
.cta {
|
|
788
|
+
text-align: center;
|
|
789
|
+
padding: 120px 0;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
.cta-box {
|
|
793
|
+
background: var(--surface);
|
|
794
|
+
border: 1px solid var(--border-bright);
|
|
795
|
+
border-radius: 24px;
|
|
796
|
+
padding: 64px 48px;
|
|
797
|
+
position: relative;
|
|
798
|
+
overflow: hidden;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
.cta-box::before {
|
|
802
|
+
content: '';
|
|
803
|
+
position: absolute;
|
|
804
|
+
inset: 0;
|
|
805
|
+
background:
|
|
806
|
+
radial-gradient(ellipse at 50% 0%, var(--cyan-glow) 0%, transparent 50%),
|
|
807
|
+
radial-gradient(ellipse at 50% 100%, var(--purple-dim) 0%, transparent 50%);
|
|
808
|
+
pointer-events: none;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
.cta h2 {
|
|
812
|
+
font-size: clamp(28px, 4vw, 40px);
|
|
813
|
+
font-weight: 700;
|
|
814
|
+
letter-spacing: -1px;
|
|
815
|
+
margin-bottom: 16px;
|
|
816
|
+
position: relative;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
.cta p {
|
|
820
|
+
font-size: 17px;
|
|
821
|
+
color: var(--text-dim);
|
|
822
|
+
margin-bottom: 36px;
|
|
823
|
+
position: relative;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
.cta .hero-actions { position: relative; }
|
|
827
|
+
|
|
828
|
+
.install-cmd {
|
|
829
|
+
display: inline-flex;
|
|
830
|
+
align-items: center;
|
|
831
|
+
gap: 12px;
|
|
832
|
+
background: var(--surface2);
|
|
833
|
+
border: 1px solid var(--border);
|
|
834
|
+
border-radius: 10px;
|
|
835
|
+
padding: 14px 24px;
|
|
836
|
+
font-family: var(--font-mono);
|
|
837
|
+
font-size: 14px;
|
|
838
|
+
color: var(--text-dim);
|
|
839
|
+
margin-bottom: 28px;
|
|
840
|
+
position: relative;
|
|
841
|
+
cursor: pointer;
|
|
842
|
+
transition: all 0.2s;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
.install-cmd:hover {
|
|
846
|
+
border-color: var(--cyan);
|
|
847
|
+
color: var(--text);
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
.install-cmd .t-prompt { margin-right: 4px; }
|
|
851
|
+
|
|
852
|
+
.copy-hint {
|
|
853
|
+
font-size: 10px;
|
|
854
|
+
color: var(--text-muted);
|
|
855
|
+
text-transform: uppercase;
|
|
856
|
+
letter-spacing: 1px;
|
|
857
|
+
font-weight: 500;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
/* ============ FOOTER ============ */
|
|
861
|
+
footer {
|
|
862
|
+
border-top: 1px solid var(--border);
|
|
863
|
+
padding: 40px 0;
|
|
864
|
+
text-align: center;
|
|
865
|
+
font-size: 13px;
|
|
866
|
+
color: var(--text-muted);
|
|
867
|
+
position: relative;
|
|
868
|
+
z-index: 1;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
footer a {
|
|
872
|
+
color: var(--text-dim);
|
|
873
|
+
text-decoration: none;
|
|
874
|
+
transition: color 0.2s;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
footer a:hover { color: var(--cyan-bright); }
|
|
878
|
+
|
|
879
|
+
/* ============ PHILOSOPHY CARDS ============ */
|
|
880
|
+
.philosophy {
|
|
881
|
+
display: grid;
|
|
882
|
+
grid-template-columns: repeat(3, 1fr);
|
|
883
|
+
gap: 24px;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
.phil-card {
|
|
887
|
+
padding: 32px;
|
|
888
|
+
border-radius: 16px;
|
|
889
|
+
border: 1px solid var(--border);
|
|
890
|
+
background: var(--surface);
|
|
891
|
+
position: relative;
|
|
892
|
+
overflow: hidden;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
.phil-card::before {
|
|
896
|
+
content: '';
|
|
897
|
+
position: absolute;
|
|
898
|
+
top: 0;
|
|
899
|
+
left: 0;
|
|
900
|
+
width: 100%;
|
|
901
|
+
height: 3px;
|
|
902
|
+
background: var(--phil-accent, var(--cyan));
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
.phil-num {
|
|
906
|
+
font-family: var(--font-mono);
|
|
907
|
+
font-size: 48px;
|
|
908
|
+
font-weight: 800;
|
|
909
|
+
color: var(--border-bright);
|
|
910
|
+
margin-bottom: 12px;
|
|
911
|
+
line-height: 1;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
.phil-card h3 {
|
|
915
|
+
font-size: 18px;
|
|
916
|
+
font-weight: 600;
|
|
917
|
+
margin-bottom: 10px;
|
|
918
|
+
letter-spacing: -0.3px;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
.phil-card p {
|
|
922
|
+
font-size: 14px;
|
|
923
|
+
color: var(--text-dim);
|
|
924
|
+
line-height: 1.6;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
/* ============ RESPONSIVE ============ */
|
|
928
|
+
@media (max-width: 900px) {
|
|
929
|
+
.wrap { padding: 0 20px; }
|
|
930
|
+
nav { padding: 0 20px; }
|
|
931
|
+
.features-grid { grid-template-columns: 1fr 1fr; }
|
|
932
|
+
.cli-grid { grid-template-columns: 1fr; }
|
|
933
|
+
.stats-row { grid-template-columns: repeat(2, 1fr); gap: 32px; }
|
|
934
|
+
.philosophy { grid-template-columns: 1fr; }
|
|
935
|
+
.nav-links { display: none; }
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
@media (max-width: 600px) {
|
|
939
|
+
.features-grid { grid-template-columns: 1fr; }
|
|
940
|
+
.stats-row { grid-template-columns: 1fr; gap: 40px; }
|
|
941
|
+
section { padding: 60px 0; }
|
|
942
|
+
.hero { padding-top: 120px; }
|
|
943
|
+
.cta-box { padding: 40px 24px; }
|
|
944
|
+
.arch-visual { padding: 32px 20px; }
|
|
945
|
+
}
|
|
946
|
+
</style>
|
|
947
|
+
</head>
|
|
948
|
+
<body>
|
|
949
|
+
|
|
950
|
+
<!-- ===== NAV ===== -->
|
|
951
|
+
<nav>
|
|
952
|
+
<div class="nav-inner">
|
|
953
|
+
<div class="nav-logo">
|
|
954
|
+
<div class="logo-mark">L</div>
|
|
955
|
+
luca
|
|
956
|
+
</div>
|
|
957
|
+
<ul class="nav-links" id="nav">
|
|
958
|
+
<li><a href="#features">Features</a></li>
|
|
959
|
+
<li><a href="#architecture">Architecture</a></li>
|
|
960
|
+
<li><a href="#code">Code</a></li>
|
|
961
|
+
<li><a href="#cli">CLI</a></li>
|
|
962
|
+
<li><a href="#get-started" class="nav-cta">Get Started</a></li>
|
|
963
|
+
</ul>
|
|
964
|
+
</div>
|
|
965
|
+
</nav>
|
|
966
|
+
|
|
967
|
+
<!-- ===== HERO ===== -->
|
|
968
|
+
<section class="hero" id="hero">
|
|
969
|
+
<div class="wrap">
|
|
970
|
+
<div class="hero-badge anim" style="--i:0">
|
|
971
|
+
<span class="dot"></span>
|
|
972
|
+
Built on Bun
|
|
973
|
+
</div>
|
|
974
|
+
<h1 class="anim" style="--i:1">
|
|
975
|
+
One Container.<br>
|
|
976
|
+
<span class="gradient-text">Everything You Need.</span>
|
|
977
|
+
</h1>
|
|
978
|
+
<p class="hero-sub anim" style="--i:2">
|
|
979
|
+
Luca is a runtime container framework that gives your server and browser applications
|
|
980
|
+
every dependency they need — zero external packages required.
|
|
981
|
+
</p>
|
|
982
|
+
<div class="hero-actions anim" style="--i:3">
|
|
983
|
+
<a href="#get-started" class="btn btn-primary">Get Started</a>
|
|
984
|
+
<a href="#features" class="btn btn-secondary">Explore Features</a>
|
|
985
|
+
</div>
|
|
986
|
+
|
|
987
|
+
<div class="terminal anim" style="--i:4">
|
|
988
|
+
<div class="terminal-bar">
|
|
989
|
+
<div class="terminal-dot"></div>
|
|
990
|
+
<div class="terminal-dot"></div>
|
|
991
|
+
<div class="terminal-dot"></div>
|
|
992
|
+
<div class="terminal-title">luca — interactive</div>
|
|
993
|
+
</div>
|
|
994
|
+
<div class="terminal-body">
|
|
995
|
+
<div class="line"><span class="t-comment">// everything is on the container</span></div>
|
|
996
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">container</span> = <span class="t-kw">await</span> <span class="t-fn">createContainer</span><span class="t-bracket">()</span></div>
|
|
997
|
+
<div class="line"> </div>
|
|
998
|
+
<div class="line"><span class="t-comment">// features, clients, servers — all built in</span></div>
|
|
999
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">fs</span> = container.<span class="t-method">feature</span><span class="t-bracket">(</span><span class="t-str">'fs'</span><span class="t-bracket">)</span></div>
|
|
1000
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">api</span> = container.<span class="t-method">client</span><span class="t-bracket">(</span><span class="t-str">'rest'</span><span class="t-bracket">)</span></div>
|
|
1001
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">app</span> = container.<span class="t-method">server</span><span class="t-bracket">(</span><span class="t-str">'express'</span><span class="t-bracket">)</span></div>
|
|
1002
|
+
<div class="line"> </div>
|
|
1003
|
+
<div class="line"><span class="t-comment">// that's it. start building.</span></div>
|
|
1004
|
+
<div class="line"><span class="t-kw">await</span> app.<span class="t-method">start</span><span class="t-bracket">()</span></div>
|
|
1005
|
+
</div>
|
|
1006
|
+
</div>
|
|
1007
|
+
</div>
|
|
1008
|
+
</section>
|
|
1009
|
+
|
|
1010
|
+
<!-- ===== STATS ===== -->
|
|
1011
|
+
<div class="wrap">
|
|
1012
|
+
<div class="stats-row">
|
|
1013
|
+
<div class="stat anim-scale" style="--i:0">
|
|
1014
|
+
<div class="stat-value"><span class="accent">0</span></div>
|
|
1015
|
+
<div class="stat-label">External Dependencies</div>
|
|
1016
|
+
</div>
|
|
1017
|
+
<div class="stat anim-scale" style="--i:1">
|
|
1018
|
+
<div class="stat-value">20<span class="accent">+</span></div>
|
|
1019
|
+
<div class="stat-label">Built-in Helpers</div>
|
|
1020
|
+
</div>
|
|
1021
|
+
<div class="stat anim-scale" style="--i:2">
|
|
1022
|
+
<div class="stat-value">2</div>
|
|
1023
|
+
<div class="stat-label">Runtimes (Node + Browser)</div>
|
|
1024
|
+
</div>
|
|
1025
|
+
<div class="stat anim-scale" style="--i:3">
|
|
1026
|
+
<div class="stat-value">1</div>
|
|
1027
|
+
<div class="stat-label">Container for Everything</div>
|
|
1028
|
+
</div>
|
|
1029
|
+
</div>
|
|
1030
|
+
</div>
|
|
1031
|
+
|
|
1032
|
+
<!-- ===== FEATURES ===== -->
|
|
1033
|
+
<section id="features">
|
|
1034
|
+
<div class="wrap">
|
|
1035
|
+
<div class="sec-label anim" style="--i:0">Features</div>
|
|
1036
|
+
<h2 class="sec-title anim" style="--i:1">Batteries Included.<br>All of Them.</h2>
|
|
1037
|
+
<p class="sec-desc anim" style="--i:2">
|
|
1038
|
+
Every feature is a first-class citizen of the container — observable state, event-driven, introspectable. No glue code, no boilerplate.
|
|
1039
|
+
</p>
|
|
1040
|
+
|
|
1041
|
+
<div class="features-grid">
|
|
1042
|
+
<div class="feature-card fc-cyan anim" style="--i:3">
|
|
1043
|
+
<div class="feature-icon">
|
|
1044
|
+
<svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M4 6h14M4 11h14M4 16h8"/></svg>
|
|
1045
|
+
</div>
|
|
1046
|
+
<h3>File System</h3>
|
|
1047
|
+
<p>Read, write, watch, and scan your project files. Intelligent file management with <code>fileManager</code> for full project awareness.</p>
|
|
1048
|
+
</div>
|
|
1049
|
+
|
|
1050
|
+
<div class="feature-card fc-purple anim" style="--i:4">
|
|
1051
|
+
<div class="feature-icon" style="--icon-bg: var(--purple-dim); --icon-color: var(--purple-bright);">
|
|
1052
|
+
<svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><rect x="3" y="3" width="16" height="16" rx="3"/><path d="M7 8h8M7 11h5M7 14h6"/></svg>
|
|
1053
|
+
</div>
|
|
1054
|
+
<h3>Process & VM</h3>
|
|
1055
|
+
<p>Execute shell commands with <code>proc.exec()</code>. Run isolated code in the VM with full module loading and sandboxing.</p>
|
|
1056
|
+
</div>
|
|
1057
|
+
|
|
1058
|
+
<div class="feature-card fc-amber anim" style="--i:5">
|
|
1059
|
+
<div class="feature-icon" style="--icon-bg: var(--amber-dim); --icon-color: var(--amber-bright);">
|
|
1060
|
+
<svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><circle cx="11" cy="11" r="3"/><path d="M11 3v2M11 17v2M3 11h2M17 11h2M5.6 5.6l1.4 1.4M15 15l1.4 1.4M5.6 16.4l1.4-1.4M15 7l1.4-1.4"/></svg>
|
|
1061
|
+
</div>
|
|
1062
|
+
<h3>Networking</h3>
|
|
1063
|
+
<p>Built-in HTTP fetch, port management, and network utilities. Check availability, find open ports, make requests.</p>
|
|
1064
|
+
</div>
|
|
1065
|
+
|
|
1066
|
+
<div class="feature-card fc-green anim" style="--i:6">
|
|
1067
|
+
<div class="feature-icon" style="--icon-bg: var(--green-dim); --icon-color: var(--green);">
|
|
1068
|
+
<svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M6 3v18M6 8h9a3 3 0 010 6H6"/></svg>
|
|
1069
|
+
</div>
|
|
1070
|
+
<h3>Git Integration</h3>
|
|
1071
|
+
<p>Full git awareness — branch info, status, diff, log. Your container knows your repo as well as you do.</p>
|
|
1072
|
+
</div>
|
|
1073
|
+
|
|
1074
|
+
<div class="feature-card fc-rose anim" style="--i:7">
|
|
1075
|
+
<div class="feature-icon" style="--icon-bg: var(--rose-dim); --icon-color: var(--rose);">
|
|
1076
|
+
<svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M10 4L3 11l7 7M14 4l7 7-7 7"/></svg>
|
|
1077
|
+
</div>
|
|
1078
|
+
<h3>REST & WebSocket</h3>
|
|
1079
|
+
<p>Full-featured HTTP client and real-time WebSocket support. Build APIs and consume them from the same container.</p>
|
|
1080
|
+
</div>
|
|
1081
|
+
|
|
1082
|
+
<div class="feature-card fc-cyan anim" style="--i:8">
|
|
1083
|
+
<div class="feature-icon">
|
|
1084
|
+
<svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><circle cx="11" cy="11" r="8"/><path d="M11 7v4l3 3"/></svg>
|
|
1085
|
+
</div>
|
|
1086
|
+
<h3>Observable State</h3>
|
|
1087
|
+
<p>Every helper has reactive, observable state. Subscribe to changes, bind UI, react to events across the entire system.</p>
|
|
1088
|
+
</div>
|
|
1089
|
+
|
|
1090
|
+
<div class="feature-card fc-purple anim" style="--i:9">
|
|
1091
|
+
<div class="feature-icon" style="--icon-bg: var(--purple-dim); --icon-color: var(--purple-bright);">
|
|
1092
|
+
<svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M4 6h14M4 11h14M4 16h14"/><circle cx="8" cy="6" r="1.5" fill="currentColor"/><circle cx="14" cy="11" r="1.5" fill="currentColor"/><circle cx="10" cy="16" r="1.5" fill="currentColor"/></svg>
|
|
1093
|
+
</div>
|
|
1094
|
+
<h3>Introspection</h3>
|
|
1095
|
+
<p>Every helper self-documents. Auto-generated docs, usage examples, method signatures. Explore your system at runtime.</p>
|
|
1096
|
+
</div>
|
|
1097
|
+
|
|
1098
|
+
<div class="feature-card fc-amber anim" style="--i:10">
|
|
1099
|
+
<div class="feature-icon" style="--icon-bg: var(--amber-dim); --icon-color: var(--amber-bright);">
|
|
1100
|
+
<svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M3 7l9-4 9 4-9 4-9-4zM3 12l9 4 9-4M3 17l9 4 9-4"/></svg>
|
|
1101
|
+
</div>
|
|
1102
|
+
<h3>Express & Endpoints</h3>
|
|
1103
|
+
<p>File-based endpoint discovery, Express server with OpenAPI generation, static file serving, rate limiting — out of the box.</p>
|
|
1104
|
+
</div>
|
|
1105
|
+
|
|
1106
|
+
<div class="feature-card fc-green anim" style="--i:11">
|
|
1107
|
+
<div class="feature-icon" style="--icon-bg: var(--green-dim); --icon-color: var(--green);">
|
|
1108
|
+
<svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M11 3a8 8 0 018 8 8 8 0 01-8 8 8 8 0 01-8-8 8 8 0 018-8z"/><path d="M3 11h18M11 3c2.5 2.8 4 5.8 4 8s-1.5 5.2-4 8c-2.5-2.8-4-5.8-4-8s1.5-5.2 4-8z"/></svg>
|
|
1109
|
+
</div>
|
|
1110
|
+
<h3>Cross-Runtime</h3>
|
|
1111
|
+
<p>Same API on server and browser. Node container for backends, Browser container for frontends. Shared primitives everywhere.</p>
|
|
1112
|
+
</div>
|
|
1113
|
+
</div>
|
|
1114
|
+
</div>
|
|
1115
|
+
</section>
|
|
1116
|
+
|
|
1117
|
+
<!-- ===== PHILOSOPHY ===== -->
|
|
1118
|
+
<section>
|
|
1119
|
+
<div class="wrap">
|
|
1120
|
+
<div class="sec-label anim" style="--i:0">Philosophy</div>
|
|
1121
|
+
<h2 class="sec-title anim" style="--i:1">Docker for Your Runtime</h2>
|
|
1122
|
+
<p class="sec-desc anim" style="--i:2">
|
|
1123
|
+
Like Docker gives you a complete, reproducible environment for deployment — Luca gives you a complete, consistent runtime for development.
|
|
1124
|
+
</p>
|
|
1125
|
+
|
|
1126
|
+
<div class="philosophy">
|
|
1127
|
+
<div class="phil-card anim" style="--i:3; --phil-accent: var(--cyan);">
|
|
1128
|
+
<div class="phil-num">01</div>
|
|
1129
|
+
<h3>Zero Dependencies</h3>
|
|
1130
|
+
<p>The container provides everything. File system, networking, git, servers, clients, process execution — no <code style="font-size:12px; background:var(--cyan-dim); color:var(--cyan-bright); padding:1px 5px; border-radius:3px; font-family:var(--font-mono);">npm install</code> needed.</p>
|
|
1131
|
+
</div>
|
|
1132
|
+
<div class="phil-card anim" style="--i:4; --phil-accent: var(--purple);">
|
|
1133
|
+
<div class="phil-num">02</div>
|
|
1134
|
+
<h3>Compose, Don't Configure</h3>
|
|
1135
|
+
<p>Features, clients, and servers are composable building blocks. Request what you need from the container, wire it together, ship it.</p>
|
|
1136
|
+
</div>
|
|
1137
|
+
<div class="phil-card anim" style="--i:5; --phil-accent: var(--amber);">
|
|
1138
|
+
<div class="phil-num">03</div>
|
|
1139
|
+
<h3>Know Thyself</h3>
|
|
1140
|
+
<p>Every component is introspectable. Auto-generated documentation, observable state, full event system. Your app explains itself.</p>
|
|
1141
|
+
</div>
|
|
1142
|
+
</div>
|
|
1143
|
+
</div>
|
|
1144
|
+
</section>
|
|
1145
|
+
|
|
1146
|
+
<!-- ===== ARCHITECTURE ===== -->
|
|
1147
|
+
<section id="architecture">
|
|
1148
|
+
<div class="wrap">
|
|
1149
|
+
<div class="sec-label anim" style="--i:0">Architecture</div>
|
|
1150
|
+
<h2 class="sec-title anim" style="--i:1">Everything Lives<br>in the Container</h2>
|
|
1151
|
+
<p class="sec-desc anim" style="--i:2">
|
|
1152
|
+
A singleton per process. Event bus, state machine, dependency injector, and registry — all in one coherent object.
|
|
1153
|
+
</p>
|
|
1154
|
+
|
|
1155
|
+
<div class="arch-visual anim" style="--i:3">
|
|
1156
|
+
<div class="arch-container-box">
|
|
1157
|
+
<div class="arch-container-label">container</div>
|
|
1158
|
+
|
|
1159
|
+
<div class="arch-section-title">Registries</div>
|
|
1160
|
+
<div class="arch-row">
|
|
1161
|
+
<div class="arch-item at-feature">
|
|
1162
|
+
<div class="arch-type">Registry</div>
|
|
1163
|
+
<div class="arch-name">features</div>
|
|
1164
|
+
<div class="arch-detail">fs, git, proc, vm, grep...</div>
|
|
1165
|
+
</div>
|
|
1166
|
+
<div class="arch-item at-client">
|
|
1167
|
+
<div class="arch-type">Registry</div>
|
|
1168
|
+
<div class="arch-name">clients</div>
|
|
1169
|
+
<div class="arch-detail">rest, websocket</div>
|
|
1170
|
+
</div>
|
|
1171
|
+
<div class="arch-item at-server">
|
|
1172
|
+
<div class="arch-type">Registry</div>
|
|
1173
|
+
<div class="arch-name">servers</div>
|
|
1174
|
+
<div class="arch-detail">express, websocket</div>
|
|
1175
|
+
</div>
|
|
1176
|
+
<div class="arch-item at-cmd">
|
|
1177
|
+
<div class="arch-type">Registry</div>
|
|
1178
|
+
<div class="arch-name">commands</div>
|
|
1179
|
+
<div class="arch-detail">file-based discovery</div>
|
|
1180
|
+
</div>
|
|
1181
|
+
<div class="arch-item at-cmd">
|
|
1182
|
+
<div class="arch-type">Registry</div>
|
|
1183
|
+
<div class="arch-name">endpoints</div>
|
|
1184
|
+
<div class="arch-detail">HTTP handlers</div>
|
|
1185
|
+
</div>
|
|
1186
|
+
</div>
|
|
1187
|
+
|
|
1188
|
+
<div class="arch-divider">primitives</div>
|
|
1189
|
+
|
|
1190
|
+
<div class="arch-row">
|
|
1191
|
+
<div class="arch-item">
|
|
1192
|
+
<div class="arch-type" style="color:var(--text-dim)">Core</div>
|
|
1193
|
+
<div class="arch-name">Event Bus</div>
|
|
1194
|
+
<div class="arch-detail">emit, on, once</div>
|
|
1195
|
+
</div>
|
|
1196
|
+
<div class="arch-item">
|
|
1197
|
+
<div class="arch-type" style="color:var(--text-dim)">Core</div>
|
|
1198
|
+
<div class="arch-name">State Machine</div>
|
|
1199
|
+
<div class="arch-detail">observable, reactive</div>
|
|
1200
|
+
</div>
|
|
1201
|
+
<div class="arch-item">
|
|
1202
|
+
<div class="arch-type" style="color:var(--text-dim)">Core</div>
|
|
1203
|
+
<div class="arch-name">Paths</div>
|
|
1204
|
+
<div class="arch-detail">resolve, join, cwd</div>
|
|
1205
|
+
</div>
|
|
1206
|
+
<div class="arch-item">
|
|
1207
|
+
<div class="arch-type" style="color:var(--text-dim)">Core</div>
|
|
1208
|
+
<div class="arch-name">Introspection</div>
|
|
1209
|
+
<div class="arch-detail">self-documenting</div>
|
|
1210
|
+
</div>
|
|
1211
|
+
</div>
|
|
1212
|
+
</div>
|
|
1213
|
+
</div>
|
|
1214
|
+
</div>
|
|
1215
|
+
</section>
|
|
1216
|
+
|
|
1217
|
+
<!-- ===== CODE EXAMPLES ===== -->
|
|
1218
|
+
<section id="code">
|
|
1219
|
+
<div class="wrap">
|
|
1220
|
+
<div class="sec-label anim" style="--i:0">Developer Experience</div>
|
|
1221
|
+
<h2 class="sec-title anim" style="--i:1">Write Less. Build More.</h2>
|
|
1222
|
+
<p class="sec-desc anim" style="--i:2">
|
|
1223
|
+
Clean, expressive APIs that feel natural. Everything you need is one method call away.
|
|
1224
|
+
</p>
|
|
1225
|
+
|
|
1226
|
+
<div class="anim" style="--i:3">
|
|
1227
|
+
<div class="code-tabs">
|
|
1228
|
+
<button class="code-tab active" data-panel="server">Server</button>
|
|
1229
|
+
<button class="code-tab" data-panel="files">Files</button>
|
|
1230
|
+
<button class="code-tab" data-panel="script">Script</button>
|
|
1231
|
+
<button class="code-tab" data-panel="endpoints">Endpoints</button>
|
|
1232
|
+
</div>
|
|
1233
|
+
|
|
1234
|
+
<div class="code-panels">
|
|
1235
|
+
<div class="code-panel active" id="panel-server">
|
|
1236
|
+
<div class="line"><span class="t-comment">// spin up an Express server with endpoints</span></div>
|
|
1237
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">app</span> = container.<span class="t-method">server</span>(<span class="t-str">'express'</span>)</div>
|
|
1238
|
+
<div class="line"> </div>
|
|
1239
|
+
<div class="line"><span class="t-comment">// endpoints are auto-discovered from your files</span></div>
|
|
1240
|
+
<div class="line"><span class="t-kw">await</span> app.<span class="t-method">mountEndpoints</span>()</div>
|
|
1241
|
+
<div class="line"> </div>
|
|
1242
|
+
<div class="line"><span class="t-comment">// WebSocket server alongside HTTP</span></div>
|
|
1243
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">ws</span> = container.<span class="t-method">server</span>(<span class="t-str">'websocket'</span>)</div>
|
|
1244
|
+
<div class="line">ws.<span class="t-method">on</span>(<span class="t-str">'connection'</span>, <span class="t-cmd">socket</span> <span class="t-kw">=></span> {</div>
|
|
1245
|
+
<div class="line"> socket.<span class="t-method">send</span>(<span class="t-str">'welcome to luca'</span>)</div>
|
|
1246
|
+
<div class="line">})</div>
|
|
1247
|
+
<div class="line"> </div>
|
|
1248
|
+
<div class="line"><span class="t-kw">await</span> app.<span class="t-method">start</span>() <span class="t-comment">// that's it</span></div>
|
|
1249
|
+
</div>
|
|
1250
|
+
|
|
1251
|
+
<div class="code-panel" id="panel-files">
|
|
1252
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">fs</span> = container.<span class="t-method">feature</span>(<span class="t-str">'fs'</span>)</div>
|
|
1253
|
+
<div class="line"> </div>
|
|
1254
|
+
<div class="line"><span class="t-comment">// read any file</span></div>
|
|
1255
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">data</span> = <span class="t-kw">await</span> fs.<span class="t-method">readFile</span>(<span class="t-str">'config.json'</span>)</div>
|
|
1256
|
+
<div class="line"> </div>
|
|
1257
|
+
<div class="line"><span class="t-comment">// search content across your project</span></div>
|
|
1258
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">grep</span> = container.<span class="t-method">feature</span>(<span class="t-str">'grep'</span>)</div>
|
|
1259
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">results</span> = <span class="t-kw">await</span> grep.<span class="t-method">run</span>(<span class="t-str">'TODO'</span>, {</div>
|
|
1260
|
+
<div class="line"> <span class="t-key">include</span>: [<span class="t-str">'**/*.ts'</span>]</div>
|
|
1261
|
+
<div class="line">})</div>
|
|
1262
|
+
<div class="line"> </div>
|
|
1263
|
+
<div class="line"><span class="t-comment">// intelligent project-wide file awareness</span></div>
|
|
1264
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">fm</span> = container.<span class="t-method">feature</span>(<span class="t-str">'fileManager'</span>)</div>
|
|
1265
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">files</span> = fm.<span class="t-method">fileIds</span> <span class="t-comment">// every file, indexed</span></div>
|
|
1266
|
+
</div>
|
|
1267
|
+
|
|
1268
|
+
<div class="code-panel" id="panel-script">
|
|
1269
|
+
<div class="line"><span class="t-comment">// scripts have the full container at their fingertips</span></div>
|
|
1270
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">git</span> = container.<span class="t-method">feature</span>(<span class="t-str">'git'</span>)</div>
|
|
1271
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">proc</span> = container.<span class="t-method">feature</span>(<span class="t-str">'proc'</span>)</div>
|
|
1272
|
+
<div class="line"> </div>
|
|
1273
|
+
<div class="line"><span class="t-comment">// check git status</span></div>
|
|
1274
|
+
<div class="line">console.<span class="t-method">log</span>(git.<span class="t-key">branch</span>) <span class="t-comment">// "main"</span></div>
|
|
1275
|
+
<div class="line">console.<span class="t-method">log</span>(git.<span class="t-key">status</span>) <span class="t-comment">// { modified: [...] }</span></div>
|
|
1276
|
+
<div class="line"> </div>
|
|
1277
|
+
<div class="line"><span class="t-comment">// run shell commands</span></div>
|
|
1278
|
+
<div class="line"><span class="t-kw">const</span> { <span class="t-cmd">stdout</span> } = <span class="t-kw">await</span> proc.<span class="t-method">exec</span>(<span class="t-str">'ls -la'</span>)</div>
|
|
1279
|
+
<div class="line"> </div>
|
|
1280
|
+
<div class="line"><span class="t-comment">// isolated VM execution</span></div>
|
|
1281
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">vm</span> = container.<span class="t-method">feature</span>(<span class="t-str">'vm'</span>)</div>
|
|
1282
|
+
<div class="line"><span class="t-kw">const</span> <span class="t-cmd">result</span> = <span class="t-kw">await</span> vm.<span class="t-method">run</span>(<span class="t-str">'return 2 + 2'</span>)</div>
|
|
1283
|
+
</div>
|
|
1284
|
+
|
|
1285
|
+
<div class="code-panel" id="panel-endpoints">
|
|
1286
|
+
<div class="line"><span class="t-comment">// endpoints/hello.ts — file-based routing</span></div>
|
|
1287
|
+
<div class="line"><span class="t-kw">export default</span> {</div>
|
|
1288
|
+
<div class="line"> <span class="t-key">method</span>: <span class="t-str">'GET'</span>,</div>
|
|
1289
|
+
<div class="line"> <span class="t-key">path</span>: <span class="t-str">'/hello/:name'</span>,</div>
|
|
1290
|
+
<div class="line"> </div>
|
|
1291
|
+
<div class="line"> <span class="t-kw">async</span> <span class="t-fn">handler</span>(<span class="t-cmd">req</span>, <span class="t-cmd">res</span>, <span class="t-cmd">container</span>) {</div>
|
|
1292
|
+
<div class="line"> <span class="t-comment">// full container access in every handler</span></div>
|
|
1293
|
+
<div class="line"> <span class="t-kw">const</span> <span class="t-cmd">fs</span> = container.<span class="t-method">feature</span>(<span class="t-str">'fs'</span>)</div>
|
|
1294
|
+
<div class="line"> <span class="t-kw">const</span> <span class="t-cmd">template</span> = <span class="t-kw">await</span> fs.<span class="t-method">readFile</span>(<span class="t-str">'greeting.html'</span>)</div>
|
|
1295
|
+
<div class="line"> </div>
|
|
1296
|
+
<div class="line"> res.<span class="t-method">json</span>({ <span class="t-key">hello</span>: req.params.<span class="t-key">name</span> })</div>
|
|
1297
|
+
<div class="line"> }</div>
|
|
1298
|
+
<div class="line">}</div>
|
|
1299
|
+
</div>
|
|
1300
|
+
</div>
|
|
1301
|
+
</div>
|
|
1302
|
+
</div>
|
|
1303
|
+
</section>
|
|
1304
|
+
|
|
1305
|
+
<!-- ===== CLI ===== -->
|
|
1306
|
+
<section id="cli">
|
|
1307
|
+
<div class="wrap">
|
|
1308
|
+
<div class="sec-label anim" style="--i:0">Command Line</div>
|
|
1309
|
+
<h2 class="sec-title anim" style="--i:1">A CLI That<br>Understands Your Code</h2>
|
|
1310
|
+
<p class="sec-desc anim" style="--i:2">
|
|
1311
|
+
Run code, generate docs, serve apps, explore registries — all from your terminal.
|
|
1312
|
+
</p>
|
|
1313
|
+
|
|
1314
|
+
<div class="cli-grid">
|
|
1315
|
+
<div class="cli-card anim" style="--i:3">
|
|
1316
|
+
<div class="cli-cmd">luca eval "container.features.available"</div>
|
|
1317
|
+
<div class="cli-desc">Run arbitrary JavaScript against the live container. Inspect state, test features, explore registries interactively.</div>
|
|
1318
|
+
</div>
|
|
1319
|
+
<div class="cli-card anim" style="--i:4">
|
|
1320
|
+
<div class="cli-cmd">luca describe fs</div>
|
|
1321
|
+
<div class="cli-desc">Auto-generated documentation for any feature, client, or server. Methods, options, state, events — all introspected.</div>
|
|
1322
|
+
</div>
|
|
1323
|
+
<div class="cli-card anim" style="--i:5">
|
|
1324
|
+
<div class="cli-cmd">luca serve</div>
|
|
1325
|
+
<div class="cli-desc">Start an Express server that auto-discovers your endpoints/ folder. OpenAPI docs, static files, and hot reload included.</div>
|
|
1326
|
+
</div>
|
|
1327
|
+
<div class="cli-card anim" style="--i:6">
|
|
1328
|
+
<div class="cli-cmd">luca describe servers</div>
|
|
1329
|
+
<div class="cli-desc">Explore entire registries at once. See every available server, client, or feature with their full documentation.</div>
|
|
1330
|
+
</div>
|
|
1331
|
+
<div class="cli-card anim" style="--i:7">
|
|
1332
|
+
<div class="cli-cmd">luca console</div>
|
|
1333
|
+
<div class="cli-desc">Drop into an interactive REPL with the full container in scope. Every feature, client, and server at your fingertips.</div>
|
|
1334
|
+
</div>
|
|
1335
|
+
<div class="cli-card anim" style="--i:8">
|
|
1336
|
+
<div class="cli-cmd">luca run scripts/deploy.ts</div>
|
|
1337
|
+
<div class="cli-desc">Execute scripts with the container pre-loaded. No imports needed — your script gets the full runtime automatically.</div>
|
|
1338
|
+
</div>
|
|
1339
|
+
</div>
|
|
1340
|
+
</div>
|
|
1341
|
+
</section>
|
|
1342
|
+
|
|
1343
|
+
<!-- ===== CTA ===== -->
|
|
1344
|
+
<section class="cta" id="get-started">
|
|
1345
|
+
<div class="wrap">
|
|
1346
|
+
<div class="cta-box anim" style="--i:0">
|
|
1347
|
+
<h2>Start Building with Luca</h2>
|
|
1348
|
+
<p>One container. Every feature. Zero dependencies.</p>
|
|
1349
|
+
|
|
1350
|
+
<div class="install-cmd" onclick="navigator.clipboard.writeText('bun add luca')">
|
|
1351
|
+
<span class="t-prompt">$</span>
|
|
1352
|
+
<span>bun add luca</span>
|
|
1353
|
+
<span class="copy-hint">click to copy</span>
|
|
1354
|
+
</div>
|
|
1355
|
+
|
|
1356
|
+
<div class="hero-actions">
|
|
1357
|
+
<a href="https://github.com/soederpop/luca" class="btn btn-primary" target="_blank" rel="noopener">
|
|
1358
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"/></svg>
|
|
1359
|
+
View on GitHub
|
|
1360
|
+
</a>
|
|
1361
|
+
<a href="#features" class="btn btn-secondary">Explore Docs</a>
|
|
1362
|
+
</div>
|
|
1363
|
+
</div>
|
|
1364
|
+
</div>
|
|
1365
|
+
</section>
|
|
1366
|
+
|
|
1367
|
+
<!-- ===== FOOTER ===== -->
|
|
1368
|
+
<footer>
|
|
1369
|
+
<div class="wrap">
|
|
1370
|
+
<p>Luca — Lightweight Universal Conversational Architecture</p>
|
|
1371
|
+
<p style="margin-top:8px">Built with <a href="https://bun.sh" target="_blank" rel="noopener">Bun</a>. Designed for developers who build.</p>
|
|
1372
|
+
</div>
|
|
1373
|
+
</footer>
|
|
1374
|
+
|
|
1375
|
+
<!-- ===== SCRIPTS ===== -->
|
|
1376
|
+
<script>
|
|
1377
|
+
// Tab switching
|
|
1378
|
+
document.querySelectorAll('.code-tab').forEach(tab => {
|
|
1379
|
+
tab.addEventListener('click', () => {
|
|
1380
|
+
document.querySelectorAll('.code-tab').forEach(t => t.classList.remove('active'));
|
|
1381
|
+
document.querySelectorAll('.code-panel').forEach(p => p.classList.remove('active'));
|
|
1382
|
+
tab.classList.add('active');
|
|
1383
|
+
document.getElementById('panel-' + tab.dataset.panel).classList.add('active');
|
|
1384
|
+
});
|
|
1385
|
+
});
|
|
1386
|
+
|
|
1387
|
+
// Nav scroll spy
|
|
1388
|
+
const navLinks = document.querySelectorAll('#nav a[href^="#"]');
|
|
1389
|
+
const sections = [];
|
|
1390
|
+
navLinks.forEach(link => {
|
|
1391
|
+
const id = link.getAttribute('href').slice(1);
|
|
1392
|
+
const el = document.getElementById(id);
|
|
1393
|
+
if (el) sections.push({ el, link });
|
|
1394
|
+
});
|
|
1395
|
+
|
|
1396
|
+
const observer = new IntersectionObserver(entries => {
|
|
1397
|
+
entries.forEach(entry => {
|
|
1398
|
+
if (entry.isIntersecting) {
|
|
1399
|
+
navLinks.forEach(l => l.classList.remove('active'));
|
|
1400
|
+
const match = sections.find(s => s.el === entry.target);
|
|
1401
|
+
if (match) match.link.classList.add('active');
|
|
1402
|
+
}
|
|
1403
|
+
});
|
|
1404
|
+
}, { rootMargin: '-20% 0px -70% 0px' });
|
|
1405
|
+
|
|
1406
|
+
sections.forEach(s => observer.observe(s.el));
|
|
1407
|
+
|
|
1408
|
+
// Intersection observer for animations
|
|
1409
|
+
const animObserver = new IntersectionObserver((entries) => {
|
|
1410
|
+
entries.forEach(entry => {
|
|
1411
|
+
if (entry.isIntersecting) {
|
|
1412
|
+
entry.target.style.animationPlayState = 'running';
|
|
1413
|
+
animObserver.unobserve(entry.target);
|
|
1414
|
+
}
|
|
1415
|
+
});
|
|
1416
|
+
}, { threshold: 0.1 });
|
|
1417
|
+
|
|
1418
|
+
document.querySelectorAll('.anim, .anim-scale').forEach(el => {
|
|
1419
|
+
el.style.animationPlayState = 'paused';
|
|
1420
|
+
// Don't pause hero elements
|
|
1421
|
+
if (el.closest('.hero') || el.closest('.stats-row')) {
|
|
1422
|
+
el.style.animationPlayState = 'running';
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1425
|
+
animObserver.observe(el);
|
|
1426
|
+
});
|
|
1427
|
+
</script>
|
|
1428
|
+
|
|
1429
|
+
</body>
|
|
1430
|
+
</html>
|