refactor: replace Benefits component with Features and remove featured section from Hero
This commit is contained in:
@@ -7,6 +7,7 @@ import { UseCases } from '@/components/UseCases'
|
||||
import { SecondaryFeatures } from '@/components/SecondaryFeatures'
|
||||
import { Benefits } from '@/components/Benefits'
|
||||
import { About } from '@/components/About'
|
||||
import { Features } from '@/components/Features'
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
@@ -18,7 +19,7 @@ export default function Home() {
|
||||
<About />
|
||||
</AnimatedSection>
|
||||
<AnimatedSection>
|
||||
<Benefits />
|
||||
<Features />
|
||||
</AnimatedSection>
|
||||
<AnimatedSection>
|
||||
<PrimaryFeatures />
|
||||
|
126
src/components/Features.tsx
Normal file
126
src/components/Features.tsx
Normal file
@@ -0,0 +1,126 @@
|
||||
import Pathfinding from '@/components/Pathfinding'
|
||||
|
||||
export function Features() {
|
||||
return (
|
||||
<section id="features" className="bg-white py-24 sm:py-32">
|
||||
<div className="mx-auto max-w-2xl px-6 lg:max-w-7xl lg:px-8">
|
||||
<p className="mt-2 max-w-lg text-4xl font-semibold tracking-tight text-pretty text-gray-950 sm:text-5xl">
|
||||
Network Capabilities
|
||||
</p>
|
||||
<p className="mt-2 max-w-lg text-lg text-gray-600">
|
||||
If you have anything else you want to ask,{' '}
|
||||
<a
|
||||
href="mailto:info@example.com"
|
||||
className="text-gray-900 underline"
|
||||
>
|
||||
reach out to us
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<div className="mt-10 grid grid-cols-1 gap-4 sm:mt-16 lg:grid-cols-6 lg:grid-rows-2">
|
||||
<div className="relative lg:col-span-3">
|
||||
<div className="absolute inset-0 rounded-lg bg-white max-lg:rounded-t-4xl lg:rounded-tl-4xl" />
|
||||
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] max-lg:rounded-t-[calc(2rem+1px)] lg:rounded-tl-[calc(2rem+1px)]">
|
||||
<Pathfinding />
|
||||
<div className="p-10 pt-4">
|
||||
<h3 className="text-sm/4 font-semibold text-cyan-500">Routing</h3>
|
||||
<p className="mt-2 text-lg font-medium tracking-tight text-gray-950">
|
||||
Automatic pathfinding
|
||||
</p>
|
||||
<p className="mt-2 max-w-lg text-sm/6 text-gray-600">
|
||||
The Mycelium Network automatically discovers the shortest and fastest routes between nodes,
|
||||
ensuring optimal data flow and network efficiency without manual configuration.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 max-lg:rounded-t-4xl lg:rounded-tl-4xl" />
|
||||
</div>
|
||||
<div className="relative lg:col-span-3">
|
||||
<div className="absolute inset-0 rounded-lg bg-white lg:rounded-tr-4xl" />
|
||||
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] lg:rounded-tr-[calc(2rem+1px)]">
|
||||
<img
|
||||
alt=""
|
||||
src="https://tailwindcss.com/plus-assets/img/component-images/bento-01-releases.png"
|
||||
className="h-80 object-cover object-left lg:object-right"
|
||||
/>
|
||||
<div className="p-10 pt-4">
|
||||
<h3 className="text-sm/4 font-semibold text-cyan-500">Communication</h3>
|
||||
<p className="mt-2 text-lg font-medium tracking-tight text-gray-950">
|
||||
Distributed message bus
|
||||
</p>
|
||||
<p className="mt-2 max-w-lg text-sm/6 text-gray-600">
|
||||
Acts as a global message layer that lets nodes exchange information seamlessly.
|
||||
Enables resilient, asynchronous communication across the entire decentralized mesh.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 lg:rounded-tr-4xl" />
|
||||
</div>
|
||||
<div className="relative lg:col-span-2">
|
||||
<div className="absolute inset-0 rounded-lg bg-white lg:rounded-bl-4xl" />
|
||||
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] lg:rounded-bl-[calc(2rem+1px)]">
|
||||
<img
|
||||
alt=""
|
||||
src="https://tailwindcss.com/plus-assets/img/component-images/bento-01-speed.png"
|
||||
className="h-80 object-cover object-left"
|
||||
/>
|
||||
<div className="p-10 pt-4">
|
||||
<h3 className="text-sm/4 font-semibold text-cyan-500">Discovery</h3>
|
||||
<p className="mt-2 text-lg font-medium tracking-tight text-gray-950">
|
||||
Automatic proxy detection
|
||||
</p>
|
||||
<p className="mt-2 max-w-lg text-sm/6 text-gray-600">
|
||||
The system continuously scans for open SOCKS5 proxies within the network,
|
||||
making it effortless to find available connection points without manual setup.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 lg:rounded-bl-4xl" />
|
||||
</div>
|
||||
<div className="relative lg:col-span-2">
|
||||
<div className="absolute inset-0 rounded-lg bg-white" />
|
||||
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)]">
|
||||
<img
|
||||
alt=""
|
||||
src="https://tailwindcss.com/plus-assets/img/component-images/bento-01-integrations.png"
|
||||
className="h-80 object-cover"
|
||||
/>
|
||||
<div className="p-10 pt-4">
|
||||
<h3 className="text-sm/4 font-semibold text-cyan-500">Connectivity</h3>
|
||||
<p className="mt-2 text-lg font-medium tracking-tight text-gray-950">
|
||||
Seamless proxy forwarding
|
||||
</p>
|
||||
<p className="mt-2 max-w-lg text-sm/6 text-gray-600">
|
||||
Local SOCKS5 connections can be forwarded through nearby nodes or remote proxies.
|
||||
When browsers use the local proxy, traffic moves securely through the mesh—like a built-in VPN.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5" />
|
||||
</div>
|
||||
<div className="relative lg:col-span-2">
|
||||
<div className="absolute inset-0 rounded-lg bg-white max-lg:rounded-b-4xl lg:rounded-br-4xl" />
|
||||
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] max-lg:rounded-b-[calc(2rem+1px)] lg:rounded-br-[calc(2rem+1px)]">
|
||||
<img
|
||||
alt=""
|
||||
src="https://tailwindcss.com/plus-assets/img/component-images/bento-01-network.png"
|
||||
className="h-80 object-cover"
|
||||
/>
|
||||
<div className="p-10 pt-4">
|
||||
<h3 className="text-sm/4 font-semibold text-cyan-500">Delivery</h3>
|
||||
<p className="mt-2 text-lg font-medium tracking-tight text-gray-950">
|
||||
Decentralized content distribution
|
||||
</p>
|
||||
<p className="mt-2 max-w-lg text-sm/6 text-gray-600">
|
||||
Mycelium can serve data from distributed 0-DBs, creating a CDN-like layer that delivers
|
||||
content faster and more reliably—without relying on centralized servers.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 max-lg:rounded-b-4xl lg:rounded-br-4xl" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
@@ -138,7 +138,7 @@ export function Hero() {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative -mt-4 lg:col-span-7 lg:mt-0 xl:col-span-6">
|
||||
{/* <div className="relative -mt-4 lg:col-span-7 lg:mt-0 xl:col-span-6">
|
||||
<p className="text-center text-sm font-semibold text-gray-900 lg:text-left">
|
||||
As featured in
|
||||
</p>
|
||||
@@ -161,7 +161,7 @@ export function Hero() {
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</Container>
|
||||
</div>
|
||||
|
233
src/components/Pathfinding.tsx
Normal file
233
src/components/Pathfinding.tsx
Normal file
@@ -0,0 +1,233 @@
|
||||
// pathfinding.tsx
|
||||
// Animated SVG illustrating "Automatic pathfinding"
|
||||
// - Central hub + surrounding nodes
|
||||
// - Arrows fade/slide in
|
||||
// - Shortest path highlights on loop
|
||||
// - Respects prefers-reduced-motion
|
||||
'use client';
|
||||
|
||||
import * as React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
import clsx from 'clsx';
|
||||
|
||||
|
||||
type Props = {
|
||||
className?: string; // e.g. "w-full h-64"
|
||||
accent?: string; // main accent color
|
||||
stroke?: string; // neutral stroke color
|
||||
bg?: string; // background color
|
||||
};
|
||||
|
||||
const Node = ({
|
||||
cx,
|
||||
cy,
|
||||
r = 16,
|
||||
fill = "#00b8db",
|
||||
ring = "#E5E7EB",
|
||||
pulse = false,
|
||||
rMotion = 2,
|
||||
}: {
|
||||
cx: number;
|
||||
cy: number;
|
||||
r?: number;
|
||||
fill?: string;
|
||||
ring?: string;
|
||||
pulse?: boolean;
|
||||
rMotion?: number;
|
||||
}) => {
|
||||
const prefersReduced = useReducedMotion();
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* outer ring */}
|
||||
<motion.circle
|
||||
cx={cx}
|
||||
cy={cy}
|
||||
r={r + 14}
|
||||
fill="none"
|
||||
stroke={ring}
|
||||
strokeWidth={2}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.6 }}
|
||||
/>
|
||||
{/* core node */}
|
||||
<motion.circle
|
||||
cx={cx}
|
||||
cy={cy}
|
||||
r={r}
|
||||
fill={fill}
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
scale: pulse && !prefersReduced ? [1, 1 + rMotion / 16, 1] : 1,
|
||||
}}
|
||||
transition={{
|
||||
duration: pulse && !prefersReduced ? 1.8 : 0.6,
|
||||
repeat: pulse && !prefersReduced ? Infinity : 0,
|
||||
repeatType: "loop",
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const Arrow = ({
|
||||
d,
|
||||
color = "#111827",
|
||||
delay = 0,
|
||||
}: {
|
||||
d: string;
|
||||
color?: string;
|
||||
delay?: number;
|
||||
}) => (
|
||||
<motion.path
|
||||
d={d}
|
||||
fill="none"
|
||||
stroke={color}
|
||||
strokeWidth={3}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
initial={{ pathLength: 0, opacity: 0 }}
|
||||
animate={{ pathLength: 1, opacity: 1 }}
|
||||
transition={{
|
||||
delay,
|
||||
duration: 0.8,
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const DashedPath = ({
|
||||
d,
|
||||
color = "#9CA3AF",
|
||||
dash = 6,
|
||||
delay = 0,
|
||||
loop = false,
|
||||
}: {
|
||||
d: string;
|
||||
color?: string;
|
||||
dash?: number;
|
||||
delay?: number;
|
||||
loop?: boolean;
|
||||
}) => {
|
||||
const prefersReduced = useReducedMotion();
|
||||
|
||||
return (
|
||||
<motion.path
|
||||
d={d}
|
||||
fill="none"
|
||||
stroke={color}
|
||||
strokeWidth={3}
|
||||
strokeDasharray={dash}
|
||||
strokeLinecap="round"
|
||||
initial={{ pathLength: 0, opacity: 0.4 }}
|
||||
animate={{
|
||||
pathLength: 1,
|
||||
opacity: 1,
|
||||
}}
|
||||
transition={{
|
||||
delay,
|
||||
duration: 0.9,
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
repeat: !prefersReduced && loop ? Infinity : 0,
|
||||
repeatDelay: 1.2,
|
||||
repeatType: "reverse",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default function Pathfinding({
|
||||
className,
|
||||
accent = "#00b8db", // indigo-800 vibe
|
||||
stroke = "#111827", // gray-900
|
||||
bg = "#FFFFFF",
|
||||
}: Props) {
|
||||
// Canvas
|
||||
const W = 760;
|
||||
const H = 420;
|
||||
|
||||
// Layout (simple radial)
|
||||
const center = { x: 380, y: 210 };
|
||||
const nodes = [
|
||||
{ x: 130, y: 210 }, // left
|
||||
{ x: 670, y: 210 }, // right
|
||||
{ x: 380, y: 70 }, // top
|
||||
{ x: 280, y: 340 }, // bottom-left
|
||||
{ x: 500, y: 340 }, // bottom-right
|
||||
];
|
||||
|
||||
// Helper to make arrow path with a small head
|
||||
const arrowTo = (from: { x: number; y: number }, to: { x: number; y: number }) => {
|
||||
const dx = to.x - from.x;
|
||||
const dy = to.y - from.y;
|
||||
const len = Math.hypot(dx, dy);
|
||||
const ux = dx / len;
|
||||
const uy = dy / len;
|
||||
const end = { x: to.x - ux * 18, y: to.y - uy * 18 }; // inset a bit
|
||||
const headL = {
|
||||
x: end.x - uy * 8 - ux * 6,
|
||||
y: end.y + ux * 8 - uy * 6,
|
||||
};
|
||||
const headR = {
|
||||
x: end.x + uy * 8 - ux * 6,
|
||||
y: end.y - ux * 8 - uy * 6,
|
||||
};
|
||||
return `M ${from.x} ${from.y} L ${end.x} ${end.y} M ${headL.x} ${headL.y} L ${end.x} ${end.y} L ${headR.x} ${headR.y}`;
|
||||
};
|
||||
|
||||
// "Shortest" highlighted route: left -> center -> bottom-right
|
||||
const highlightA = `M ${nodes[0].x} ${nodes[0].y} L ${center.x} ${center.y}`;
|
||||
const highlightB = `M ${center.x} ${center.y} L ${nodes[4].x} ${nodes[4].y}`;
|
||||
|
||||
// Faint alternative routes
|
||||
const alt1 = `M ${nodes[2].x} ${nodes[2].y} L ${center.x} ${center.y}`;
|
||||
const alt2 = `M ${nodes[3].x} ${nodes[3].y} L ${center.x} ${center.y}`;
|
||||
const alt3 = `M ${center.x} ${center.y} L ${nodes[1].x} ${nodes[1].y}`;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"relative overflow-hidden",
|
||||
className
|
||||
)}
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
aria-label="Automatic pathfinding between nodes"
|
||||
style={{ background: bg }}
|
||||
>
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full">
|
||||
{/* background subtle grid */}
|
||||
<defs>
|
||||
<pattern id="grid" width="24" height="24" patternUnits="userSpaceOnUse">
|
||||
<path d="M 24 0 L 0 0 0 24" fill="none" stroke="#F3F4F6" strokeWidth="1" />
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width={W} height={H} fill="url(#grid)" />
|
||||
|
||||
{/* faint alternative connections */}
|
||||
<DashedPath d={alt1} color="#E5E7EB" dash={5} delay={0.1} />
|
||||
<DashedPath d={alt2} color="#E5E7EB" dash={5} delay={0.2} />
|
||||
<DashedPath d={alt3} color="#E5E7EB" dash={5} delay={0.3} />
|
||||
|
||||
{/* highlighted “shortest path” (animates / pulses) */}
|
||||
<DashedPath d={highlightA} color={accent} dash={8} delay={0.2} loop />
|
||||
<DashedPath d={highlightB} color={accent} dash={8} delay={0.4} loop />
|
||||
|
||||
{/* directional arrows toward the center (auto routing) */}
|
||||
<Arrow d={arrowTo(nodes[0], center)} color={stroke} delay={0.1} />
|
||||
<Arrow d={arrowTo(nodes[2], center)} color={stroke} delay={0.2} />
|
||||
<Arrow d={arrowTo(nodes[3], center)} color={stroke} delay={0.25} />
|
||||
<Arrow d={arrowTo(nodes[1], center)} color={stroke} delay={0.3} />
|
||||
|
||||
{/* nodes */}
|
||||
<Node cx={center.x} cy={center.y} r={18} fill={accent} ring="#E5E7EB" pulse />
|
||||
{nodes.map((n, i) => (
|
||||
<Node key={i} cx={n.x} cy={n.y} r={14} fill="#FFFFFF" ring="#E5E7EB" />
|
||||
))}
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user