4 Commits

Author SHA1 Message Date
c15b110afe feat: adjust hero section width on homepage
- Reduced max-width of hero content container from max-w-3xl to max-w-2xl for better content alignment and readability
- Content width now matches design specifications for desktop breakpoints
2025-11-01 21:08:51 +01:00
3564b5cb0f feat: enhance homepage with smooth scroll navigation
- Added scroll-to-slider functionality when clicking "Get Started" button
- Modified AnimatedSection to support ref forwarding for scroll targeting
- Updated HomeAurora component to accept click handler prop
- Refined homepage hero text and description for clearer value proposition
- Changed button from link to click handler for better user interaction
2025-11-01 21:08:42 +01:00
51ef8dffb5 feat: enhance UI components and layout styling
- Updated FeatureDescription text size to be larger on desktop (lg:text-base)
- Added rounded corners (rounded-3xl) to DarkCard component
- Modified CloudArchitecture section with wider container (max-w-5xl) and updated heading styles
- Adjusted mobile feature navigation indicators with darker colors (bg-gray-600/700)
- Improved hero section typography using H2 and H5 components for better hierarchy
- Refined padding and background styling in CloudFeatures mobile
2025-11-01 21:02:35 +01:00
9d8f1a6919 refactor: replace MagicCard with DarkCard component
- Replaced MagicCard with new DarkCard component across apple-cards-carousel and HomeGlobe
- Updated card styling and layout in apple-cards-carousel to work with DarkCard
- Removed gradient and border styling from globe stats cards
- Adjusted padding and margin values to maintain consistent appearance
- Fixed spacing and alignment of chevron icon in cards
2025-10-31 15:35:45 +01:00
10 changed files with 76 additions and 54 deletions

View File

@@ -1,4 +1,5 @@
import { motion } from 'framer-motion' import { motion } from 'framer-motion'
import { forwardRef } from 'react'
type AnimatedSectionProps = { type AnimatedSectionProps = {
children: React.ReactNode children: React.ReactNode
@@ -6,9 +7,11 @@ type AnimatedSectionProps = {
className?: string className?: string
} }
export function AnimatedSection({ children, id, className }: AnimatedSectionProps) { export const AnimatedSection = forwardRef<HTMLElement, AnimatedSectionProps>(
({ children, id, className }, ref) => {
return ( return (
<motion.section <motion.section
ref={ref}
id={id} id={id}
className={className} className={className}
initial={{ opacity: 0, y: 40 }} initial={{ opacity: 0, y: 40 }}
@@ -19,4 +22,5 @@ export function AnimatedSection({ children, id, className }: AnimatedSectionProp
{children} {children}
</motion.section> </motion.section>
) )
} },
)

View File

@@ -131,7 +131,7 @@ export const FeatureTitle = createTextComponent(
) )
export const FeatureDescription = createTextComponent( export const FeatureDescription = createTextComponent(
'p', 'p',
'text-sm leading-normal tracking-normal' 'lg:text-base text-sm leading-normal tracking-normal'
) )
export const MobileFeatureTitle = createTextComponent( export const MobileFeatureTitle = createTextComponent(
'h3', 'h3',

View File

@@ -11,6 +11,7 @@ import {
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { motion } from "motion/react"; import { motion } from "motion/react";
import { DarkCard } from "./cards";
interface CarouselProps { interface CarouselProps {
items: JSX.Element[]; items: JSX.Element[];
@@ -129,11 +130,12 @@ export const Card = ({
}) => { }) => {
return ( return (
<Link to={card.link}> <Link to={card.link}>
<motion.div <DarkCard className="p-0 rounded-3xl">
layoutId={layout ? `card-${card.title}` : undefined} <motion.div
className="relative z-10 flex h-104 w-80 flex-col justify-between overflow-hidden rounded-3xl border border-gray-500/30 bg-[#1C1C1C] transition-transform duration-200 hover:scale-105 md:h-120 md:w-96" layoutId={layout ? `card-${card.title}` : undefined}
> className="relative z-10 flex h-104 w-80 flex-col justify-between overflow-hidden rounded-3xl p-8 md:h-120 md:w-96"
<div className="flex h-2/5 flex-col justify-center py-6 px-8"> >
<div className="flex h-2/5 flex-col justify-center py-6 px-4">
<motion.p <motion.p
layoutId={layout ? `category-${card.category}` : undefined} layoutId={layout ? `category-${card.category}` : undefined}
className="text-left font-sans font-semibold text-cyan-500 uppercase tracking-wider text-xs md:text-sm" className="text-left font-sans font-semibold text-cyan-500 uppercase tracking-wider text-xs md:text-sm"
@@ -150,8 +152,8 @@ export const Card = ({
<motion.p className="max-w-xs text-left font-sans lg:text-xl text-lg text-neutral-300 lg:leading-normal leading-tight"> <motion.p className="max-w-xs text-left font-sans lg:text-xl text-lg text-neutral-300 lg:leading-normal leading-tight">
{card.description} {card.description}
</motion.p> </motion.p>
<div className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-[#212121] text-[#858585] transition-colors duration-200 hover:bg-[#262626] hover:text-white md:h-8 md:w-8"> <div className="flex h-6 w-6 ml-2 shrink-0 items-center justify-center rounded-full bg-[#212121] text-[#858585] transition-colors duration-200 hover:bg-[#262626] hover:text-white md:h-8 md:w-8">
<IconChevronRight className="h-4 w-4 md:h-6 md:w-6" /> <IconChevronRight className="h-4 w-4 md:h-6 md:w-6 " />
</div> </div>
</div> </div>
</div> </div>
@@ -162,7 +164,8 @@ export const Card = ({
className="h-full w-full origin-bottom-right scale-75 object-contain mb-10" className="h-full w-full origin-bottom-right scale-75 object-contain mb-10"
/> />
</div> </div>
</motion.div> </motion.div>
</DarkCard>
</Link> </Link>
); );
}; };

View File

@@ -0,0 +1,19 @@
import * as React from "react";
import { cn } from "@/lib/utils";
const DarkCard = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"border border-white/10 bg-white/3 p-8 backdrop-blur-sm transition hover:-translate-y-1 hover:border-cyan-300/50 rounded-3xl hover:bg-white/6 hover:scale-105 hover:shadow-lg hover:shadow-cyan-500/15",
className
)}
{...props}
/>
));
DarkCard.displayName = "DarkCard";
export { DarkCard };

View File

@@ -1,5 +1,5 @@
import { Container } from '../../components/Container' import { Container } from '../../components/Container'
import { Eyebrow, SectionHeader, P } from '../../components/Texts' import { Eyebrow, H3, P } from '../../components/Texts'
const architectureSections = [ const architectureSections = [
{ {
@@ -39,15 +39,15 @@ const architectureSections = [
export function CloudArchitecture() { export function CloudArchitecture() {
return ( return (
<section className="bg-white py-24 sm:py-32"> <section className="bg-white py-24 lg:py-32">
<Container> <Container>
<div className="mx-auto max-w-3xl text-center"> <div className="mx-auto max-w-5xl text-center">
<Eyebrow> <Eyebrow>
Technical Architecture Technical Architecture
</Eyebrow> </Eyebrow>
<SectionHeader as="h2" className="mt-6 text-gray-900"> <H3 className="mt-6 text-gray-900">
Built on a sovereign, encrypted delivery mesh. Built on a Sovereign, Encrypted Delivery Mesh.
</SectionHeader> </H3>
<P className="mt-6 text-gray-600"> <P className="mt-6 text-gray-600">
Mycelium Cloud rides on the ThreeFold Grid, pairing encrypted mesh Mycelium Cloud rides on the ThreeFold Grid, pairing encrypted mesh
networking with deterministic K3s orchestration. Every layer is networking with deterministic K3s orchestration. Every layer is

View File

@@ -363,7 +363,7 @@ function CloudFeaturesMobile() {
<div className="relative mx-auto w-full max-w-[366px]"> <div className="relative mx-auto w-full max-w-[366px]">
<feature.screen /> <feature.screen />
</div> </div>
<div className="absolute inset-x-0 bottom-0 bg-gray-800/95 p-6 backdrop-blur-sm sm:p-10"> <div className="absolute inset-x-0 bottom-0 bg-gray-800 p-6 backdrop-blur-sm sm:p-10">
<feature.icon className="h-8 w-8" /> <feature.icon className="h-8 w-8" />
<MobileFeatureTitle color="white" className="mt-6"> <MobileFeatureTitle color="white" className="mt-6">
{feature.name} {feature.name}
@@ -383,7 +383,7 @@ function CloudFeaturesMobile() {
key={featureIndex} key={featureIndex}
className={clsx( className={clsx(
'relative h-0.5 w-4 rounded-full', 'relative h-0.5 w-4 rounded-full',
featureIndex === activeIndex ? 'bg-gray-300' : 'bg-gray-500', featureIndex === activeIndex ? 'bg-gray-600' : 'bg-gray-700',
)} )}
aria-label={`Go to slide ${featureIndex + 1}`} aria-label={`Go to slide ${featureIndex + 1}`}
onClick={() => { onClick={() => {

View File

@@ -2,7 +2,7 @@ import { useId } from 'react'
import { Button } from '../../components/Button' import { Button } from '../../components/Button'
import { Container } from '../../components/Container' import { Container } from '../../components/Container'
import { Eyebrow, SectionHeader, P } from '../../components/Texts' import { Eyebrow, H2, P, H5 } from '../../components/Texts'
function BackgroundIllustration(props: React.ComponentPropsWithoutRef<'div'>) { function BackgroundIllustration(props: React.ComponentPropsWithoutRef<'div'>) {
const id = useId() const id = useId()
@@ -82,16 +82,16 @@ export function CloudHero() {
<Eyebrow className="tracking-[0.35em] uppercase text-cyan-500"> <Eyebrow className="tracking-[0.35em] uppercase text-cyan-500">
Mycelium Cloud Mycelium Cloud
</Eyebrow> </Eyebrow>
<SectionHeader as="h1" className="mt-6 text-gray-900"> <H2 as="h1" className="mt-6 text-gray-900">
Deploy sovereign Kubernetes clusters on decentralized Deploy sovereign Kubernetes clusters on decentralized
infrastructure. infrastructure.
</SectionHeader> </H2>
<P className="mt-6 text-gray-600"> <H5 className="mt-6 text-gray-600">
Mycelium Cloud turns the ThreeFold Grid into a programmable Mycelium Cloud turns the ThreeFold Grid into a programmable
substrate for K3s. Launch verifiable clusters with nature-inspired substrate for K3s. Launch verifiable clusters with nature-inspired
networking, quantum-safe storage, and zero-image delivery that networking, quantum-safe storage, and zero-image delivery that
keeps every workload deterministic. keeps every workload deterministic.
</P> </H5>
<P className="mt-6 text-gray-500"> <P className="mt-6 text-gray-500">
Developer guide to decentralized cloud computing. Developer guide to decentralized cloud computing.
</P> </P>

View File

@@ -2,7 +2,7 @@ import { H1, H5 } from "@/components/Texts"
import { Button } from "@/components/Button" import { Button } from "@/components/Button"
export function HomeAurora() { export function HomeAurora({ onGetStartedClick }: { onGetStartedClick: () => void }) {
return ( return (
<div <div
className="relative bg-cover sm:bg-contain bg-right bg-no-repeat" className="relative bg-cover sm:bg-contain bg-right bg-no-repeat"
@@ -10,28 +10,30 @@ export function HomeAurora() {
> >
<div className="mx-auto max-w-7xl lg:px-4"> <div className="mx-auto max-w-7xl lg:px-4">
<div className="px-6 pt-12 pb-24 sm:pb-32 lg:col-span-5 lg:px-0 lg:pt-40 lg:pb-48 xl:col-span-5"> <div className="px-6 pt-12 pb-24 sm:pb-32 lg:col-span-5 lg:px-0 lg:pt-40 lg:pb-48 xl:col-span-5">
<div className="mx-auto max-w-3xl lg:mx-0"> <div className="mx-auto max-w-2xl lg:mx-0">
<div className="hidden sm:flex"> <div className="hidden sm:flex">
<div className="relative rounded-full px-3 py-1 text-sm/6 text-gray-500 ring-1 ring-gray-900/10 hover:ring-gray-900/20"> <div className="relative rounded-full px-3 py-1 text-sm/6 text-gray-500 ring-1 ring-gray-900/10 hover:ring-gray-900/20">
Anim aute id magna aliqua ad ad non deserunt sunt.{' '} Anim aute id magna aliqua ad ad non deserunt sunt.{' '}
<a href="#" className="font-semibold whitespace-nowrap text-cyan-600"> <a href="#" className="font-semibold whitespace-nowrap text-cyan-600">
<span aria-hidden="true" className="absolute inset-0" /> <span aria-hidden="true" className="absolute inset-0" />
Read more <span aria-hidden="true">&rarr;</span> Read more <span aria-hidden="trwhenue">&rarr;</span>
</a> </a>
</div> </div>
</div> </div>
<H1 className="mt-8"> <H1 className="mt-8">
Full Sovereignty for Cloud, Network & AI. The Sovereign Agentic Cloud
</H1> </H1>
<H5 className="mt-8 text-lg text-gray-600"> <H5 className="mt-8 text-lg text-gray-600">
Build and run mission-critical workloads on distributed compute, encrypted networking, and sovereign AI orchestration without centralized gatekeepers. A global, self-healing network you can join.
Host nodes, deploy workloads, or build private AI systems,
all on infrastructure you own and control.
</H5> </H5>
<div className="mt-10 flex items-center gap-x-6"> <div className="mt-10 flex items-center gap-x-6">
<Button <Button
to="#"
variant="solid" variant="solid"
className="" className=""
color="cyan" color="cyan"
onClick={onGetStartedClick}
> >
Get started Get started
</Button> </Button>

View File

@@ -4,7 +4,7 @@ import { Globe } from "@/components/ui/Globe"
import { motion } from "framer-motion" import { motion } from "framer-motion"
import { P, CT, CP, SectionHeader, Eyebrow } from "@/components/Texts" import { P, CT, CP, SectionHeader, Eyebrow } from "@/components/Texts"
import { CountUpNumber } from '@/components/CountUpNumber' import { CountUpNumber } from '@/components/CountUpNumber'
import { MagicCard } from '@/components/magicui/magic-card' import { DarkCard } from "@/components/ui/cards";
export function WorldMap() { export function WorldMap() {
return ( return (
@@ -65,16 +65,13 @@ export function WorldMap() {
transition={{ duration: 0.5, delay: 0.4, ease: "easeOut" }} transition={{ duration: 0.5, delay: 0.4, ease: "easeOut" }}
className="lg:absolute lg:top-12 lg:-left-12 w-80" className="lg:absolute lg:top-12 lg:-left-12 w-80"
> >
<MagicCard <DarkCard>
gradientColor="#334155"
className="border border-gray-500/30 transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-xl hover:shadow-cyan-500/20"
>
<div><CT color="light" className="uppercase tracking-wide [text-shadow:0_0_12px_var(--color-cyan-500)]">CORES</CT></div> <div><CT color="light" className="uppercase tracking-wide [text-shadow:0_0_12px_var(--color-cyan-500)]">CORES</CT></div>
<div><CountUpNumber end={54958} className="mt-2 text-3xl font-bold text-white [text-shadow:0_0_12px_var(--color-cyan-500)]" /></div> <div><CountUpNumber end={54958} className="mt-2 text-3xl font-bold text-white [text-shadow:0_0_12px_var(--color-cyan-500)]" /></div>
<CP color="light" className="mt-2 text-sm"> <CP color="light" className="mt-2 text-sm">
Total Central Processing Unit Cores available on the grid. Total Central Processing Unit Cores available on the grid.
</CP> </CP>
</MagicCard> </DarkCard>
</motion.div> </motion.div>
<motion.div <motion.div
@@ -84,16 +81,13 @@ export function WorldMap() {
transition={{ duration: 0.5, delay: 0.5, ease: "easeOut" }} transition={{ duration: 0.5, delay: 0.5, ease: "easeOut" }}
className="lg:absolute lg:-top-10 lg:right-0 w-80" className="lg:absolute lg:-top-10 lg:right-0 w-80"
> >
<MagicCard <DarkCard>
gradientColor="#334155"
className="border border-gray-500/30 transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-xl hover:shadow-cyan-500/20"
>
<div><CT color="light" className="uppercase tracking-wide [text-shadow:0_0_12px_var(--color-cyan-500)]">NODES</CT></div> <div><CT color="light" className="uppercase tracking-wide [text-shadow:0_0_12px_var(--color-cyan-500)]">NODES</CT></div>
<div><CountUpNumber end={1493} className="mt-4 text-3xl font-bold text-white [text-shadow:0_0_12px_var(--color-cyan-500)]" /></div> <div><CountUpNumber end={1493} className="mt-4 text-3xl font-bold text-white [text-shadow:0_0_12px_var(--color-cyan-500)]" /></div>
<CP color="light" className="mt-2 text-sm"> <CP color="light" className="mt-2 text-sm">
Total number of nodes on the grid. Total number of nodes on the grid.
</CP> </CP>
</MagicCard> </DarkCard>
</motion.div> </motion.div>
<motion.div <motion.div
@@ -103,16 +97,13 @@ export function WorldMap() {
transition={{ duration: 0.5, delay: 0.6, ease: "easeOut" }} transition={{ duration: 0.5, delay: 0.6, ease: "easeOut" }}
className="lg:absolute lg:bottom-28 lg:-left-12 w-80" className="lg:absolute lg:bottom-28 lg:-left-12 w-80"
> >
<MagicCard <DarkCard>
gradientColor="#334155"
className="border border-gray-500/30 transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-xl hover:shadow-cyan-500/20"
>
<div><CT color="light" className="uppercase tracking-wide [text-shadow:0_0_12px_var(--color-cyan-500)]">SSD CAPACITY</CT></div> <div><CT color="light" className="uppercase tracking-wide [text-shadow:0_0_12px_var(--color-cyan-500)]">SSD CAPACITY</CT></div>
<div><CountUpNumber end={5388956} className="mt-2 text-3xl font-bold text-white [text-shadow:0_0_12px_var(--color-cyan-500)]" /></div> <div><CountUpNumber end={5388956} className="mt-2 text-3xl font-bold text-white [text-shadow:0_0_12px_var(--color-cyan-500)]" /></div>
<CP color="light" className="mt-2 text-sm"> <CP color="light" className="mt-2 text-sm">
Total GB amount of storage (SSD, HDD, & RAM) on the grid. Total GB amount of storage (SSD, HDD, & RAM) on the grid.
</CP> </CP>
</MagicCard> </DarkCard>
</motion.div> </motion.div>
<motion.div <motion.div
@@ -122,16 +113,13 @@ export function WorldMap() {
transition={{ duration: 0.5, delay: 0.7, ease: "easeOut" }} transition={{ duration: 0.5, delay: 0.7, ease: "easeOut" }}
className="lg:absolute lg:top-47 lg:right-0 w-80" className="lg:absolute lg:top-47 lg:right-0 w-80"
> >
<MagicCard <DarkCard>
gradientColor="#334155"
className="border border-gray-500/30 transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-xl hover:shadow-cyan-500/20"
>
<div><CT color="light" className="uppercase tracking-wide [text-shadow:0_0_12px_var(--color-cyan-500)]">COUNTRIES</CT></div> <div><CT color="light" className="uppercase tracking-wide [text-shadow:0_0_12px_var(--color-cyan-500)]">COUNTRIES</CT></div>
<div><CountUpNumber end={44} className="mt-2 text-3xl font-bold text-white [text-shadow:0_0_12px_var(--color-cyan-500)]" /></div> <div><CountUpNumber end={44} className="mt-2 text-3xl font-bold text-white [text-shadow:0_0_12px_var(--color-cyan-500)]" /></div>
<CP color="light" className="mt-2 text-sm"> <CP color="light" className="mt-2 text-sm">
Total number of countries with active nodes. Total number of countries with active nodes.
</CP> </CP>
</MagicCard> </DarkCard>
</motion.div> </motion.div>
</div> </div>
</div> </div>

View File

@@ -1,3 +1,4 @@
import { useRef } from 'react'
import { AnimatedSection } from '../../components/AnimatedSection' import { AnimatedSection } from '../../components/AnimatedSection'
import { HomeAurora } from './HomeAurora' import { HomeAurora } from './HomeAurora'
import { StackSectionLight } from './StackSection' import { StackSectionLight } from './StackSection'
@@ -8,10 +9,15 @@ import { HomeSlider } from './HomeSlider'
export default function HomePage() { export default function HomePage() {
const sliderRef = useRef<HTMLDivElement>(null)
const handleScrollToSlider = () => {
sliderRef.current?.scrollIntoView({ behavior: 'smooth' })
}
return ( return (
<div> <div>
<AnimatedSection> <AnimatedSection>
<HomeAurora /> <HomeAurora onGetStartedClick={handleScrollToSlider} />
</AnimatedSection> </AnimatedSection>
<AnimatedSection id="next-section"> <AnimatedSection id="next-section">
@@ -23,7 +29,7 @@ export default function HomePage() {
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection ref={sliderRef}>
<HomeSlider /> <HomeSlider />
</AnimatedSection> </AnimatedSection>