- Renamed NodePage component and directory to NodesPage/nodes for consistency - Updated all navigation links from "Node" to "Nodes" across headers and footer - Replaced anchor tags with React Router Link components for proper SPA navigation - Reorganized NetworkPage component order and added NetworkPros section - Converted NetworkUsecases from horizontal slider to responsive grid layout - Added new use cases for adaptive mesh and compute fabric - Update
232 lines
8.7 KiB
TypeScript
232 lines
8.7 KiB
TypeScript
import { useId } from 'react'
|
|
import { Container } from '@/components/Container'
|
|
import { CP } from '@/components/Texts'
|
|
|
|
const features = [
|
|
{
|
|
name: 'Sovereign DNS',
|
|
description:
|
|
'Human-readable names secured by your keypair, not a registrar. Unblockable discovery, private namespaces, and instant resolution across PODs.',
|
|
icon: DeviceListIcon,
|
|
},
|
|
{
|
|
name: 'Integrated VPN (Desktop)',
|
|
description:
|
|
'Connect securely from anywhere. No setup and no servers needed. Peer-to-peer routing delivers local speed and global reach.',
|
|
icon: DeviceLockIcon,
|
|
},
|
|
{
|
|
name: 'Unstoppable Publishing',
|
|
description:
|
|
'Host sites or services directly from your POD. Signed content, geo-aware delivery, and built-in resistance to takedowns.',
|
|
icon: DeviceChartIcon,
|
|
},
|
|
{
|
|
name: 'AI-Driven Search',
|
|
description:
|
|
'Private, semantic search across your own data and sites. Indexes locally, shares results securely, and retrieves instantly on-edge.',
|
|
icon: DeviceArrowIcon,
|
|
},
|
|
{
|
|
name: 'Private Chat',
|
|
description:
|
|
'Peer-to-peer messaging with zero metadata and zero servers. Works offline through nearby peers and is encrypted end-to-end.',
|
|
icon: DeviceCardsIcon,
|
|
},
|
|
{
|
|
name: 'On-Network AI',
|
|
description:
|
|
'Run LLMs and AI tools directly inside the network. Keep data local, distribute workloads, and build your own autonomous agents.',
|
|
icon: DeviceClockIcon,
|
|
},
|
|
]
|
|
|
|
function DeviceArrowIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
return (
|
|
<svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
|
|
<path
|
|
fillRule="evenodd"
|
|
clipRule="evenodd"
|
|
d="M9 0a4 4 0 00-4 4v24a4 4 0 004 4h14a4 4 0 004-4V4a4 4 0 00-4-4H9zm0 2a2 2 0 00-2 2v24a2 2 0 002 2h14a2 2 0 002-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9z"
|
|
fill="#737373"
|
|
/>
|
|
<path
|
|
d="M12 25l8-8m0 0h-6m6 0v6"
|
|
stroke="#171717"
|
|
strokeWidth={2}
|
|
strokeLinecap="round"
|
|
/>
|
|
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
function DeviceCardsIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
let id = useId()
|
|
|
|
return (
|
|
<svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
|
|
<path
|
|
fillRule="evenodd"
|
|
clipRule="evenodd"
|
|
d="M9 0a4 4 0 00-4 4v24a4 4 0 004 4h14a4 4 0 004-4V4a4 4 0 00-4-4H9zm0 2a2 2 0 00-2 2v24a2 2 0 002 2h14a2 2 0 002-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9z"
|
|
fill="#737373"
|
|
/>
|
|
<path
|
|
fillRule="evenodd"
|
|
clipRule="evenodd"
|
|
d="M9 13a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H10a1 1 0 01-1-1v-2zm0 6a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H10a1 1 0 01-1-1v-2zm1 5a1 1 0 00-1 1v2a1 1 0 001 1h12a1 1 0 001-1v-2a1 1 0 00-1-1H10z"
|
|
fill={`url(#${id}-gradient)`}
|
|
/>
|
|
<rect x={9} y={6} width={14} height={4} rx={1} fill="#171717" />
|
|
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
<defs>
|
|
<linearGradient
|
|
id={`${id}-gradient`}
|
|
x1={16}
|
|
y1={12}
|
|
x2={16}
|
|
y2={28}
|
|
gradientUnits="userSpaceOnUse"
|
|
>
|
|
<stop stopColor="#737373" />
|
|
<stop offset={1} stopColor="#737373" stopOpacity={0} />
|
|
</linearGradient>
|
|
</defs>
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
function DeviceClockIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
return (
|
|
<svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
|
|
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
<path
|
|
fillRule="evenodd"
|
|
clipRule="evenodd"
|
|
d="M5 4a4 4 0 014-4h14a4 4 0 014 4v10h-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9a2 2 0 00-2 2v24a2 2 0 002 2h5v2H9a4 4 0 01-4-4V4z"
|
|
fill="#737373"
|
|
/>
|
|
<path
|
|
fillRule="evenodd"
|
|
clipRule="evenodd"
|
|
d="M24 32a8 8 0 100-16 8 8 0 000 16zm1-8.414V19h-2v5.414l4 4L28.414 27 25 23.586z"
|
|
fill="#171717"
|
|
/>
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
function DeviceListIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
return (
|
|
<svg viewBox="0 0 32 32" fill="none" aria-hidden="true" {...props}>
|
|
<path
|
|
fillRule="evenodd"
|
|
clipRule="evenodd"
|
|
d="M9 0a4 4 0 00-4 4v24a4 4 0 004 4h14a4 4 0 004-4V4a4 4 0 00-4-4H9zm0 2a2 2 0 00-2 2v24a2 2 0 002 2h14a2 2 0 002-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9z"
|
|
fill="#737373"
|
|
/>
|
|
<circle cx={11} cy={14} r={2} fill="#171717" />
|
|
<circle cx={11} cy={20} r={2} fill="#171717" />
|
|
<circle cx={11} cy={26} r={2} fill="#171717" />
|
|
<path
|
|
d="M16 14h6M16 20h6M16 26h6"
|
|
stroke="#737373"
|
|
strokeWidth={2}
|
|
strokeLinecap="square"
|
|
/>
|
|
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
function DeviceLockIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
return (
|
|
<svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
|
|
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
<path
|
|
fillRule="evenodd"
|
|
clipRule="evenodd"
|
|
d="M5 4a4 4 0 014-4h14a4 4 0 014 4v10h-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9a2 2 0 00-2 2v24a2 2 0 002 2h5v2H9a4 4 0 01-4-4V4z"
|
|
fill="#737373"
|
|
/>
|
|
<path
|
|
fillRule="evenodd"
|
|
clipRule="evenodd"
|
|
d="M18 19.5a3.5 3.5 0 117 0V22a2 2 0 012 2v6a2 2 0 01-2 2h-7a2 2 0 01-2-2v-6a2 2 0 012-2v-2.5zm2 2.5h3v-2.5a1.5 1.5 0 00-3 0V22z"
|
|
fill="#171717"
|
|
/>
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
function DeviceChartIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
return (
|
|
<svg viewBox="0 0 32 32" fill="none" aria-hidden="true" {...props}>
|
|
<path
|
|
fillRule="evenodd"
|
|
clipRule="evenodd"
|
|
d="M9 0a4 4 0 00-4 4v24a4 4 0 004 4h14a4 4 0 004-4V4a4 4 0 00-4-4H9zm0 2a2 2 0 00-2 2v24a2 2 0 002 2h14a2 2 0 002-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9z"
|
|
fill="#737373"
|
|
/>
|
|
<path
|
|
fillRule="evenodd"
|
|
clipRule="evenodd"
|
|
d="M23 13.838V26a2 2 0 01-2 2H11a2 2 0 01-2-2V15.65l2.57 3.212a1 1 0 001.38.175L15.4 17.2a1 1 0 011.494.353l1.841 3.681c.399.797 1.562.714 1.843-.13L23 13.837z"
|
|
fill="#171717"
|
|
/>
|
|
<path
|
|
d="M10 12h12"
|
|
stroke="#737373"
|
|
strokeWidth={2}
|
|
strokeLinecap="square"
|
|
/>
|
|
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
export function SecondaryFeatures() {
|
|
return (
|
|
<section className="w-full max-w-8xl mx-auto bg-transparent">
|
|
|
|
{/* ✅ Top horizontal line with 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">
|
|
<div className="mx-auto max-w-4xl sm:text-center">
|
|
<h2 className="text-base/7 font-semibold text-cyan-500">FEATURES</h2>
|
|
<p className="text-3xl lg:text-4xl font-medium tracking-tight text-gray-900">
|
|
Core Features
|
|
</p>
|
|
<p className="mt-6 text-lg text-gray-600">
|
|
The Mycelium Network is evolving with new features to support richer data movement, identity, and application connectivity across the mesh.
|
|
</p>
|
|
</div>
|
|
<ul
|
|
role="list"
|
|
className="mx-auto mt-12 grid max-w-2xl grid-cols-1 gap-6 text-sm sm:grid-cols-2 md:gap-y-10 lg:max-w-none lg:grid-cols-3"
|
|
>
|
|
{features.map((feature) => (
|
|
<li
|
|
key={feature.name}
|
|
className="rounded-2xl border border-gray-100 p-8 transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20"
|
|
>
|
|
<feature.icon className="h-8 w-8" />
|
|
<CP className="mt-6 font-semibold text-gray-900">
|
|
{feature.name}
|
|
</CP>
|
|
<p className="mt-2 text-gray-700">{feature.description}</p>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</Container>
|
|
{/* ✅ Bottom horizontal line with 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>
|
|
)
|
|
}
|