FabienDanieau commited on
Commit
6d63e8c
·
1 Parent(s): e8700c6

fix SDK link

Browse files
Files changed (1) hide show
  1. src/pages/Home.jsx +506 -303
src/pages/Home.jsx CHANGED
@@ -1,5 +1,5 @@
1
- import { useState, useEffect } from 'react';
2
- import { Link as RouterLink } from 'react-router-dom';
3
  import {
4
  Box,
5
  Container,
@@ -8,17 +8,28 @@ import {
8
  Grid,
9
  Stack,
10
  Link,
11
- } from '@mui/material';
12
- import { useSpring, animated } from '@react-spring/web';
13
- import OpenInNewIcon from '@mui/icons-material/OpenInNew';
14
- import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
15
 
16
- import Layout from '../components/Layout';
17
- import Section from '../components/Section';
18
- import { useApps } from '../context/AppsContext';
19
 
20
  // Floating Sticker Component with scroll parallax
21
- function FloatingSticker({ src, size, top, left, right, bottom, rotation = 0, floatRange = 15, floatSpeed = 6000, scrollFactor = 0.05 }) {
 
 
 
 
 
 
 
 
 
 
 
22
  const [floatOffset, setFloatOffset] = useState(0);
23
  const [scrollY, setScrollY] = useState(0);
24
 
@@ -27,7 +38,8 @@ function FloatingSticker({ src, size, top, left, right, bottom, rotation = 0, fl
27
  let animationFrame;
28
  const animate = () => {
29
  const elapsed = Date.now() - startTime;
30
- const offset = Math.sin((elapsed / floatSpeed) * Math.PI * 2) * floatRange;
 
31
  setFloatOffset(offset);
32
  animationFrame = requestAnimationFrame(animate);
33
  };
@@ -37,8 +49,8 @@ function FloatingSticker({ src, size, top, left, right, bottom, rotation = 0, fl
37
 
38
  useEffect(() => {
39
  const handleScroll = () => setScrollY(window.scrollY);
40
- window.addEventListener('scroll', handleScroll, { passive: true });
41
- return () => window.removeEventListener('scroll', handleScroll);
42
  }, []);
43
 
44
  const springProps = useSpring({
@@ -51,11 +63,14 @@ function FloatingSticker({ src, size, top, left, right, bottom, rotation = 0, fl
51
  src={src}
52
  alt=""
53
  style={{
54
- position: 'absolute',
55
- top, left, right, bottom,
 
 
 
56
  width: size,
57
- height: 'auto',
58
- pointerEvents: 'none',
59
  zIndex: 2,
60
  ...springProps,
61
  }}
@@ -69,8 +84,8 @@ function Hero() {
69
 
70
  useEffect(() => {
71
  const handleScroll = () => setScrollY(window.scrollY);
72
- window.addEventListener('scroll', handleScroll, { passive: true });
73
- return () => window.removeEventListener('scroll', handleScroll);
74
  }, []);
75
 
76
  const videoParallax = useSpring({
@@ -81,25 +96,25 @@ function Hero() {
81
  return (
82
  <Box
83
  sx={{
84
- position: 'relative',
85
- minHeight: { xs: '85vh', md: '80vh' },
86
- display: 'flex',
87
- alignItems: { xs: 'flex-end', md: 'center' },
88
  pb: { xs: 12, md: 0 },
89
- backgroundColor: '#000',
90
- overflow: 'hidden',
91
  // Curved bottom edge
92
- '&::after': {
93
  content: '""',
94
- position: 'absolute',
95
  bottom: -1,
96
  left: 0,
97
  right: 0,
98
  height: { xs: 60, md: 90 },
99
- background: 'inherit',
100
- backgroundColor: 'background.default',
101
- borderRadius: '100% 100% 0 0 / 100% 100% 0 0',
102
- transform: 'translateY(50%)',
103
  },
104
  }}
105
  >
@@ -109,24 +124,27 @@ function Hero() {
109
  loop
110
  playsInline
111
  style={{
112
- position: 'absolute',
113
- top: '50%',
114
- left: '50%',
115
- minWidth: '100%',
116
- minHeight: '100%',
117
- width: 'auto',
118
- height: 'auto',
119
  opacity: 0.9,
120
  ...videoParallax,
121
  }}
122
  >
123
- <source src="/assets/Reachy-mini-wake-up-companion.mp4" type="video/mp4" />
 
 
 
124
  </animated.video>
125
 
126
  {/* Overlay gradients + vignette */}
127
  <Box
128
  sx={{
129
- position: 'absolute',
130
  inset: 0,
131
  background: `
132
  linear-gradient(to right, rgba(0,0,0,0.75) 0%, rgba(0,0,0,0.4) 40%, rgba(0,0,0,0.15) 100%),
@@ -136,43 +154,57 @@ function Hero() {
136
  }}
137
  />
138
 
139
- <Container maxWidth="lg" sx={{ position: 'relative', zIndex: 10 }}>
140
  <Box sx={{ maxWidth: 640 }}>
141
  <Stack direction="row" spacing={1} alignItems="center" sx={{ mb: 2 }}>
142
  <Typography
143
  sx={{
144
- color: 'rgba(255,255,255,0.6)',
145
  fontSize: 13,
146
  fontWeight: 500,
147
  }}
148
  >
149
  Open Source Robot
150
  </Typography>
151
- <Box sx={{ width: 4, height: 4, borderRadius: '50%', bgcolor: 'rgba(255,255,255,0.3)' }} />
 
 
 
 
 
 
 
152
  <Typography
153
  sx={{
154
- color: 'rgba(255,255,255,0.6)',
155
  fontSize: 13,
156
  fontWeight: 500,
157
- display: 'flex',
158
- alignItems: 'center',
159
  gap: 0.5,
160
  }}
161
  >
162
- Powered by <Box component="img" src="/assets/hf-logo.svg" alt="Hugging Face" sx={{ height: 14 }} />
 
 
 
 
 
 
163
  </Typography>
164
  </Stack>
165
 
166
- <Box sx={{ position: 'relative', display: 'inline-block', mb: 2 }}>
167
  <Typography
168
  variant="h1"
169
  component="h1"
170
  sx={{
171
- color: 'white',
172
- background: 'linear-gradient(135deg, #ffffff 0%, rgba(255,255,255,0.85) 100%)',
173
- backgroundClip: 'text',
174
- WebkitBackgroundClip: 'text',
175
- WebkitTextFillColor: 'transparent',
 
176
  }}
177
  >
178
  Reachy Mini
@@ -183,29 +215,29 @@ function Hero() {
183
  variant="h5"
184
  component="p"
185
  sx={{
186
- color: 'rgba(255,255,255,0.75)',
187
  fontWeight: 400,
188
  mb: 4,
189
  lineHeight: 1.6,
190
  maxWidth: 520,
191
  }}
192
  >
193
- An expressive companion robot designed for{' '}
194
- <Box component="span" sx={{ color: 'white', fontWeight: 500 }}>
195
  human interaction
196
  </Box>
197
- ,{' '}
198
- <Box component="span" sx={{ color: 'white', fontWeight: 500 }}>
199
  creative coding
200
  </Box>
201
- , and{' '}
202
- <Box component="span" sx={{ color: 'white', fontWeight: 500 }}>
203
  AI experimentation
204
  </Box>
205
  .
206
  </Typography>
207
 
208
- <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>
209
  <Button
210
  component={RouterLink}
211
  to="/buy"
@@ -216,11 +248,11 @@ function Hero() {
216
  py: 1.75,
217
  fontSize: 16,
218
  fontWeight: 600,
219
- background: 'linear-gradient(135deg, #FF9500 0%, #ff7b00 100%)',
220
- boxShadow: '0 4px 24px rgba(255, 149, 0, 0.35)',
221
- '&:hover': {
222
- boxShadow: '0 8px 32px rgba(255, 149, 0, 0.5)',
223
- transform: 'translateY(-2px)',
224
  },
225
  }}
226
  >
@@ -236,12 +268,12 @@ function Hero() {
236
  py: 1.75,
237
  fontSize: 16,
238
  fontWeight: 600,
239
- color: 'rgba(255,255,255,0.9)',
240
- borderColor: 'rgba(255,255,255,0.3)',
241
- '&:hover': {
242
- color: 'white',
243
- borderColor: 'rgba(255,255,255,0.6)',
244
- backgroundColor: 'rgba(255,255,255,0.05)'
245
  },
246
  }}
247
  >
@@ -250,7 +282,6 @@ function Hero() {
250
  </Stack>
251
  </Box>
252
  </Container>
253
-
254
  </Box>
255
  );
256
  }
@@ -258,37 +289,40 @@ function Hero() {
258
  // Stats/Bento Section - Sober backgrounds, illustrations for color
259
  function StatsSection() {
260
  return (
261
- <Section id="stats" sx={{ py: { xs: 8, md: 12 }, position: 'relative', overflow: 'visible' }}>
262
- <Grid container spacing={2} sx={{ overflow: 'visible' }}>
 
 
 
263
  {/* Big stat - Open Source */}
264
- <Grid size={{ xs: 12, md: 8 }} sx={{ overflow: 'visible' }}>
265
  <Box
266
  component={RouterLink}
267
  to="/getting-started"
268
  sx={{
269
  height: { xs: 280, md: 320 },
270
  borderRadius: 4,
271
- background: '#0f0f1a',
272
- border: '1px solid rgba(255,255,255,0.08)',
273
  p: { xs: 4, md: 6 },
274
- position: 'relative',
275
- display: 'flex',
276
- flexDirection: 'column',
277
- justifyContent: 'space-between',
278
  // Clip only bottom and left, allow top and right overflow
279
- clipPath: 'inset(-100px -50px 0 0 round 16px)',
280
- textDecoration: 'none',
281
- color: 'inherit',
282
- cursor: 'pointer',
283
- transition: 'border-color 0.3s ease, transform 0.3s ease',
284
- '&:hover': {
285
- borderColor: 'rgba(255,255,255,0.2)',
286
- transform: 'translateY(-2px)',
287
  },
288
  }}
289
  >
290
  {/* How to create app illustration - floating */}
291
- <Box sx={{ display: { xs: 'none', sm: 'block' } }}>
292
  <FloatingSticker
293
  src="/assets/reachy-how-to-create-app.svg"
294
  size={336}
@@ -300,26 +334,35 @@ function StatsSection() {
300
  scrollFactor={0.03}
301
  />
302
  </Box>
303
- <Box sx={{ position: 'relative', zIndex: 1 }}>
304
  <Typography
305
  sx={{
306
  fontSize: { xs: 50, md: 60 },
307
  fontWeight: 800,
308
  lineHeight: 1,
309
- color: 'white',
310
  }}
311
  >
312
- Build your<br />
 
313
  own robot
314
  </Typography>
315
  <Typography
316
  variant="h4"
317
- sx={{ color: 'white', fontWeight: 600, mt: 1 }}
318
  >
319
  Get Started
320
  </Typography>
321
  </Box>
322
- <Typography sx={{ color: 'rgba(255,255,255,0.5)', fontSize: 15, position: 'relative', zIndex: 1, maxWidth: 400 }}>
 
 
 
 
 
 
 
 
323
  Follow our guides to assemble your Reachy Mini →
324
  </Typography>
325
  </Box>
@@ -333,14 +376,14 @@ function StatsSection() {
333
  sx={{
334
  height: { xs: 280, md: 320 },
335
  borderRadius: 4,
336
- background: '#0f0f1a',
337
- border: '1px solid rgba(255,255,255,0.08)',
338
- overflow: 'hidden',
339
- position: 'relative',
340
- textDecoration: 'none',
341
- display: 'block',
342
- transition: 'all 0.3s ease',
343
- '&:hover': { borderColor: 'rgba(255,255,255,0.2)' },
344
  }}
345
  >
346
  {/* GIF Background */}
@@ -349,32 +392,33 @@ function StatsSection() {
349
  src="/assets/reachy-mini-hand-tracking.gif"
350
  alt="Real-time interaction"
351
  sx={{
352
- position: 'absolute',
353
  top: 0,
354
  left: 0,
355
- width: '100%',
356
- height: '100%',
357
- objectFit: 'cover',
358
  }}
359
  />
360
  {/* Overlay gradient */}
361
  <Box
362
  sx={{
363
- position: 'absolute',
364
  inset: 0,
365
- background: 'linear-gradient(to top, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.3) 50%, rgba(0,0,0,0.1) 100%)',
 
366
  }}
367
  />
368
  {/* Content */}
369
  <Box
370
  sx={{
371
- position: 'relative',
372
  zIndex: 1,
373
- height: '100%',
374
  p: { xs: 4, md: 5 },
375
- display: 'flex',
376
- flexDirection: 'column',
377
- justifyContent: 'flex-end',
378
  }}
379
  >
380
  <Typography
@@ -382,13 +426,15 @@ function StatsSection() {
382
  fontSize: { xs: 56, md: 72 },
383
  fontWeight: 800,
384
  lineHeight: 1,
385
- color: 'white',
386
  }}
387
  >
388
  Apps
389
  </Typography>
390
  <Box sx={{ mt: 1 }}>
391
- <Typography sx={{ color: 'rgba(255,255,255,0.6)', fontSize: 14, mt: 0.5 }}>
 
 
392
  Explore ready-to-use app →
393
  </Typography>
394
  </Box>
@@ -406,15 +452,15 @@ function StatsSection() {
406
  sx={{
407
  height: { xs: 200, md: 200 },
408
  borderRadius: 4,
409
- background: '#0f0f1a',
410
- border: '1px solid rgba(255,255,255,0.08)',
411
  p: { xs: 4, md: 5 },
412
- display: 'flex',
413
- flexDirection: 'column',
414
- justifyContent: 'space-between',
415
- textDecoration: 'none',
416
- transition: 'all 0.3s ease',
417
- '&:hover': { borderColor: 'rgba(255,255,255,0.2)' },
418
  }}
419
  >
420
  <Box
@@ -424,10 +470,12 @@ function StatsSection() {
424
  sx={{ width: 36, height: 36, opacity: 0.8 }}
425
  />
426
  <Box>
427
- <Typography variant="h5" sx={{ color: 'white', fontWeight: 600 }}>
428
- Join our Discord Community
429
  </Typography>
430
- <Typography sx={{ color: 'rgba(255,255,255,0.5)', fontSize: 14, mt: 0.5 }}>
 
 
431
  We are already 4500+ Makers →
432
  </Typography>
433
  </Box>
@@ -438,52 +486,76 @@ function StatsSection() {
438
  <Grid size={{ xs: 12, md: 8 }}>
439
  <Box
440
  component="a"
441
- href="https://huggingface.co/docs/reachy_mini/SDK/overview"
442
  target="_blank"
443
  rel="noopener noreferrer"
444
  sx={{
445
  height: { xs: 200, md: 200 },
446
  borderRadius: 4,
447
- background: '#0d1117',
448
- border: '1px solid rgba(255,255,255,0.08)',
449
  p: { xs: 4, md: 5 },
450
- display: 'flex',
451
- alignItems: 'center',
452
  gap: 4,
453
- textDecoration: 'none',
454
- transition: 'all 0.3s ease',
455
- overflow: 'hidden',
456
- '&:hover': { borderColor: 'rgba(255,255,255,0.2)' },
457
  }}
458
  >
459
  <Box
460
  sx={{
461
  fontFamily: '"JetBrains Mono", monospace',
462
  fontSize: { xs: 12, md: 14 },
463
- color: '#e6edf3',
464
  flex: 1,
465
- whiteSpace: 'pre',
466
- overflow: 'hidden',
467
  }}
468
  >
469
- <Box component="span" sx={{ color: '#ff7b72' }}>from</Box>{' '}
470
- <Box component="span" sx={{ color: '#79c0ff' }}>reachy_mini</Box>{' '}
471
- <Box component="span" sx={{ color: '#ff7b72' }}>import</Box>{' '}
472
- <Box component="span" sx={{ color: '#ffa657' }}>ReachyMini</Box>
473
- {'\n\n'}
474
- <Box component="span" sx={{ color: '#ff7b72' }}>with</Box>{' '}
475
- <Box component="span" sx={{ color: '#ffa657' }}>ReachyMini</Box>
476
- <Box component="span" sx={{ color: '#8b949e' }}>()</Box>{' '}
477
- <Box component="span" sx={{ color: '#ff7b72' }}>as</Box>{' '}
478
- <Box component="span" sx={{ color: '#79c0ff' }}>mini</Box>:
479
- {'\n'}
480
- {' '}mini.<Box component="span" sx={{ color: '#d2a8ff' }}>goto_target</Box>(head=pose)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  </Box>
482
- <Box sx={{ textAlign: 'right' }}>
483
- <Typography variant="h5" sx={{ color: 'white', fontWeight: 600 }}>
484
  Discover the Python SDK
485
  </Typography>
486
- <Typography sx={{ color: 'rgba(255,255,255,0.5)', fontSize: 14, mt: 0.5 }}>
 
 
487
  Full control in 3 lines →
488
  </Typography>
489
  </Box>
@@ -497,27 +569,35 @@ function StatsSection() {
497
  // Products Section - Minimal comparison
498
  function ProductsSection() {
499
  return (
500
- <Section background="alt" sx={{ py: { xs: 8, md: 12 }, position: 'relative', overflow: 'visible' }}>
 
 
 
501
  {/* Stickers */}
502
- <Box sx={{ display: { xs: 'none', lg: 'block' } }}>
503
- <FloatingSticker
504
- src="/assets/reachies/captain.png"
505
- size={240}
506
- top={80}
507
- left={60}
508
- rotation={-8}
509
- floatRange={12}
510
- floatSpeed={5500}
511
- scrollFactor={0.03}
512
  />
513
  </Box>
514
 
515
- <Box sx={{ textAlign: 'center', mb: 8 }}>
516
  <Typography variant="h2" sx={{ mb: 2 }}>
517
  Two ways to Reachy
518
  </Typography>
519
- <Typography variant="body1" color="text.secondary" sx={{ maxWidth: 500, mx: 'auto' }}>
520
- Choose wireless for standalone use, or Lite for a budget-friendly tethered experience.
 
 
 
 
 
521
  </Typography>
522
  </Box>
523
 
@@ -528,26 +608,34 @@ function ProductsSection() {
528
  sx={{
529
  p: 5,
530
  borderRadius: 4,
531
- border: '2px solid',
532
- borderColor: 'primary.main',
533
- background: 'linear-gradient(135deg, rgba(255,149,0,0.03) 0%, transparent 100%)',
534
- textAlign: 'center',
535
- position: 'relative',
 
536
  }}
537
  >
538
  <Box
539
  sx={{
540
- position: 'absolute',
541
  top: -12,
542
- left: '50%',
543
- transform: 'translateX(-50%)',
544
  px: 2,
545
  py: 0.5,
546
  borderRadius: 50,
547
- background: 'linear-gradient(135deg, #FF9500 0%, #ff7b00 100%)',
548
  }}
549
  >
550
- <Typography sx={{ color: 'white', fontSize: 12, fontWeight: 700, textTransform: 'uppercase' }}>
 
 
 
 
 
 
 
551
  Most Popular
552
  </Typography>
553
  </Box>
@@ -564,17 +652,28 @@ function ProductsSection() {
564
  fontSize: 56,
565
  fontWeight: 800,
566
  mb: 3,
567
- background: 'linear-gradient(135deg, #FF9500 0%, #ff7b00 100%)',
568
- WebkitBackgroundClip: 'text',
569
- WebkitTextFillColor: 'transparent',
570
  }}
571
  >
572
  $449
573
  </Typography>
574
 
575
- <Stack spacing={1} sx={{ mb: 4, textAlign: 'left', maxWidth: 280, mx: 'auto' }}>
576
- {['Raspberry Pi 4 on-board', 'Wi-Fi + USB', 'Camera, 4 mics, speaker', 'Accelerometer'].map((item) => (
577
- <Typography key={item} sx={{ fontSize: 14, color: 'text.secondary' }}>
 
 
 
 
 
 
 
 
 
 
 
578
  ✓ {item}
579
  </Typography>
580
  ))}
@@ -599,9 +698,9 @@ function ProductsSection() {
599
  sx={{
600
  p: 5,
601
  borderRadius: 4,
602
- border: '1px solid',
603
- borderColor: 'divider',
604
- textAlign: 'center',
605
  }}
606
  >
607
  <Typography variant="h3" sx={{ mt: 2, mb: 1 }}>
@@ -616,15 +715,26 @@ function ProductsSection() {
616
  fontSize: 56,
617
  fontWeight: 800,
618
  mb: 3,
619
- color: 'text.primary',
620
  }}
621
  >
622
  $299
623
  </Typography>
624
 
625
- <Stack spacing={1} sx={{ mb: 4, textAlign: 'left', maxWidth: 280, mx: 'auto' }}>
626
- {['Your Mac/PC as brain', 'USB only', 'Camera, 4 mics, speaker', 'Same motion capabilities'].map((item) => (
627
- <Typography key={item} sx={{ fontSize: 14, color: 'text.secondary' }}>
 
 
 
 
 
 
 
 
 
 
 
628
  ✓ {item}
629
  </Typography>
630
  ))}
@@ -645,11 +755,11 @@ function ProductsSection() {
645
  </Grid>
646
 
647
  {/* Lead time notice */}
648
- <Box sx={{ textAlign: 'center', mt: 5 }}>
649
  <Typography
650
  variant="body1"
651
  sx={{
652
- color: 'text.primary',
653
  fontWeight: 600,
654
  }}
655
  >
@@ -657,9 +767,15 @@ function ProductsSection() {
657
  </Typography>
658
  </Box>
659
 
660
- <Typography variant="body2" color="text.secondary" sx={{ textAlign: 'center', mt: 3 }}>
661
- Both ship as DIY kits. Assembly takes ~2 hours.{' '}
662
- <Link component={RouterLink} to="/getting-started">Watch the guide →</Link>
 
 
 
 
 
 
663
  </Typography>
664
  </Section>
665
  );
@@ -668,51 +784,60 @@ function ProductsSection() {
668
  // Apps Showcase - Sober design with illustrations
669
  function AppsShowcase() {
670
  const { apps } = useApps();
671
-
672
  // Round down to nearest 10 (e.g., 35 → 30, 42 → 40)
673
  const appsCountRounded = Math.floor(apps.length / 10) * 10;
674
-
675
  return (
676
  <Box
677
  sx={{
678
  py: { xs: 8, md: 12 },
679
- background: '#0a0a12',
680
- position: 'relative',
681
- overflow: 'visible',
682
  }}
683
  >
684
  {/* Sticker */}
685
- <Box sx={{ display: { xs: 'none', lg: 'block' } }}>
686
- <FloatingSticker
687
- src="/assets/reachies/jazzman.png"
688
- size={240}
689
- top={40}
690
- right={80}
691
- rotation={10}
692
- floatRange={10}
693
- floatSpeed={5800}
694
- scrollFactor={0.04}
695
  />
696
  </Box>
697
 
698
  <Container maxWidth="lg">
699
  {/* Header */}
700
- <Box sx={{ textAlign: 'center', mb: 8 }}>
701
  <Typography
702
  variant="overline"
703
- sx={{ color: 'rgba(255,255,255,0.5)', mb: 2, display: 'block', letterSpacing: '0.15em' }}
 
 
 
 
 
704
  >
705
  App Ecosystem
706
  </Typography>
707
- <Typography
708
- variant="h2"
709
- sx={{ color: 'white', mb: 3 }}
710
- >
711
  {appsCountRounded}+ apps, one click install
712
  </Typography>
713
- <Typography sx={{ color: 'rgba(255,255,255,0.5)', maxWidth: 500, mx: 'auto', lineHeight: 1.7 }}>
714
- From AI conversations to hand tracking - explore what the community has built
715
- or create your own and share it with the world.
 
 
 
 
 
 
 
716
  </Typography>
717
  </Box>
718
 
@@ -721,23 +846,23 @@ function AppsShowcase() {
721
  sx={{
722
  mb: 4,
723
  borderRadius: 4,
724
- overflow: 'hidden',
725
- background: '#0f0f1a',
726
- border: '1px solid rgba(255,255,255,0.08)',
727
- display: 'flex',
728
- flexDirection: { xs: 'column', md: 'row' },
729
  }}
730
  >
731
  {/* Illustration */}
732
  <Box
733
  sx={{
734
- flex: { xs: 'none', md: 1 },
735
- height: { xs: 250, md: 'auto' },
736
  minHeight: { md: 320 },
737
- display: 'flex',
738
- alignItems: 'center',
739
- justifyContent: 'center',
740
- overflow: 'hidden',
741
  }}
742
  >
743
  <Box
@@ -745,48 +870,70 @@ function AppsShowcase() {
745
  src="/assets/reachy-conversation-app.jpg"
746
  alt="AI Companion"
747
  sx={{
748
- width: '100%',
749
- height: '100%',
750
- objectFit: 'cover',
751
  }}
752
  />
753
  </Box>
754
-
755
  {/* Content */}
756
  <Box
757
  sx={{
758
- flex: { xs: 'none', md: 1 },
759
  p: { xs: 4, md: 6 },
760
- display: 'flex',
761
- flexDirection: 'column',
762
- justifyContent: 'center',
763
  }}
764
  >
765
  <Box
766
  sx={{
767
- display: 'inline-flex',
768
- alignItems: 'center',
769
  gap: 1,
770
  px: 2,
771
  py: 0.5,
772
  mb: 2,
773
  borderRadius: 50,
774
- background: 'rgba(255,255,255,0.08)',
775
- border: '1px solid rgba(255,255,255,0.1)',
776
- width: 'fit-content',
777
  }}
778
  >
779
- <Box sx={{ width: 6, height: 6, borderRadius: '50%', bgcolor: 'rgba(255,255,255,0.5)' }} />
780
- <Typography sx={{ color: 'rgba(255,255,255,0.7)', fontSize: 11, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.05em' }}>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
781
  Featured
782
  </Typography>
783
  </Box>
784
- <Typography variant="h3" sx={{ color: 'white', mb: 2 }}>
785
  AI Companion
786
  </Typography>
787
- <Typography sx={{ color: 'rgba(255,255,255,0.6)', mb: 4, lineHeight: 1.8, maxWidth: 400 }}>
788
- Have a conversation with Reachy! Powered by LLMs, it understands what you say
789
- and responds with expressive movements and speech.
 
 
 
 
 
 
 
790
  </Typography>
791
  <Button
792
  component={RouterLink}
@@ -806,22 +953,22 @@ function AppsShowcase() {
806
  <Box
807
  sx={{
808
  borderRadius: 4,
809
- overflow: 'hidden',
810
- background: '#0f0f1a',
811
- border: '1px solid rgba(255,255,255,0.08)',
812
- display: 'flex',
813
- flexDirection: { xs: 'column', sm: 'row' },
814
- height: { xs: 'auto', md: 200 },
815
- transition: 'border-color 0.3s',
816
- '&:hover': { borderColor: 'rgba(255,255,255,0.2)' },
817
  }}
818
  >
819
  <Box
820
  sx={{
821
- width: { xs: '100%', sm: 200 },
822
- height: { xs: 150, sm: 'auto' },
823
  flexShrink: 0,
824
- overflow: 'hidden',
825
  }}
826
  >
827
  <Box
@@ -829,17 +976,30 @@ function AppsShowcase() {
829
  src="/assets/reachy-hand-tracking-app.jpg"
830
  alt="Hand Tracking"
831
  sx={{
832
- width: '100%',
833
- height: '100%',
834
- objectFit: 'cover',
835
  }}
836
  />
837
  </Box>
838
- <Box sx={{ p: 3, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
839
- <Typography variant="h5" sx={{ color: 'white', mb: 1 }}>
 
 
 
 
 
 
 
840
  Hand Tracking
841
  </Typography>
842
- <Typography sx={{ color: 'rgba(255,255,255,0.5)', fontSize: 14, lineHeight: 1.6 }}>
 
 
 
 
 
 
843
  Reachy follows your hand movements in real-time using OpenCV.
844
  </Typography>
845
  </Box>
@@ -854,31 +1014,35 @@ function AppsShowcase() {
854
  sx={{
855
  borderRadius: 4,
856
  height: { xs: 150, md: 200 },
857
- background: '#0f0f1a',
858
- border: '1px solid rgba(255,255,255,0.08)',
859
- display: 'flex',
860
- flexDirection: 'column',
861
- alignItems: 'center',
862
- justifyContent: 'center',
863
- textDecoration: 'none',
864
- transition: 'all 0.3s',
865
- '&:hover': { borderColor: 'rgba(255,255,255,0.2)' },
866
  }}
867
  >
868
  <Typography
869
  sx={{
870
  fontSize: 48,
871
  fontWeight: 800,
872
- color: 'white',
873
  mb: 1,
874
  }}
875
  >
876
  +{appsCountRounded}
877
  </Typography>
878
- <Typography sx={{ color: 'rgba(255,255,255,0.7)', fontWeight: 600 }}>
 
 
879
  more apps to explore
880
  </Typography>
881
- <Typography sx={{ color: 'rgba(255,255,255,0.4)', fontSize: 13, mt: 0.5 }}>
 
 
882
  Browse all →
883
  </Typography>
884
  </Box>
@@ -886,14 +1050,18 @@ function AppsShowcase() {
886
  </Grid>
887
 
888
  {/* Build your own CTA */}
889
- <Box sx={{ textAlign: 'center', mt: 6 }}>
890
- <Typography sx={{ color: 'rgba(255,255,255,0.4)', fontSize: 14 }}>
891
- Got an idea?{' '}
892
  <Link
893
  href="https://huggingface.co/docs/reachy_mini/"
894
  target="_blank"
895
  rel="noopener noreferrer"
896
- sx={{ color: 'primary.main', textDecoration: 'none', '&:hover': { textDecoration: 'underline' } }}
 
 
 
 
897
  >
898
  Build your own app →
899
  </Link>
@@ -907,30 +1075,58 @@ function AppsShowcase() {
907
  // Community Section
908
  function CommunitySection() {
909
  return (
910
- <Section sx={{ py: { xs: 8, md: 12 }, position: 'relative', overflow: 'visible' }}>
911
- <Box sx={{ display: { xs: 'none', md: 'block' } }}>
912
- <FloatingSticker src="/assets/reachies/cowboy.png" size={280} top={-20} left={100} rotation={-10} floatRange={12} floatSpeed={5500} scrollFactor={0.04} />
913
- <FloatingSticker src="/assets/reachies/astronaut.png" size={300} bottom={-40} right={120} rotation={8} floatRange={15} floatSpeed={6500} scrollFactor={0.05} />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
914
  </Box>
915
 
916
  <Box
917
  sx={{
918
- background: '#0f0f1a',
919
- border: '1px solid rgba(255,255,255,0.08)',
920
  borderRadius: 4,
921
  p: { xs: 5, md: 8 },
922
- textAlign: 'center',
923
- color: 'white',
924
- position: 'relative',
925
  }}
926
  >
927
- <Box sx={{ position: 'relative', zIndex: 1 }}>
928
  <Typography variant="h2" sx={{ mb: 2 }}>
929
  Join 4500+ makers
930
  </Typography>
931
- <Typography sx={{ color: 'rgba(255,255,255,0.6)', maxWidth: 500, mx: 'auto', mb: 4, lineHeight: 1.8 }}>
932
- Connect with other Reachy Mini owners on Discord. Share your projects,
933
- get help, and stay updated on the latest developments.
 
 
 
 
 
 
 
 
934
  </Typography>
935
  <Button
936
  variant="contained"
@@ -951,16 +1147,24 @@ function CommunitySection() {
951
  function FinalCTA() {
952
  return (
953
  <Section background="alt" sx={{ py: { xs: 8, md: 12 } }}>
954
- <Box sx={{ textAlign: 'center', maxWidth: 600, mx: 'auto' }}>
955
  <Typography variant="h2" sx={{ mb: 3 }}>
956
  Ready to meet Reachy?
957
  </Typography>
958
- <Typography variant="body1" color="text.secondary" sx={{ mb: 5, lineHeight: 1.8 }}>
959
- Get your own expressive companion robot and join the community of makers
960
- building the future of human-robot interaction.
 
 
 
 
961
  </Typography>
962
 
963
- <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2} justifyContent="center">
 
 
 
 
964
  <Button
965
  variant="contained"
966
  size="large"
@@ -970,7 +1174,6 @@ function FinalCTA() {
970
  >
971
  Buy Reachy Mini
972
  </Button>
973
-
974
  </Stack>
975
 
976
  {/* <Stack direction={{ xs: 'column', sm: 'row' }} spacing={{ xs: 1, sm: 4 }} justifyContent="center" sx={{ mt: 5, color: 'text.secondary' }}>
 
1
+ import { useState, useEffect } from "react";
2
+ import { Link as RouterLink } from "react-router-dom";
3
  import {
4
  Box,
5
  Container,
 
8
  Grid,
9
  Stack,
10
  Link,
11
+ } from "@mui/material";
12
+ import { useSpring, animated } from "@react-spring/web";
13
+ import OpenInNewIcon from "@mui/icons-material/OpenInNew";
14
+ import ArrowForwardIcon from "@mui/icons-material/ArrowForward";
15
 
16
+ import Layout from "../components/Layout";
17
+ import Section from "../components/Section";
18
+ import { useApps } from "../context/AppsContext";
19
 
20
  // Floating Sticker Component with scroll parallax
21
+ function FloatingSticker({
22
+ src,
23
+ size,
24
+ top,
25
+ left,
26
+ right,
27
+ bottom,
28
+ rotation = 0,
29
+ floatRange = 15,
30
+ floatSpeed = 6000,
31
+ scrollFactor = 0.05,
32
+ }) {
33
  const [floatOffset, setFloatOffset] = useState(0);
34
  const [scrollY, setScrollY] = useState(0);
35
 
 
38
  let animationFrame;
39
  const animate = () => {
40
  const elapsed = Date.now() - startTime;
41
+ const offset =
42
+ Math.sin((elapsed / floatSpeed) * Math.PI * 2) * floatRange;
43
  setFloatOffset(offset);
44
  animationFrame = requestAnimationFrame(animate);
45
  };
 
49
 
50
  useEffect(() => {
51
  const handleScroll = () => setScrollY(window.scrollY);
52
+ window.addEventListener("scroll", handleScroll, { passive: true });
53
+ return () => window.removeEventListener("scroll", handleScroll);
54
  }, []);
55
 
56
  const springProps = useSpring({
 
63
  src={src}
64
  alt=""
65
  style={{
66
+ position: "absolute",
67
+ top,
68
+ left,
69
+ right,
70
+ bottom,
71
  width: size,
72
+ height: "auto",
73
+ pointerEvents: "none",
74
  zIndex: 2,
75
  ...springProps,
76
  }}
 
84
 
85
  useEffect(() => {
86
  const handleScroll = () => setScrollY(window.scrollY);
87
+ window.addEventListener("scroll", handleScroll, { passive: true });
88
+ return () => window.removeEventListener("scroll", handleScroll);
89
  }, []);
90
 
91
  const videoParallax = useSpring({
 
96
  return (
97
  <Box
98
  sx={{
99
+ position: "relative",
100
+ minHeight: { xs: "85vh", md: "80vh" },
101
+ display: "flex",
102
+ alignItems: { xs: "flex-end", md: "center" },
103
  pb: { xs: 12, md: 0 },
104
+ backgroundColor: "#000",
105
+ overflow: "hidden",
106
  // Curved bottom edge
107
+ "&::after": {
108
  content: '""',
109
+ position: "absolute",
110
  bottom: -1,
111
  left: 0,
112
  right: 0,
113
  height: { xs: 60, md: 90 },
114
+ background: "inherit",
115
+ backgroundColor: "background.default",
116
+ borderRadius: "100% 100% 0 0 / 100% 100% 0 0",
117
+ transform: "translateY(50%)",
118
  },
119
  }}
120
  >
 
124
  loop
125
  playsInline
126
  style={{
127
+ position: "absolute",
128
+ top: "50%",
129
+ left: "50%",
130
+ minWidth: "100%",
131
+ minHeight: "100%",
132
+ width: "auto",
133
+ height: "auto",
134
  opacity: 0.9,
135
  ...videoParallax,
136
  }}
137
  >
138
+ <source
139
+ src="/assets/Reachy-mini-wake-up-companion.mp4"
140
+ type="video/mp4"
141
+ />
142
  </animated.video>
143
 
144
  {/* Overlay gradients + vignette */}
145
  <Box
146
  sx={{
147
+ position: "absolute",
148
  inset: 0,
149
  background: `
150
  linear-gradient(to right, rgba(0,0,0,0.75) 0%, rgba(0,0,0,0.4) 40%, rgba(0,0,0,0.15) 100%),
 
154
  }}
155
  />
156
 
157
+ <Container maxWidth="lg" sx={{ position: "relative", zIndex: 10 }}>
158
  <Box sx={{ maxWidth: 640 }}>
159
  <Stack direction="row" spacing={1} alignItems="center" sx={{ mb: 2 }}>
160
  <Typography
161
  sx={{
162
+ color: "rgba(255,255,255,0.6)",
163
  fontSize: 13,
164
  fontWeight: 500,
165
  }}
166
  >
167
  Open Source Robot
168
  </Typography>
169
+ <Box
170
+ sx={{
171
+ width: 4,
172
+ height: 4,
173
+ borderRadius: "50%",
174
+ bgcolor: "rgba(255,255,255,0.3)",
175
+ }}
176
+ />
177
  <Typography
178
  sx={{
179
+ color: "rgba(255,255,255,0.6)",
180
  fontSize: 13,
181
  fontWeight: 500,
182
+ display: "flex",
183
+ alignItems: "center",
184
  gap: 0.5,
185
  }}
186
  >
187
+ Powered by{" "}
188
+ <Box
189
+ component="img"
190
+ src="/assets/hf-logo.svg"
191
+ alt="Hugging Face"
192
+ sx={{ height: 14 }}
193
+ />
194
  </Typography>
195
  </Stack>
196
 
197
+ <Box sx={{ position: "relative", display: "inline-block", mb: 2 }}>
198
  <Typography
199
  variant="h1"
200
  component="h1"
201
  sx={{
202
+ color: "white",
203
+ background:
204
+ "linear-gradient(135deg, #ffffff 0%, rgba(255,255,255,0.85) 100%)",
205
+ backgroundClip: "text",
206
+ WebkitBackgroundClip: "text",
207
+ WebkitTextFillColor: "transparent",
208
  }}
209
  >
210
  Reachy Mini
 
215
  variant="h5"
216
  component="p"
217
  sx={{
218
+ color: "rgba(255,255,255,0.75)",
219
  fontWeight: 400,
220
  mb: 4,
221
  lineHeight: 1.6,
222
  maxWidth: 520,
223
  }}
224
  >
225
+ An expressive companion robot designed for{" "}
226
+ <Box component="span" sx={{ color: "white", fontWeight: 500 }}>
227
  human interaction
228
  </Box>
229
+ ,{" "}
230
+ <Box component="span" sx={{ color: "white", fontWeight: 500 }}>
231
  creative coding
232
  </Box>
233
+ , and{" "}
234
+ <Box component="span" sx={{ color: "white", fontWeight: 500 }}>
235
  AI experimentation
236
  </Box>
237
  .
238
  </Typography>
239
 
240
+ <Stack direction={{ xs: "column", sm: "row" }} spacing={2}>
241
  <Button
242
  component={RouterLink}
243
  to="/buy"
 
248
  py: 1.75,
249
  fontSize: 16,
250
  fontWeight: 600,
251
+ background: "linear-gradient(135deg, #FF9500 0%, #ff7b00 100%)",
252
+ boxShadow: "0 4px 24px rgba(255, 149, 0, 0.35)",
253
+ "&:hover": {
254
+ boxShadow: "0 8px 32px rgba(255, 149, 0, 0.5)",
255
+ transform: "translateY(-2px)",
256
  },
257
  }}
258
  >
 
268
  py: 1.75,
269
  fontSize: 16,
270
  fontWeight: 600,
271
+ color: "rgba(255,255,255,0.9)",
272
+ borderColor: "rgba(255,255,255,0.3)",
273
+ "&:hover": {
274
+ color: "white",
275
+ borderColor: "rgba(255,255,255,0.6)",
276
+ backgroundColor: "rgba(255,255,255,0.05)",
277
  },
278
  }}
279
  >
 
282
  </Stack>
283
  </Box>
284
  </Container>
 
285
  </Box>
286
  );
287
  }
 
289
  // Stats/Bento Section - Sober backgrounds, illustrations for color
290
  function StatsSection() {
291
  return (
292
+ <Section
293
+ id="stats"
294
+ sx={{ py: { xs: 8, md: 12 }, position: "relative", overflow: "visible" }}
295
+ >
296
+ <Grid container spacing={2} sx={{ overflow: "visible" }}>
297
  {/* Big stat - Open Source */}
298
+ <Grid size={{ xs: 12, md: 8 }} sx={{ overflow: "visible" }}>
299
  <Box
300
  component={RouterLink}
301
  to="/getting-started"
302
  sx={{
303
  height: { xs: 280, md: 320 },
304
  borderRadius: 4,
305
+ background: "#0f0f1a",
306
+ border: "1px solid rgba(255,255,255,0.08)",
307
  p: { xs: 4, md: 6 },
308
+ position: "relative",
309
+ display: "flex",
310
+ flexDirection: "column",
311
+ justifyContent: "space-between",
312
  // Clip only bottom and left, allow top and right overflow
313
+ clipPath: "inset(-100px -50px 0 0 round 16px)",
314
+ textDecoration: "none",
315
+ color: "inherit",
316
+ cursor: "pointer",
317
+ transition: "border-color 0.3s ease, transform 0.3s ease",
318
+ "&:hover": {
319
+ borderColor: "rgba(255,255,255,0.2)",
320
+ transform: "translateY(-2px)",
321
  },
322
  }}
323
  >
324
  {/* How to create app illustration - floating */}
325
+ <Box sx={{ display: { xs: "none", sm: "block" } }}>
326
  <FloatingSticker
327
  src="/assets/reachy-how-to-create-app.svg"
328
  size={336}
 
334
  scrollFactor={0.03}
335
  />
336
  </Box>
337
+ <Box sx={{ position: "relative", zIndex: 1 }}>
338
  <Typography
339
  sx={{
340
  fontSize: { xs: 50, md: 60 },
341
  fontWeight: 800,
342
  lineHeight: 1,
343
+ color: "white",
344
  }}
345
  >
346
+ Build your
347
+ <br />
348
  own robot
349
  </Typography>
350
  <Typography
351
  variant="h4"
352
+ sx={{ color: "white", fontWeight: 600, mt: 1 }}
353
  >
354
  Get Started
355
  </Typography>
356
  </Box>
357
+ <Typography
358
+ sx={{
359
+ color: "rgba(255,255,255,0.5)",
360
+ fontSize: 15,
361
+ position: "relative",
362
+ zIndex: 1,
363
+ maxWidth: 400,
364
+ }}
365
+ >
366
  Follow our guides to assemble your Reachy Mini →
367
  </Typography>
368
  </Box>
 
376
  sx={{
377
  height: { xs: 280, md: 320 },
378
  borderRadius: 4,
379
+ background: "#0f0f1a",
380
+ border: "1px solid rgba(255,255,255,0.08)",
381
+ overflow: "hidden",
382
+ position: "relative",
383
+ textDecoration: "none",
384
+ display: "block",
385
+ transition: "all 0.3s ease",
386
+ "&:hover": { borderColor: "rgba(255,255,255,0.2)" },
387
  }}
388
  >
389
  {/* GIF Background */}
 
392
  src="/assets/reachy-mini-hand-tracking.gif"
393
  alt="Real-time interaction"
394
  sx={{
395
+ position: "absolute",
396
  top: 0,
397
  left: 0,
398
+ width: "100%",
399
+ height: "100%",
400
+ objectFit: "cover",
401
  }}
402
  />
403
  {/* Overlay gradient */}
404
  <Box
405
  sx={{
406
+ position: "absolute",
407
  inset: 0,
408
+ background:
409
+ "linear-gradient(to top, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.3) 50%, rgba(0,0,0,0.1) 100%)",
410
  }}
411
  />
412
  {/* Content */}
413
  <Box
414
  sx={{
415
+ position: "relative",
416
  zIndex: 1,
417
+ height: "100%",
418
  p: { xs: 4, md: 5 },
419
+ display: "flex",
420
+ flexDirection: "column",
421
+ justifyContent: "flex-end",
422
  }}
423
  >
424
  <Typography
 
426
  fontSize: { xs: 56, md: 72 },
427
  fontWeight: 800,
428
  lineHeight: 1,
429
+ color: "white",
430
  }}
431
  >
432
  Apps
433
  </Typography>
434
  <Box sx={{ mt: 1 }}>
435
+ <Typography
436
+ sx={{ color: "rgba(255,255,255,0.6)", fontSize: 14, mt: 0.5 }}
437
+ >
438
  Explore ready-to-use app →
439
  </Typography>
440
  </Box>
 
452
  sx={{
453
  height: { xs: 200, md: 200 },
454
  borderRadius: 4,
455
+ background: "#0f0f1a",
456
+ border: "1px solid rgba(255,255,255,0.08)",
457
  p: { xs: 4, md: 5 },
458
+ display: "flex",
459
+ flexDirection: "column",
460
+ justifyContent: "space-between",
461
+ textDecoration: "none",
462
+ transition: "all 0.3s ease",
463
+ "&:hover": { borderColor: "rgba(255,255,255,0.2)" },
464
  }}
465
  >
466
  <Box
 
470
  sx={{ width: 36, height: 36, opacity: 0.8 }}
471
  />
472
  <Box>
473
+ <Typography variant="h5" sx={{ color: "white", fontWeight: 600 }}>
474
+ Join our Discord Community
475
  </Typography>
476
+ <Typography
477
+ sx={{ color: "rgba(255,255,255,0.5)", fontSize: 14, mt: 0.5 }}
478
+ >
479
  We are already 4500+ Makers →
480
  </Typography>
481
  </Box>
 
486
  <Grid size={{ xs: 12, md: 8 }}>
487
  <Box
488
  component="a"
489
+ href="https://huggingface.co/docs/reachy_mini/SDK/readme"
490
  target="_blank"
491
  rel="noopener noreferrer"
492
  sx={{
493
  height: { xs: 200, md: 200 },
494
  borderRadius: 4,
495
+ background: "#0d1117",
496
+ border: "1px solid rgba(255,255,255,0.08)",
497
  p: { xs: 4, md: 5 },
498
+ display: "flex",
499
+ alignItems: "center",
500
  gap: 4,
501
+ textDecoration: "none",
502
+ transition: "all 0.3s ease",
503
+ overflow: "hidden",
504
+ "&:hover": { borderColor: "rgba(255,255,255,0.2)" },
505
  }}
506
  >
507
  <Box
508
  sx={{
509
  fontFamily: '"JetBrains Mono", monospace',
510
  fontSize: { xs: 12, md: 14 },
511
+ color: "#e6edf3",
512
  flex: 1,
513
+ whiteSpace: "pre",
514
+ overflow: "hidden",
515
  }}
516
  >
517
+ <Box component="span" sx={{ color: "#ff7b72" }}>
518
+ from
519
+ </Box>{" "}
520
+ <Box component="span" sx={{ color: "#79c0ff" }}>
521
+ reachy_mini
522
+ </Box>{" "}
523
+ <Box component="span" sx={{ color: "#ff7b72" }}>
524
+ import
525
+ </Box>{" "}
526
+ <Box component="span" sx={{ color: "#ffa657" }}>
527
+ ReachyMini
528
+ </Box>
529
+ {"\n\n"}
530
+ <Box component="span" sx={{ color: "#ff7b72" }}>
531
+ with
532
+ </Box>{" "}
533
+ <Box component="span" sx={{ color: "#ffa657" }}>
534
+ ReachyMini
535
+ </Box>
536
+ <Box component="span" sx={{ color: "#8b949e" }}>
537
+ ()
538
+ </Box>{" "}
539
+ <Box component="span" sx={{ color: "#ff7b72" }}>
540
+ as
541
+ </Box>{" "}
542
+ <Box component="span" sx={{ color: "#79c0ff" }}>
543
+ mini
544
+ </Box>
545
+ :{"\n"}
546
+ {" "}mini.
547
+ <Box component="span" sx={{ color: "#d2a8ff" }}>
548
+ goto_target
549
+ </Box>
550
+ (head=pose)
551
  </Box>
552
+ <Box sx={{ textAlign: "right" }}>
553
+ <Typography variant="h5" sx={{ color: "white", fontWeight: 600 }}>
554
  Discover the Python SDK
555
  </Typography>
556
+ <Typography
557
+ sx={{ color: "rgba(255,255,255,0.5)", fontSize: 14, mt: 0.5 }}
558
+ >
559
  Full control in 3 lines →
560
  </Typography>
561
  </Box>
 
569
  // Products Section - Minimal comparison
570
  function ProductsSection() {
571
  return (
572
+ <Section
573
+ background="alt"
574
+ sx={{ py: { xs: 8, md: 12 }, position: "relative", overflow: "visible" }}
575
+ >
576
  {/* Stickers */}
577
+ <Box sx={{ display: { xs: "none", lg: "block" } }}>
578
+ <FloatingSticker
579
+ src="/assets/reachies/captain.png"
580
+ size={240}
581
+ top={80}
582
+ left={60}
583
+ rotation={-8}
584
+ floatRange={12}
585
+ floatSpeed={5500}
586
+ scrollFactor={0.03}
587
  />
588
  </Box>
589
 
590
+ <Box sx={{ textAlign: "center", mb: 8 }}>
591
  <Typography variant="h2" sx={{ mb: 2 }}>
592
  Two ways to Reachy
593
  </Typography>
594
+ <Typography
595
+ variant="body1"
596
+ color="text.secondary"
597
+ sx={{ maxWidth: 500, mx: "auto" }}
598
+ >
599
+ Choose wireless for standalone use, or Lite for a budget-friendly
600
+ tethered experience.
601
  </Typography>
602
  </Box>
603
 
 
608
  sx={{
609
  p: 5,
610
  borderRadius: 4,
611
+ border: "2px solid",
612
+ borderColor: "primary.main",
613
+ background:
614
+ "linear-gradient(135deg, rgba(255,149,0,0.03) 0%, transparent 100%)",
615
+ textAlign: "center",
616
+ position: "relative",
617
  }}
618
  >
619
  <Box
620
  sx={{
621
+ position: "absolute",
622
  top: -12,
623
+ left: "50%",
624
+ transform: "translateX(-50%)",
625
  px: 2,
626
  py: 0.5,
627
  borderRadius: 50,
628
+ background: "linear-gradient(135deg, #FF9500 0%, #ff7b00 100%)",
629
  }}
630
  >
631
+ <Typography
632
+ sx={{
633
+ color: "white",
634
+ fontSize: 12,
635
+ fontWeight: 700,
636
+ textTransform: "uppercase",
637
+ }}
638
+ >
639
  Most Popular
640
  </Typography>
641
  </Box>
 
652
  fontSize: 56,
653
  fontWeight: 800,
654
  mb: 3,
655
+ background: "linear-gradient(135deg, #FF9500 0%, #ff7b00 100%)",
656
+ WebkitBackgroundClip: "text",
657
+ WebkitTextFillColor: "transparent",
658
  }}
659
  >
660
  $449
661
  </Typography>
662
 
663
+ <Stack
664
+ spacing={1}
665
+ sx={{ mb: 4, textAlign: "left", maxWidth: 280, mx: "auto" }}
666
+ >
667
+ {[
668
+ "Raspberry Pi 4 on-board",
669
+ "Wi-Fi + USB",
670
+ "Camera, 4 mics, speaker",
671
+ "Accelerometer",
672
+ ].map((item) => (
673
+ <Typography
674
+ key={item}
675
+ sx={{ fontSize: 14, color: "text.secondary" }}
676
+ >
677
  ✓ {item}
678
  </Typography>
679
  ))}
 
698
  sx={{
699
  p: 5,
700
  borderRadius: 4,
701
+ border: "1px solid",
702
+ borderColor: "divider",
703
+ textAlign: "center",
704
  }}
705
  >
706
  <Typography variant="h3" sx={{ mt: 2, mb: 1 }}>
 
715
  fontSize: 56,
716
  fontWeight: 800,
717
  mb: 3,
718
+ color: "text.primary",
719
  }}
720
  >
721
  $299
722
  </Typography>
723
 
724
+ <Stack
725
+ spacing={1}
726
+ sx={{ mb: 4, textAlign: "left", maxWidth: 280, mx: "auto" }}
727
+ >
728
+ {[
729
+ "Your Mac/PC as brain",
730
+ "USB only",
731
+ "Camera, 4 mics, speaker",
732
+ "Same motion capabilities",
733
+ ].map((item) => (
734
+ <Typography
735
+ key={item}
736
+ sx={{ fontSize: 14, color: "text.secondary" }}
737
+ >
738
  ✓ {item}
739
  </Typography>
740
  ))}
 
755
  </Grid>
756
 
757
  {/* Lead time notice */}
758
+ <Box sx={{ textAlign: "center", mt: 5 }}>
759
  <Typography
760
  variant="body1"
761
  sx={{
762
+ color: "text.primary",
763
  fontWeight: 600,
764
  }}
765
  >
 
767
  </Typography>
768
  </Box>
769
 
770
+ <Typography
771
+ variant="body2"
772
+ color="text.secondary"
773
+ sx={{ textAlign: "center", mt: 3 }}
774
+ >
775
+ Both ship as DIY kits. Assembly takes ~2 hours.{" "}
776
+ <Link component={RouterLink} to="/getting-started">
777
+ Watch the guide →
778
+ </Link>
779
  </Typography>
780
  </Section>
781
  );
 
784
  // Apps Showcase - Sober design with illustrations
785
  function AppsShowcase() {
786
  const { apps } = useApps();
787
+
788
  // Round down to nearest 10 (e.g., 35 → 30, 42 → 40)
789
  const appsCountRounded = Math.floor(apps.length / 10) * 10;
790
+
791
  return (
792
  <Box
793
  sx={{
794
  py: { xs: 8, md: 12 },
795
+ background: "#0a0a12",
796
+ position: "relative",
797
+ overflow: "visible",
798
  }}
799
  >
800
  {/* Sticker */}
801
+ <Box sx={{ display: { xs: "none", lg: "block" } }}>
802
+ <FloatingSticker
803
+ src="/assets/reachies/jazzman.png"
804
+ size={240}
805
+ top={40}
806
+ right={80}
807
+ rotation={10}
808
+ floatRange={10}
809
+ floatSpeed={5800}
810
+ scrollFactor={0.04}
811
  />
812
  </Box>
813
 
814
  <Container maxWidth="lg">
815
  {/* Header */}
816
+ <Box sx={{ textAlign: "center", mb: 8 }}>
817
  <Typography
818
  variant="overline"
819
+ sx={{
820
+ color: "rgba(255,255,255,0.5)",
821
+ mb: 2,
822
+ display: "block",
823
+ letterSpacing: "0.15em",
824
+ }}
825
  >
826
  App Ecosystem
827
  </Typography>
828
+ <Typography variant="h2" sx={{ color: "white", mb: 3 }}>
 
 
 
829
  {appsCountRounded}+ apps, one click install
830
  </Typography>
831
+ <Typography
832
+ sx={{
833
+ color: "rgba(255,255,255,0.5)",
834
+ maxWidth: 500,
835
+ mx: "auto",
836
+ lineHeight: 1.7,
837
+ }}
838
+ >
839
+ From AI conversations to hand tracking - explore what the community
840
+ has built or create your own and share it with the world.
841
  </Typography>
842
  </Box>
843
 
 
846
  sx={{
847
  mb: 4,
848
  borderRadius: 4,
849
+ overflow: "hidden",
850
+ background: "#0f0f1a",
851
+ border: "1px solid rgba(255,255,255,0.08)",
852
+ display: "flex",
853
+ flexDirection: { xs: "column", md: "row" },
854
  }}
855
  >
856
  {/* Illustration */}
857
  <Box
858
  sx={{
859
+ flex: { xs: "none", md: 1 },
860
+ height: { xs: 250, md: "auto" },
861
  minHeight: { md: 320 },
862
+ display: "flex",
863
+ alignItems: "center",
864
+ justifyContent: "center",
865
+ overflow: "hidden",
866
  }}
867
  >
868
  <Box
 
870
  src="/assets/reachy-conversation-app.jpg"
871
  alt="AI Companion"
872
  sx={{
873
+ width: "100%",
874
+ height: "100%",
875
+ objectFit: "cover",
876
  }}
877
  />
878
  </Box>
879
+
880
  {/* Content */}
881
  <Box
882
  sx={{
883
+ flex: { xs: "none", md: 1 },
884
  p: { xs: 4, md: 6 },
885
+ display: "flex",
886
+ flexDirection: "column",
887
+ justifyContent: "center",
888
  }}
889
  >
890
  <Box
891
  sx={{
892
+ display: "inline-flex",
893
+ alignItems: "center",
894
  gap: 1,
895
  px: 2,
896
  py: 0.5,
897
  mb: 2,
898
  borderRadius: 50,
899
+ background: "rgba(255,255,255,0.08)",
900
+ border: "1px solid rgba(255,255,255,0.1)",
901
+ width: "fit-content",
902
  }}
903
  >
904
+ <Box
905
+ sx={{
906
+ width: 6,
907
+ height: 6,
908
+ borderRadius: "50%",
909
+ bgcolor: "rgba(255,255,255,0.5)",
910
+ }}
911
+ />
912
+ <Typography
913
+ sx={{
914
+ color: "rgba(255,255,255,0.7)",
915
+ fontSize: 11,
916
+ fontWeight: 600,
917
+ textTransform: "uppercase",
918
+ letterSpacing: "0.05em",
919
+ }}
920
+ >
921
  Featured
922
  </Typography>
923
  </Box>
924
+ <Typography variant="h3" sx={{ color: "white", mb: 2 }}>
925
  AI Companion
926
  </Typography>
927
+ <Typography
928
+ sx={{
929
+ color: "rgba(255,255,255,0.6)",
930
+ mb: 4,
931
+ lineHeight: 1.8,
932
+ maxWidth: 400,
933
+ }}
934
+ >
935
+ Have a conversation with Reachy! Powered by LLMs, it understands
936
+ what you say and responds with expressive movements and speech.
937
  </Typography>
938
  <Button
939
  component={RouterLink}
 
953
  <Box
954
  sx={{
955
  borderRadius: 4,
956
+ overflow: "hidden",
957
+ background: "#0f0f1a",
958
+ border: "1px solid rgba(255,255,255,0.08)",
959
+ display: "flex",
960
+ flexDirection: { xs: "column", sm: "row" },
961
+ height: { xs: "auto", md: 200 },
962
+ transition: "border-color 0.3s",
963
+ "&:hover": { borderColor: "rgba(255,255,255,0.2)" },
964
  }}
965
  >
966
  <Box
967
  sx={{
968
+ width: { xs: "100%", sm: 200 },
969
+ height: { xs: 150, sm: "auto" },
970
  flexShrink: 0,
971
+ overflow: "hidden",
972
  }}
973
  >
974
  <Box
 
976
  src="/assets/reachy-hand-tracking-app.jpg"
977
  alt="Hand Tracking"
978
  sx={{
979
+ width: "100%",
980
+ height: "100%",
981
+ objectFit: "cover",
982
  }}
983
  />
984
  </Box>
985
+ <Box
986
+ sx={{
987
+ p: 3,
988
+ display: "flex",
989
+ flexDirection: "column",
990
+ justifyContent: "center",
991
+ }}
992
+ >
993
+ <Typography variant="h5" sx={{ color: "white", mb: 1 }}>
994
  Hand Tracking
995
  </Typography>
996
+ <Typography
997
+ sx={{
998
+ color: "rgba(255,255,255,0.5)",
999
+ fontSize: 14,
1000
+ lineHeight: 1.6,
1001
+ }}
1002
+ >
1003
  Reachy follows your hand movements in real-time using OpenCV.
1004
  </Typography>
1005
  </Box>
 
1014
  sx={{
1015
  borderRadius: 4,
1016
  height: { xs: 150, md: 200 },
1017
+ background: "#0f0f1a",
1018
+ border: "1px solid rgba(255,255,255,0.08)",
1019
+ display: "flex",
1020
+ flexDirection: "column",
1021
+ alignItems: "center",
1022
+ justifyContent: "center",
1023
+ textDecoration: "none",
1024
+ transition: "all 0.3s",
1025
+ "&:hover": { borderColor: "rgba(255,255,255,0.2)" },
1026
  }}
1027
  >
1028
  <Typography
1029
  sx={{
1030
  fontSize: 48,
1031
  fontWeight: 800,
1032
+ color: "white",
1033
  mb: 1,
1034
  }}
1035
  >
1036
  +{appsCountRounded}
1037
  </Typography>
1038
+ <Typography
1039
+ sx={{ color: "rgba(255,255,255,0.7)", fontWeight: 600 }}
1040
+ >
1041
  more apps to explore
1042
  </Typography>
1043
+ <Typography
1044
+ sx={{ color: "rgba(255,255,255,0.4)", fontSize: 13, mt: 0.5 }}
1045
+ >
1046
  Browse all →
1047
  </Typography>
1048
  </Box>
 
1050
  </Grid>
1051
 
1052
  {/* Build your own CTA */}
1053
+ <Box sx={{ textAlign: "center", mt: 6 }}>
1054
+ <Typography sx={{ color: "rgba(255,255,255,0.4)", fontSize: 14 }}>
1055
+ Got an idea?{" "}
1056
  <Link
1057
  href="https://huggingface.co/docs/reachy_mini/"
1058
  target="_blank"
1059
  rel="noopener noreferrer"
1060
+ sx={{
1061
+ color: "primary.main",
1062
+ textDecoration: "none",
1063
+ "&:hover": { textDecoration: "underline" },
1064
+ }}
1065
  >
1066
  Build your own app →
1067
  </Link>
 
1075
  // Community Section
1076
  function CommunitySection() {
1077
  return (
1078
+ <Section
1079
+ sx={{ py: { xs: 8, md: 12 }, position: "relative", overflow: "visible" }}
1080
+ >
1081
+ <Box sx={{ display: { xs: "none", md: "block" } }}>
1082
+ <FloatingSticker
1083
+ src="/assets/reachies/cowboy.png"
1084
+ size={280}
1085
+ top={-20}
1086
+ left={100}
1087
+ rotation={-10}
1088
+ floatRange={12}
1089
+ floatSpeed={5500}
1090
+ scrollFactor={0.04}
1091
+ />
1092
+ <FloatingSticker
1093
+ src="/assets/reachies/astronaut.png"
1094
+ size={300}
1095
+ bottom={-40}
1096
+ right={120}
1097
+ rotation={8}
1098
+ floatRange={15}
1099
+ floatSpeed={6500}
1100
+ scrollFactor={0.05}
1101
+ />
1102
  </Box>
1103
 
1104
  <Box
1105
  sx={{
1106
+ background: "#0f0f1a",
1107
+ border: "1px solid rgba(255,255,255,0.08)",
1108
  borderRadius: 4,
1109
  p: { xs: 5, md: 8 },
1110
+ textAlign: "center",
1111
+ color: "white",
1112
+ position: "relative",
1113
  }}
1114
  >
1115
+ <Box sx={{ position: "relative", zIndex: 1 }}>
1116
  <Typography variant="h2" sx={{ mb: 2 }}>
1117
  Join 4500+ makers
1118
  </Typography>
1119
+ <Typography
1120
+ sx={{
1121
+ color: "rgba(255,255,255,0.6)",
1122
+ maxWidth: 500,
1123
+ mx: "auto",
1124
+ mb: 4,
1125
+ lineHeight: 1.8,
1126
+ }}
1127
+ >
1128
+ Connect with other Reachy Mini owners on Discord. Share your
1129
+ projects, get help, and stay updated on the latest developments.
1130
  </Typography>
1131
  <Button
1132
  variant="contained"
 
1147
  function FinalCTA() {
1148
  return (
1149
  <Section background="alt" sx={{ py: { xs: 8, md: 12 } }}>
1150
+ <Box sx={{ textAlign: "center", maxWidth: 600, mx: "auto" }}>
1151
  <Typography variant="h2" sx={{ mb: 3 }}>
1152
  Ready to meet Reachy?
1153
  </Typography>
1154
+ <Typography
1155
+ variant="body1"
1156
+ color="text.secondary"
1157
+ sx={{ mb: 5, lineHeight: 1.8 }}
1158
+ >
1159
+ Get your own expressive companion robot and join the community of
1160
+ makers building the future of human-robot interaction.
1161
  </Typography>
1162
 
1163
+ <Stack
1164
+ direction={{ xs: "column", sm: "row" }}
1165
+ spacing={2}
1166
+ justifyContent="center"
1167
+ >
1168
  <Button
1169
  variant="contained"
1170
  size="large"
 
1174
  >
1175
  Buy Reachy Mini
1176
  </Button>
 
1177
  </Stack>
1178
 
1179
  {/* <Stack direction={{ xs: 'column', sm: 'row' }} spacing={{ xs: 1, sm: 4 }} justifyContent="center" sx={{ mt: 5, color: 'text.secondary' }}>