diff --git a/public/images/cloudhero3.webp b/public/images/cloudhero3.webp new file mode 100644 index 0000000..f7828b0 Binary files /dev/null and b/public/images/cloudhero3.webp differ diff --git a/public/images/cloudui/billing.jpg b/public/images/cloudui/billing.jpg new file mode 100644 index 0000000..2fe27ad Binary files /dev/null and b/public/images/cloudui/billing.jpg differ diff --git a/public/images/cloudui/kubeconfig.jpg b/public/images/cloudui/kubeconfig.jpg new file mode 100644 index 0000000..97bce73 Binary files /dev/null and b/public/images/cloudui/kubeconfig.jpg differ diff --git a/public/images/cloudui/reserve.jpg b/public/images/cloudui/reserve.jpg new file mode 100644 index 0000000..024f1f7 Binary files /dev/null and b/public/images/cloudui/reserve.jpg differ diff --git a/src/components/Texts.tsx b/src/components/Texts.tsx index 695dd5a..f40954e 100644 --- a/src/components/Texts.tsx +++ b/src/components/Texts.tsx @@ -13,6 +13,7 @@ const colorVariants = { secondary: 'text-gray-600', light: 'text-gray-50', accent: 'text-cyan-500', + cyan: 'text-cyan-50', white: 'text-white', dark: 'text-gray-950', tertiary: 'text-gray-700', @@ -33,7 +34,8 @@ type PolymorphicProps = P & { const createTextComponent = ( defaultElement: DefaultElement, - defaultClassName: string + defaultClassName: string, + defaultProps: Omit = {} ) => { type Props = PolymorphicProps< E, @@ -41,9 +43,9 @@ const createTextComponent = ( > function Text({ - font = 'sans', + font = defaultProps.font || 'sans', as, - color = 'primary', + color = defaultProps.color || 'primary', className, children, ...props @@ -104,7 +106,8 @@ export const H5 = createTextComponent( ) export const Eyebrow = createTextComponent( 'h2', - 'text-base/7 font-semibold tracking-wider uppercase' + 'text-base/7 font-semibold tracking-[0.18em] uppercase', + { color: 'accent' } ) export const SectionHeader = createTextComponent( 'p', diff --git a/src/pages/cloud/CloudArchitecture.tsx b/src/pages/cloud/CloudArchitecture.tsx index b078e3f..79d6188 100644 --- a/src/pages/cloud/CloudArchitecture.tsx +++ b/src/pages/cloud/CloudArchitecture.tsx @@ -42,7 +42,7 @@ export function CloudArchitecture() {
- + Technical Architecture diff --git a/src/pages/cloud/CloudFeatures.tsx b/src/pages/cloud/CloudFeatures.tsx index 41dd970..e9662db 100644 --- a/src/pages/cloud/CloudFeatures.tsx +++ b/src/pages/cloud/CloudFeatures.tsx @@ -1,124 +1,432 @@ -import { Container } from '../../components/Container' -import { Eyebrow, SectionHeader, P, Small } from '../../components/Texts' +'use client' -const featureSections = [ +import { Fragment, useEffect, useId, useRef, useState } from 'react' +import { Tab, TabGroup, TabList, TabPanel, TabPanels } from '@headlessui/react' +import clsx from 'clsx' +import { + type MotionProps, + type Variant, + AnimatePresence, + motion, +} from 'framer-motion' +import { useDebouncedCallback } from 'use-debounce' + +import { AppScreen } from '../network/AppScreen' +import { + Eyebrow, + FeatureDescription, + FeatureTitle, + MobileFeatureTitle, + P, + SectionHeader, +} from '@/components/Texts' +import { CircleBackground } from '@/components/CircleBackground' +import { Container } from '@/components/Container' + +import connectorImg from '@/images/connector.png' +import peersImg from '@/images/peers.png' +import settingImg from '@/images/setting.png' +import { PhoneFrame } from '@/components/PhoneFrame' + + +interface CustomAnimationProps { + isForwards: boolean + changeCount: number +} + +const features = [ { - title: 'Mycelium Networking', + name: 'Mycelium Connector', description: - 'Ultra-fast, decentralized networking inspired by nature to keep services reachable without exposing surfaces.', - bullets: [ - 'End-to-end encrypted mesh connectivity between every node.', - 'Direct node communication without centralized intermediaries.', - 'Self-optimizing routes that heal around failures automatically.', - 'Secure peer-to-peer communication across the entire grid.', - ], + "Start (and stop) your Mycelium connector to gain access to sites, apps, and workloads available exclusively on the Mycelium Network. View statistics around peers and traffic.", + icon: DeviceUserIcon, + screen: InviteScreen, }, { - title: 'Zero-Image Technology', + name: 'Mycelium Peers', description: - 'Metadata-first zero-images shrink artifacts up to 100x, reducing deployment time and bandwidth.', - bullets: [ - 'Deterministic deployments verified cryptographically.', - 'Run containers, VMs, and Linux workloads with secure boot.', - 'Smart contract orchestration manages every workload lifecycle.', - 'Minimal artifact footprint accelerates delivery everywhere.', - ], + 'Search and discover active peers on the Mycelium Network, or add your own.', + icon: DeviceNotificationIcon, + screen: StocksScreen, }, { - title: 'Quantum-Safe Storage (QSS)', + name: 'Network Setting', description: - 'Quantum-resistant encryption secures data beyond the application layer for complete ownership.', - bullets: [ - 'Self-healing storage recovers instantly from corruption or failure.', - 'Serve the same data via IPFS, S3, WebDAV, HTTP, and native FS.', - 'Geo-aware placement enforces residency and redundancy policies.', - 'Autonomous replication keeps data resilient across the globe.', - ], - }, - { - title: 'Multi-Master Clusters', - description: - 'High-availability Kubernetes with automatic failover and leadership orchestration.', - bullets: [ - 'Multi-master topologies orchestrated with zero downtime.', - 'Automatic failover keeps control planes healthy and responsive.', - 'HA operations managed without manual intervention or scripts.', - 'Upgrades roll out seamlessly with continuous verification.', - ], - }, - { - title: 'Effortless Load Balancing & Scaling', - description: - 'Adaptive automation balances traffic and scales workloads based on demand.', - bullets: [ - 'Built-in autoscaling that responds to real-time usage.', - 'Native load balancing distributes traffic globally.', - 'High availability delivered without custom controllers.', - 'Elastic scaling keeps costs aligned with workload demand.', - ], - }, - { - title: 'Simple Web Gateway Access', - description: - 'Expose services to the public web with declarative Kubernetes resources.', - bullets: [ - 'One resource publishes services without complex ingress rules.', - 'Domain and prefix-based routing built into the platform.', - 'No need to manage dedicated ingress controllers.', - 'Consistent configuration across every cluster and region.', - ], + 'Find version and network information and trigger light or dark mode.', + icon: DeviceTouchIcon, + screen: InvestScreen, }, ] +function DeviceUserIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} + +function DeviceNotificationIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + return ( + + ) +} + +function DeviceTouchIcon(props: React.ComponentPropsWithoutRef<'svg'>) { + let id = useId() + + return ( + + ) +} + +const maxZIndex = 2147483647 + +const bodyVariantBackwards: Variant = { + opacity: 0.4, + scale: 0.8, + zIndex: 0, + filter: 'blur(4px)', + transition: { duration: 0.4 }, +} + + +const bodyAnimation: MotionProps = { + initial: 'initial', + animate: 'animate', + exit: 'exit', + variants: { + initial: (custom: CustomAnimationProps) => ( + custom.isForwards + ? { + y: '100%', + zIndex: maxZIndex - custom.changeCount, + transition: { duration: 0.4 }, + } + : bodyVariantBackwards + ), + animate: (custom: CustomAnimationProps) => ({ + y: '0%', + opacity: 1, + scale: 1, + zIndex: maxZIndex / 2 - custom.changeCount, + filter: 'blur(0px)', + transition: { duration: 0.4 }, + }), + exit: (custom: CustomAnimationProps) => ( + custom.isForwards + ? bodyVariantBackwards + : { + y: '100%', + zIndex: maxZIndex - custom.changeCount, + transition: { duration: 0.4 }, + } + ), + }, +} + + +function InviteScreen() { + return ( + + Mycelium Connector + + ) +} + +function StocksScreen() { + return ( + + Mycelium Peers + + ) +} + +function InvestScreen() { + return ( + + Mycelium Settings + + ) +} + +function usePrevious(value: T) { + const ref = useRef() + + useEffect(() => { + ref.current = value + }, [value]) + + return ref.current +} + +function FeaturesDesktop() { + let [changeCount, setChangeCount] = useState(0) + let [selectedIndex, setSelectedIndex] = useState(0) + let prevIndex = usePrevious(selectedIndex) + let isForwards = prevIndex === undefined ? true : selectedIndex > prevIndex + + let onChange = useDebouncedCallback( + (selectedIndex: number) => { + setSelectedIndex(selectedIndex) + setChangeCount((changeCount) => changeCount + 1) + }, + 100, + { leading: true }, + ) + + return ( + + + {features.map((feature, featureIndex) => ( +
+ {featureIndex === selectedIndex && ( + + )} +
+ + + + + {feature.name} + + + + {feature.description} + +
+
+ ))} +
+
+
+ +
+ + + + {features.map((feature, featureIndex) => + selectedIndex === featureIndex ? ( + + + + + + ) : null, + )} + + + +
+
+ ) +} + +function FeaturesMobile() { + let [activeIndex, setActiveIndex] = useState(0) + let slideContainerRef = useRef>(null) + let slideRefs = useRef>>([]) + + useEffect(() => { + let observer = new window.IntersectionObserver( + (entries) => { + for (let entry of entries) { + if (entry.isIntersecting && entry.target instanceof HTMLDivElement) { + setActiveIndex(slideRefs.current.indexOf(entry.target)) + break + } + } + }, + { + root: slideContainerRef.current, + threshold: 0.6, + }, + ) + + for (let slide of slideRefs.current) { + if (slide) { + observer.observe(slide) + } + } + + return () => { + observer.disconnect() + } + }, [slideContainerRef, slideRefs]) + + return ( + <> +
+ {features.map((feature, featureIndex) => ( +
ref && (slideRefs.current[featureIndex] = ref)} + className="w-full flex-none snap-center px-4 sm:px-6 transition-all duration-300 ease-in-out hover:scale-105" + > +
+
+ +
+ + + +
+ + + {feature.name} + + + {feature.description} + +
+
+
+ ))} +
+
+ {features.map((_, featureIndex) => ( + + ))} +
+ + ) +} + export function CloudFeatures() { return ( -
+
-
- - Core Features - - - Infrastructure that verifies, heals, and scales itself. +
+ How It Works + + How Mycelium Operates -

- From mesh networking to quantum-safe storage, every capability in - Mycelium Cloud is designed for sovereign control and autonomous - operations—so your teams focus on shipping workloads instead of - wiring infrastructure. +

+ Mycelium, like its natural namesake, thrives on decentralization, + efficiency, and security, making it a truly powerful force in the world + of decentralized networks.

-
- {featureSections.map((feature) => ( -
-
- - Capability - -

- {feature.title} -

-

- {feature.description} -

-
-
    - {feature.bullets.map((bullet) => ( -
  • - - {bullet} -
  • - ))} -
-
- ))} -
+ +
+ +
+ +
) diff --git a/src/pages/cloud/CloudHeroNew.tsx b/src/pages/cloud/CloudHeroNew.tsx new file mode 100644 index 0000000..0232de6 --- /dev/null +++ b/src/pages/cloud/CloudHeroNew.tsx @@ -0,0 +1,44 @@ +import { H3, H5, Eyebrow } from "../../components/Texts" +import { Button } from "../../components/Button" + + +export function CloudHeroNew() { + return ( +
+
+
+
+ + Mycelium Cloud + +

+ Deploy sovereign Kubernetes clusters on decentralized infrastructure. +

+
+ Mycelium Cloud turns the ThreeFold Grid into a programmable substrate for K3s. +
+
+ Launch verifiable clusters with nature-inspired networking, quantum-safe storage, and zero-image delivery that keeps every workload deterministic. +
+
+ + +
+
+
+
+
+ ) +} diff --git a/src/pages/cloud/CloudOverview.tsx b/src/pages/cloud/CloudOverview.tsx index c43ef79..523a2ee 100644 --- a/src/pages/cloud/CloudOverview.tsx +++ b/src/pages/cloud/CloudOverview.tsx @@ -39,7 +39,7 @@ export function CloudOverview() {
- + Platform Overview diff --git a/src/pages/cloud/CloudUseCases.tsx b/src/pages/cloud/CloudUseCases.tsx index f8bcd11..c1b2802 100644 --- a/src/pages/cloud/CloudUseCases.tsx +++ b/src/pages/cloud/CloudUseCases.tsx @@ -41,7 +41,7 @@ export function CloudUseCases() {
- + Use Cases diff --git a/src/pages/gpu/GpuArchitecture.tsx b/src/pages/gpu/GpuArchitecture.tsx index c7e5d8a..f66e325 100644 --- a/src/pages/gpu/GpuArchitecture.tsx +++ b/src/pages/gpu/GpuArchitecture.tsx @@ -31,7 +31,7 @@ export function GpuArchitecture() {
- + Technical Architecture diff --git a/src/pages/gpu/GpuUseCases.tsx b/src/pages/gpu/GpuUseCases.tsx index 0481bee..a6f1572 100644 --- a/src/pages/gpu/GpuUseCases.tsx +++ b/src/pages/gpu/GpuUseCases.tsx @@ -37,7 +37,7 @@ export function GpuUseCases() {
- + Use Cases diff --git a/src/pages/storage/StorageArchitecture.tsx b/src/pages/storage/StorageArchitecture.tsx index ff56890..fc65d43 100644 --- a/src/pages/storage/StorageArchitecture.tsx +++ b/src/pages/storage/StorageArchitecture.tsx @@ -53,7 +53,7 @@ export function StorageArchitecture() {
- + Technical Architecture diff --git a/src/pages/storage/StorageFeatures.tsx b/src/pages/storage/StorageFeatures.tsx index c86d204..e608705 100644 --- a/src/pages/storage/StorageFeatures.tsx +++ b/src/pages/storage/StorageFeatures.tsx @@ -64,7 +64,7 @@ export function StorageFeatures() {
- + Core Features diff --git a/src/pages/storage/StorageOverview.tsx b/src/pages/storage/StorageOverview.tsx index 25f805c..160538c 100644 --- a/src/pages/storage/StorageOverview.tsx +++ b/src/pages/storage/StorageOverview.tsx @@ -43,11 +43,11 @@ export function StorageOverview() { {highlights.map((item) => (
-
+
- + {item.label}

diff --git a/src/pages/storage/StorageUseCases.tsx b/src/pages/storage/StorageUseCases.tsx index 7799334..3db294a 100644 --- a/src/pages/storage/StorageUseCases.tsx +++ b/src/pages/storage/StorageUseCases.tsx @@ -84,7 +84,7 @@ export function StorageUseCases() {
- + Use Cases