feat: redesign pods page with enhanced UI and animations

- Replaced HomeBlink with HomeAurora component for improved visual experience
- Added PodCapabilities horizontal slider with interactive navigation controls
- Created PodsFeatures section showcasing use cases with hover animations
- Updated PodsHow layout with bullet points and new PodsFlow animation component
This commit is contained in:
2025-11-13 14:04:13 +01:00
parent 5c2fcecbd9
commit aa6f475050
7 changed files with 513 additions and 20 deletions

BIN
public/images/podsimg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@@ -5,7 +5,7 @@ import { CallToAction } from './CallToAction'
import { HomeTab } from './HomeTab' import { HomeTab } from './HomeTab'
import { HomeMap } from './HomeMap' import { HomeMap } from './HomeMap'
import { HomeAudience } from './HomeAudience' import { HomeAudience } from './HomeAudience'
import { HomeBlink } from './HomeBlink' import { HomeAurora } from './HomeAurora'
import { HomeArchitecture } from './HomeArchitecture'; import { HomeArchitecture } from './HomeArchitecture';
@@ -19,7 +19,7 @@ export default function HomePage() {
return ( return (
<div> <div>
<AnimatedSection> <AnimatedSection>
<HomeBlink onGetStartedClick={handleScrollToSlider} /> <HomeAurora onGetStartedClick={handleScrollToSlider} />
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection>

View File

@@ -0,0 +1,151 @@
"use client";
import { useRef } from "react";
import { Eyebrow, CP, CT, H4 } from "@/components/Texts";
import { IoArrowBackOutline, IoArrowForwardOutline } from "react-icons/io5";
import {
HomeModernIcon,
CpuChipIcon,
ServerStackIcon,
ShieldCheckIcon,
} from "@heroicons/react/24/solid";
const capabilities = [
{
isIntro: true,
eyebrow: "CAPABILITIES",
title: "What is a Pod?",
description: "",
},
{
title: "Your private digital home on the decentralized internet",
description:
"Your Pod is a private digital home where apps, data, and identity live independently of Big Tech and central servers.",
icon: (
<div className="flex items-start justify-start">
<HomeModernIcon className="h-12 w-12 text-cyan-400" />
</div>
),
},
{
title: "An always-on space you fully control",
description:
"A dedicated, always-on environment you fully command — your own sovereign slice of the network that never goes offline.",
icon: (
<div className="flex items-start justify-start">
<CpuChipIcon className="h-12 w-12 text-cyan-400" />
</div>
),
},
{
title: "Runs communication, storage, and collaboration tools",
description:
"Runs your communication, storage, and collaboration tools in a secure local environment without reliance on outside platforms.",
icon: (
<div className="flex items-start justify-start">
<ServerStackIcon className="h-12 w-12 text-cyan-400" />
</div>
),
},
{
title: "Fully encrypted, federated peer-to-peer network",
description:
"Encrypted, federated peer-to-peer networking that links your Pod directly with trusted devices without intermediaries.",
icon: (
<div className="flex items-start justify-start">
<ShieldCheckIcon className="h-12 w-12 text-cyan-400" />
</div>
),
},
];
export function PodCapabilities() {
const sliderRef = useRef<HTMLUListElement>(null);
const scrollLeft = () =>
sliderRef.current?.scrollBy({ left: -400, behavior: "smooth" });
const scrollRight = () =>
sliderRef.current?.scrollBy({ left: 400, behavior: "smooth" });
return (
<section className="bg-[#121212] w-full max-w-8xl mx-auto">
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-800" />
<div className="w-full border-t border-l border-r border-gray-800" />
<div className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-800 bg-[#111111] overflow-hidden">
{/* Horizontal Slider */}
<ul
ref={sliderRef}
className="flex overflow-x-auto snap-x snap-mandatory scroll-smooth no-scrollbar"
>
{capabilities.map((item, idx) => (
<li
key={idx}
className={`snap-start shrink-0 w-[85%] sm:w-[50%] lg:w-[33%] border border-gray-800 p-10 relative ${
item.isIntro ? "" : "bg-[#111]/60"
}`}
>
{/* INTRO CARD */}
{item.isIntro ? (
<div className="flex flex-col justify-between h-full">
<div>
<Eyebrow>{item.eyebrow}</Eyebrow>
<H4 className="text-white mt-0 max-w-lg">{item.title}</H4>
<p className="text-gray-400 lg:text-lg text-sm leading-relaxed">
{item.description}
</p>
</div>
{/* Arrow controls */}
<div className="flex items-center gap-x-4 mt-2">
<button
onClick={scrollLeft}
className="h-8 w-8 flex items-center justify-center border border-gray-800 rounded-md hover:border-cyan-500 transition-colors"
>
<IoArrowBackOutline className="text-gray-300" size={16} />
</button>
<button
onClick={scrollRight}
className="h-8 w-8 flex items-center justify-center border border-gray-800 rounded-md hover:border-cyan-500 transition-colors"
>
<IoArrowForwardOutline
className="text-gray-300"
size={16}
/>
</button>
</div>
</div>
) : (
<>
{/* LEFT-ALIGNED ICON */}
{item.icon}
<br />
{/* LEFT-ALIGNED TEXT */}
<CT className="font-semibold leading-tight text-white text-left">
{item.title}
</CT>
<CP className="mt-2 text-gray-400 text-left">
{item.description}
</CP>
</>
)}
</li>
))}
</ul>
</div>
<div className="w-full border-b border-gray-800" />
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-800" />
</section>
);
}

View File

@@ -0,0 +1,142 @@
"use client";
import { Container } from "@/components/Container";
import { CP, Small } from "@/components/Texts";
const useCases = [
{
title: "Private Messaging & Calling",
description:
"Communicate directly Pod-to-Pod with no centralized routing.",
bullets: [
"End-to-end encrypted messaging and voice calling.",
"No intermediaries — connections flow directly between Pods.",
"Zero metadata profiling, tracking, or data resale.",
],
},
{
title: "Safe File Storage & Sharing",
description:
"Store and share files securely without exposing data to third parties.",
bullets: [
"Files remain private with no platform-level scanning or analysis.",
"Share documents and media directly with trusted contacts.",
"Full ownership of your content — no cloud vendor dependencies.",
],
},
{
title: "Personal Calendar & Meetings",
description:
"Manage your schedule within your own sovereign digital space.",
bullets: [
"Keep events, appointments, and reminders fully private.",
"Coordinate calls and meetings entirely inside your Pod.",
"No syncing with external servers or corporate platforms.",
],
},
{
title: "Private Communities & Teams",
description:
"Create groups or collaborative spaces without platform ownership.",
bullets: [
"Form teams, friendship circles, and micro-communities.",
"All interactions occur directly Pod-to-Pod.",
"No hosting company or service provider controls your group data.",
],
},
{
title: "Quantum Safe File System (QSFS)",
description:
"Store data using a self-healing, encrypted, quantum-resistant system.",
bullets: [
"Files are encrypted, split, and distributed across trusted nodes.",
"Designed to withstand future quantum-level attacks.",
"Automatic repair and reconstruction of data fragments.",
],
},
{
title: "Access From Any Device",
description:
"Your Pod travels with you — always accessible, always yours.",
bullets: [
"Use your Pod from phones, laptops, tablets, or shared machines.",
"Your identity, apps, and files follow you securely.",
"No syncing or duplicated copies — direct access to your environment.",
],
},
];
export function PodsFeatures() {
return (
<section className="w-full max-w-8xl mx-auto bg-transparent">
{/* Top horizontal spacing */}
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-100"></div>
<div className="w-full border-t border-l border-r border-gray-100" />
<Container className="py-12 border border-t-0 border-b-0 border-gray-100">
{/* Header */}
<div className="mx-auto max-w-4xl sm:text-center">
<h2 className="text-base/7 font-semibold text-cyan-500">
WHAT YOU CAN DO
</h2>
<p className="text-3xl lg:text-4xl font-medium tracking-tight text-gray-900">
A Fully Personal, Sovereign Digital Environment
</p>
<p className="mt-6 text-lg text-gray-600">
A Pod gives you a secure digital home where communication, storage,
identity, and collaboration remain fully under your control.
</p>
</div>
{/* Cards */}
<ul
role="list"
className="mx-auto mt-12 grid max-w-2xl grid-cols-1 gap-6
sm:grid-cols-2 lg:max-w-none lg:grid-cols-3 md:gap-y-10"
>
{useCases.map((useCase) => (
<li
key={useCase.title}
className="rounded-md border border-gray-100 bg-white p-6 transition-all duration-300
hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20 flex flex-col"
>
{/* Title + label */}
<div className="flex items-center justify-between">
<h3 className="font-semibold text-gray-900">
{useCase.title}
</h3>
<Small className="uppercase tracking-[0.25em] text-cyan-500">
Feature
</Small>
</div>
{/* Short description */}
<p className="mt-4 text-gray-700 leading-snug">
{useCase.description}
</p>
{/* Bullet list */}
<ul className="mt-6 space-y-3 text-sm text-gray-600">
{useCase.bullets.map((bullet) => (
<li
key={bullet}
className="flex items-start gap-3 rounded-2xl border border-cyan-100 bg-cyan-50/60 p-3 leading-relaxed"
>
<span className="mt-1 inline-block size-2 rounded-full bg-cyan-500" />
<span>{bullet}</span>
</li>
))}
</ul>
</li>
))}
</ul>
</Container>
{/* Bottom spacing */}
<div className="w-full border-b border-gray-100" />
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-100"></div>
</section>
);
}

View File

@@ -1,7 +1,7 @@
"use client"; "use client";
import { Eyebrow, H3, P } from "@/components/Texts"; import { Eyebrow, H3, P } from "@/components/Texts";
import CloudPods from "./animations/CloudPods"; import PodsFlow from "./animations/PodsFlow";
export function PodsHow() { export function PodsHow() {
return ( return (
@@ -13,34 +13,40 @@ export function PodsHow() {
<div className="max-w-7xl mx-auto px-6 lg:px-8 py-12 border border-t-0 border-b-0 border-gray-800 bg-[#111111] overflow-hidden"> <div className="max-w-7xl mx-auto px-6 lg:px-8 py-12 border border-t-0 border-b-0 border-gray-800 bg-[#111111] overflow-hidden">
{/* ✅ Two-column layout */} {/* ✅ Two-column layout */}
<div className="flex flex-col lg:flex-row-reverse gap-16"> <div className="flex flex-col lg:flex-row-reverse gap-8">
{/* ✅ Right side animation */} {/* ✅ Right side animation */}
<div className="w-full lg:w-1/2"> <div className="w-full lg:w-4/9">
<CloudPods /> <PodsFlow />
</div> </div>
{/* ✅ Left side content */} {/* ✅ Left side content */}
<div className="w-full lg:w-1/2 text-white"> <div className="w-full lg:w-5/9 text-white">
<Eyebrow color="accent" className=""> <Eyebrow color="accent" className="">
How it works How it works
</Eyebrow> </Eyebrow>
<H3 color="white" className="mt-6"> <H3 color="white" className="mt-6">
What Living in a Pod Feels Like Living in a Pod
</H3> </H3>
<P className="max-w-3xl text-gray-400 mt-6"> <P className="max-w-4xl text-gray-400 mt-6">
When you use Mycelium, everything your messages, calls, files runs directly from your Pod. When you use Mycelium, everything your messages, calls, files runs directly from your Pod.
</P> </P>
<ul className="max-w-4xl text-gray-400 mt-6 space-y-3 ml-4">
<li className="flex items-start gap-3">
<span className="mt-1.5 inline-block size-2 rounded-full bg-cyan-400" />
<span>When you message someone, it goes Pod to Pod, not through a central server.</span>
</li>
<li className="flex items-start gap-3">
<span className="mt-1.5 inline-block size-2 rounded-full bg-cyan-400" />
<span>When you host a call, it runs on your Pod no third-party data centers.</span>
</li>
<li className="flex items-start gap-3">
<span className="mt-1.5 inline-block size-2 rounded-full bg-cyan-400" />
<span>When you save a file, it stays on your Pod, encrypted and always available.</span>
</li>
</ul>
<P className="max-w-3xl text-gray-400 mt-4"> <P className="max-w-3xl text-gray-400 mt-4">
Its your personal digital hub:
When you message someone, it goes Pod to Pod, not through a central server.
When you host a call, it runs on your Pod no third-party data centers.
</P>
<P className="max-w-3xl text-gray-400 mt-4">
When you save a file, it stays on your Pod, encrypted and always available.
No one else can read it, rent it, or switch it off. No one else can read it, rent it, or switch it off.
</P>
<P className="max-w-3xl text-gray-400 mt-4">
You dont log in to the internet you are part of it. You dont log in to the internet you are part of it.
</P> </P>
</div> </div>

View File

@@ -1,12 +1,14 @@
import Homepod from './Homepod'; import Homepod from './Homepod';
import { PodsCapabilities } from './PodsCapabilities'; import { PodCapabilities } from './PodCapabilities';
import { PodsHow } from './PodsHow'; import { PodsHow } from './PodsHow';
import { PodsFeatures } from './PodsFeatures';
const PodsPage = () => { const PodsPage = () => {
return ( return (
<> <>
<Homepod /> <Homepod />
<PodsCapabilities /> <PodCapabilities />
<PodsFeatures />
<PodsHow /> <PodsHow />
</> </>
); );

View File

@@ -0,0 +1,192 @@
"use client";
import { motion } from "framer-motion";
import clsx from "clsx";
type Props = {
className?: string;
accent?: string;
gridStroke?: string;
};
const W = 760;
const H = 420;
export default function PodsFlow({
className,
accent = "#00b8db",
gridStroke = "#2b2a2a",
}: Props) {
const pods = [
{ x: 100, y: 180, label: "Pod 1" },
{ x: 260, y: 180, label: "Pod 2" },
{ x: 420, y: 180, label: "Pod 3" },
{ x: 580, y: 180, label: "Pod 4" },
];
// Pulse path
const path = `
M ${pods[0].x + 80} ${pods[0].y + 40}
L ${pods[1].x - 10} ${pods[1].y + 40}
L ${pods[1].x + 80} ${pods[1].y + 40}
L ${pods[2].x - 10} ${pods[2].y + 40}
L ${pods[2].x + 80} ${pods[2].y + 40}
L ${pods[3].x - 10} ${pods[3].y + 40}
`;
// Arrow segments
const arrows = [
{
d: `M ${pods[0].x + 80} ${pods[0].y + 40} L ${pods[1].x - 6} ${pods[1].y + 40}`,
end: { x: pods[1].x - 6, y: pods[1].y + 40 },
},
{
d: `M ${pods[1].x + 80} ${pods[1].y + 40} L ${pods[2].x - 6} ${pods[2].y + 40}`,
end: { x: pods[2].x - 6, y: pods[2].y + 40 },
},
{
d: `M ${pods[2].x + 80} ${pods[2].y + 40} L ${pods[3].x - 6} ${pods[3].y + 40}`,
end: { x: pods[3].x - 6, y: pods[3].y + 40 },
},
];
return (
<div
className={clsx("relative overflow-hidden", className)}
aria-hidden="true"
role="img"
aria-label="Pod-to-Pod signal transfer animation"
style={{ background: "transparent" }}
>
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full">
{/* GRID BG */}
<defs>
<pattern id="pods-grid" width="28" height="28" patternUnits="userSpaceOnUse">
<path d="M 28 0 L 0 0 0 28" fill="none" stroke={gridStroke} strokeWidth="1" opacity="0.6" />
</pattern>
<filter id="pods-glow">
<feGaussianBlur stdDeviation="4" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<rect width={W} height={H} fill="url(#pods-grid)" />
{/* POD BOXES */}
{pods.map((p, i) => (
<motion.rect
key={i}
x={p.x}
y={p.y}
width={80}
height={80}
rx={14}
fill="#0d0d0d"
stroke="#1a1a1a"
strokeWidth={2}
initial={{ opacity: 0 }}
animate={{ opacity: 0.9 }}
transition={{ duration: 0.5 + i * 0.15 }}
/>
))}
{/* POD LABELS */}
{pods.map((p, i) => (
<motion.text
key={i}
x={p.x + 40}
y={p.y + 50}
textAnchor="middle"
fontSize="14"
fontFamily="Inter, sans-serif"
fill="#9ca3af"
initial={{ opacity: 0 }}
animate={{ opacity: 0.9 }}
transition={{ delay: 0.1 + i * 0.1, duration: 0.6 }}
>
{p.label}
</motion.text>
))}
{/* GREY LINES */}
{arrows.map((a, i) => (
<motion.path
key={`grey-${i}`}
d={a.d}
stroke="#333"
strokeWidth={4}
strokeLinecap="round"
fill="none"
initial={{ pathLength: 0, opacity: 0 }}
animate={{ pathLength: 1, opacity: 0.8 }}
transition={{ delay: 0.2 * i, duration: 0.7 }}
/>
))}
{/* CYAN LINES */}
{arrows.map((a, i) => (
<motion.path
key={`cyan-${i}`}
d={a.d}
stroke={accent}
strokeWidth={2}
strokeLinecap="round"
strokeDasharray="10"
fill="none"
initial={{ pathLength: 0, opacity: 0 }}
animate={{ pathLength: 1, opacity: 1 }}
transition={{ delay: 0.25 * i, duration: 0.7 }}
/>
))}
{/* NEW: CYAN ENDPOINT PULSES */}
{arrows.map((a, i) => (
<motion.circle
key={`endpoint-${i}`}
cx={a.end.x}
cy={a.end.y}
r={10}
fill={accent}
opacity={0.12}
filter="url(#pods-glow)"
initial={{ scale: 0.8, opacity: 0 }}
animate={{
scale: [1, 1.2, 1],
opacity: [0.05, 0.25, 0.05],
}}
transition={{
duration: 1.5,
delay: i * 0.2,
repeat: Infinity,
repeatType: "mirror",
}}
/>
))}
{/* MAIN MOVING CYAN PULSE */}
<motion.circle
r={8}
fill={accent}
filter="url(#pods-glow)"
style={{
offsetPath: `path('${path.replace(/\s+/g, " ")}')`,
}}
initial={{ offsetDistance: "0%", opacity: 0.4 }}
animate={{
offsetDistance: ["0%", "100%"],
opacity: [0.4, 1, 0.4],
}}
transition={{
duration: 2.6,
repeat: Infinity,
ease: "linear",
}}
/>
</svg>
</div>
);
}