refactor: remove placeholder CTAs and links across multiple pages

- Removed unused Button imports from AgentHeroAlt, GallerySection, ComputeCapabilities, and StorageCapabilitiesNew
- Replaced placeholder buttons/links with TODO comments indicating future implementation
- Changed StorageCoreValue value items from <a> to <div> and removed href/target/rel attributes
- Added descriptive TODO comments explaining what was previously rendered and what needs to be added
- Affected components: AgentHeroAlt (
This commit is contained in:
2025-11-19 16:42:48 +01:00
parent f1e1721b25
commit 6d96ff9ea8
12 changed files with 89 additions and 94 deletions

View File

@@ -8,7 +8,7 @@ export function Footer() {
<div className="flex flex-col items-start justify-between gap-y-12 pt-16 pb-6 lg:flex-row lg:items-center lg:py-8"> <div className="flex flex-col items-start justify-between gap-y-12 pt-16 pb-6 lg:flex-row lg:items-center lg:py-8">
<div> <div>
<div className="flex items-center text-gray-900"> <div className="flex items-center text-gray-900">
<img src="src/images/logos/logomark.svg" alt="Mycelium Logomark" className="h-13 w-13 flex-none" /> <img src="/images/logomark.svg" alt="Mycelium Logomark" className="h-13 w-13 flex-none" />
<div className="ml-4"> <div className="ml-4">
<p className="text-base lg:text-lg font-semibold">Project Mycelium</p> <p className="text-base lg:text-lg font-semibold">Project Mycelium</p>
<p className="mt-1 text-sm">Unleash the Power of Decentralization</p> <p className="mt-1 text-sm">Unleash the Power of Decentralization</p>

View File

@@ -71,30 +71,27 @@ const clusterNodes = (nodeList: GeoNode[], cellSize = 2) => {
function DynamicMapContainer() { function DynamicMapContainer() {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [nodes, setNodes] = useState<GeoNode[]>([]); const [nodes, setNodes] = useState<GeoNode[]>([]);
const API_URL = "https://gridproxy.grid.tf/nodes?healthy=true&size=99999"; const API_URL = "https://gridproxy.grid.tf/nodes?healthy=true&size=500";
useEffect(() => { useEffect(() => {
async function fetchNodeData() { async function fetchNodeData() {
try { try {
const response = await fetch(API_URL); const response = await fetch(API_URL);
const data: RawNode[] = await response.json(); // Type the incoming data const data: RawNode[] = await response.json();
// 🚨 Map the API response to your component's expected GeoNode format
const geoNodes: GeoNode[] = data const geoNodes: GeoNode[] = data
.filter((node: RawNode) => node.location && node.location.latitude && node.location.longitude) .filter((node: RawNode) => node.location && node.location.latitude && node.location.longitude)
.map((node: RawNode) => ({ .map((node: RawNode) => ({
// Convert string coordinates to numbers lat: parseFloat(node.location.latitude),
lat: parseFloat(node.location.latitude), lng: parseFloat(node.location.longitude),
lng: parseFloat(node.location.longitude),
label: `${node.location.city}, ${node.location.country} (${node.node_id})`, label: `${node.location.city}, ${node.location.country} (${node.node_id})`,
// Optionally set color based on some node property if available
})); }));
const clusteredNodes = clusterNodes(geoNodes); const clusteredNodes = clusterNodes(geoNodes);
setNodes(clusteredNodes); setNodes(clusteredNodes);
setLoading(false);
} catch (error) { } catch (error) {
console.error("Failed to fetch node data:", error); console.error("Failed to fetch node data:", error);
} finally {
setLoading(false); setLoading(false);
} }
} }
@@ -102,30 +99,24 @@ function DynamicMapContainer() {
fetchNodeData(); fetchNodeData();
}, []); }, []);
// --- RENDERING --- // While fetching, show a loading state
if (loading) { if (loading) {
// Show a loading state while data is being fetched
return ( return (
<div className="flex justify-center items-center w-full aspect-[2/1] bg-[#111111] rounded-lg text-cyan-500"> <div className="flex justify-center items-center w-full aspect-[2/1] bg-[#111111] rounded-lg text-cyan-500">
<motion.span <motion.span
animate={{ rotate: 360 }} animate={{ rotate: 360 }}
transition={{ duration: 1, repeat: Infinity, ease: "linear" }} transition={{ duration: 1, repeat: Infinity, ease: "linear" }}
className="text-4xl" className="text-4xl"
> >
🌎 🌎
</motion.span> </motion.span>
<p className="ml-4">Loading nodes...</p> <p className="ml-4">Loading nodes...</p>
</div> </div>
); );
} }
// Pass the dynamically fetched nodes to your WorldMap component // After data is loaded, render the map
return ( return <WorldMap nodes={nodes} />;
<WorldMap
nodes={nodes}
/>
);
} }
export default DynamicMapContainer; export default DynamicMapContainer;

View File

@@ -1,6 +1,5 @@
'use client' 'use client'
import { Button } from '@/components/Button'
import { Eyebrow, H3, P } from '@/components/Texts' import { Eyebrow, H3, P } from '@/components/Texts'
export function AgentHeroAlt() { export function AgentHeroAlt() {
@@ -30,12 +29,8 @@ Private, local, and autonomous by design, they give you everything you need to b
</P> </P>
<div className="mt-10 flex items-center gap-x-6"> <div className="mt-10 flex items-center gap-x-6">
<Button href="#" variant="solid" color="cyan"> {/* TODO: Hero CTAs (Follow Development / Explore Docs) to be added when links are ready.
Follow Development Previously two Buttons here with href="#". */}
</Button>
<Button href="#" variant="outline">
Explore Docs <span aria-hidden="true"></span>
</Button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -4,7 +4,6 @@ import { useEffect, useMemo, useState } from 'react'
import { useResponsiveCarousel } from '@/hooks/useResponsiveCarousel'; import { useResponsiveCarousel } from '@/hooks/useResponsiveCarousel';
import { motion, AnimatePresence } from 'framer-motion' import { motion, AnimatePresence } from 'framer-motion'
import { wrap } from 'popmotion' import { wrap } from 'popmotion'
import { Button } from '@/components/Button';
import { SectionHeader, P, Eyebrow, CP } from '@/components/Texts'; import { SectionHeader, P, Eyebrow, CP } from '@/components/Texts';
import { TypeAnimation } from 'react-type-animation' import { TypeAnimation } from 'react-type-animation'
import { FadeIn } from '@/components/FadeIn'; import { FadeIn } from '@/components/FadeIn';
@@ -147,9 +146,8 @@ export function GallerySection() {
repeat={0} repeat={0}
/> />
</CP> </CP>
<Button href="#" color="cyan" className="text-sm px-4 py-2 lg:text-base whitespace-nowrap"> {/* TODO: Desktop CTA (Start) button to be added when link target is defined.
Start Previously: <Button href="#" color="cyan">Start</Button> */}
</Button>
</div> </div>
</div> </div>
</section> </section>
@@ -166,9 +164,8 @@ export function GallerySection() {
repeat={0} repeat={0}
/> />
</CP> </CP>
<Button href="#" color="cyan" className="text-xs px-3 py-1.5 whitespace-nowrap"> {/* TODO: Mobile CTA (Start) button to be added when link target is defined.
Start Previously: <Button href="#" color="cyan">Start</Button> */}
</Button>
</div> </div>
</div> </div>
</FadeIn> </FadeIn>

View File

@@ -2,7 +2,6 @@
import { Container } from '@/components/Container' import { Container } from '@/components/Container'
import { Eyebrow, H3, P } from '@/components/Texts' import { Eyebrow, H3, P } from '@/components/Texts'
import { Button } from '@/components/Button'
const capabilities = [ const capabilities = [
{ {
@@ -76,14 +75,8 @@ export function ComputeCapabilities() {
</ul> </ul>
{/* Button section */} {/* Button section */}
<div className="mx-auto mt-12 flex justify-center gap-6"> {/* TODO: CTA buttons (Get Started / Explore Docs) to be re-enabled when real links are available.
<Button variant="solid" color="cyan" href="#"> Previously rendered here as two Buttons with href="#". */}
Get Started
</Button>
<Button variant="outline" color="white" href="#">
Explore Docs
</Button>
</div>
</Container> </Container>
</div> </div>

View File

@@ -78,12 +78,8 @@ export function ComputeCapabilitiesNew() {
{/* Arrows inside first card */} {/* Arrows inside first card */}
<div className="flex items-center gap-x-4 mt-2"> <div className="flex items-center gap-x-4 mt-2">
<a {/* TODO: Intro card CTA (Learn more) to be added here when destination is defined.
href="#" Previously: <a href="#" className="inline-flex items-center ...">Learn more →</a> */}
className="inline-flex items-center gap-1 text-cyan-400 hover:text-cyan-300 text-sm font-medium mr-auto"
>
Learn more
</a>
<button <button
onClick={scrollLeft} onClick={scrollLeft}
className="h-8 w-8 flex items-center justify-center border border-gray-800 rounded-md hover:border-cyan-500 transition-colors" className="h-8 w-8 flex items-center justify-center border border-gray-800 rounded-md hover:border-cyan-500 transition-colors"

View File

@@ -35,9 +35,8 @@ export function ComputeHero({ onGetStartedClick = () => {} }: { onGetStartedClic
> >
Get started Get started
</Button> </Button>
<Button to="#" variant="outline"> {/* TODO: Secondary CTA (Documentation) link to be wired when docs route is ready.
Documentation <span aria-hidden="true"></span> Previously: <Button to="#" variant="outline">Documentation →</Button> */}
</Button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -103,7 +103,7 @@ export function HomeMap() {
Mycelium runs on nodes hosted by people and organizations around the world. Mycelium runs on nodes hosted by people and organizations around the world.
Each node adds compute, storage, and bandwidth, expanding the networks capacity and resilience. Each node adds compute, storage, and bandwidth, expanding the networks capacity and resilience.
</P> </P>
<P className="text-sm md:text-lg text-gray-200 max-w-3xl mx-auto py-4"> <P className="text-sm md:text-lg text-gray-200 max-w-3xl mx-auto mt-2 mb-6">
You can share your idle resources and earn rewards when they are used. You can share your idle resources and earn rewards when they are used.
Configure it once. Your node takes over from there. Configure it once. Your node takes over from there.
</P> </P>

View File

@@ -1,4 +1,4 @@
import { useEffect, useRef, useState } from 'react'
import { AnimatedSection } from '../../components/AnimatedSection' import { AnimatedSection } from '../../components/AnimatedSection'
import { CallToAction } from './CallToAction' import { CallToAction } from './CallToAction'
import { HomeTab } from './HomeTab' import { HomeTab } from './HomeTab'
@@ -7,7 +7,50 @@ import { HomeAurora } from './HomeAurora'
import { HomeArchitecture } from './HomeArchitecture'; import { HomeArchitecture } from './HomeArchitecture';
import { HomeDesign } from './HomeDesign'; import { HomeDesign } from './HomeDesign';
function LazyHomeMapSection() {
const [isVisible, setIsVisible] = useState(false)
const containerRef = useRef<HTMLDivElement | null>(null)
useEffect(() => {
const el = containerRef.current
if (!el || isVisible) return
const observer = new IntersectionObserver(
(entries) => {
const [entry] = entries
if (entry.isIntersecting) {
setIsVisible(true)
observer.disconnect()
}
},
{
root: null,
rootMargin: '200px 0px',
threshold: 0.1,
},
)
observer.observe(el)
return () => {
observer.disconnect()
}
}, [isVisible])
return (
<div ref={containerRef}>
{isVisible ? (
<HomeMap />
) : (
<div className="max-w-7xl mx-auto px-6 py-16 text-center text-gray-400">
<p className="text-sm md:text-base">
Loading live node map when you scroll here
</p>
</div>
)}
</div>
)
}
export default function HomePage() { export default function HomePage() {
return ( return (
@@ -17,7 +60,7 @@ export default function HomePage() {
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection>
<HomeArchitecture/> <HomeArchitecture />
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection>
@@ -25,16 +68,16 @@ export default function HomePage() {
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection>
<HomeMap /> <LazyHomeMapSection />
</AnimatedSection> </AnimatedSection>
<AnimatedSection>
<HomeDesign /> <HomeDesign />
</AnimatedSection>
<AnimatedSection>
<CallToAction /> <CallToAction />
</AnimatedSection>
</div> </div>
) )
} }

View File

@@ -116,20 +116,8 @@ export function PodsPricing() {
</ul> </ul>
</div> </div>
{/* CTA */} {/* TODO: Plan-specific CTA (Choose Pod) to be reinstated when purchase/upgrade flows are ready.
<a Previously rendered an <a href={tier.href}>Choose Pod</a> button here. */}
href={tier.href}
aria-describedby={tier.id}
className={`mt-8 block rounded-md px-3 py-2 text-center text-sm font-semibold
focus-visible:outline-2 focus-visible:outline-offset-2
${
tier.mostPopular
? "bg-cyan-500 text-white hover:bg-cyan-400 focus-visible:outline-cyan-500"
: "bg-white/10 text-white hover:bg-white/20 focus-visible:outline-cyan-500"
}`}
>
Choose Pod
</a>
</div> </div>
))} ))}
</div> </div>

View File

@@ -70,12 +70,8 @@ export function StorageCapabilitiesNew() {
{/* Arrows inside first card */} {/* Arrows inside first card */}
<div className="flex items-center gap-x-4 mt-2"> <div className="flex items-center gap-x-4 mt-2">
<a {/* TODO: Intro card CTA (Learn more) to be added here when destination is defined.
href="#" Previously: <a href="#" className="inline-flex items-center ...">Learn more →</a> */}
className="inline-flex items-center gap-1 text-cyan-400 hover:text-cyan-300 text-sm font-medium mr-auto"
>
Learn more
</a>
<button <button
onClick={scrollLeft} onClick={scrollLeft}
className="h-8 w-8 flex items-center justify-center border border-gray-800 rounded-md hover:border-cyan-500 transition-colors" className="h-8 w-8 flex items-center justify-center border border-gray-800 rounded-md hover:border-cyan-500 transition-colors"

View File

@@ -51,18 +51,15 @@ export function StorageCoreValue() {
{/* ✅ 3x2 logo grid */} {/* ✅ 3x2 logo grid */}
<div className="mt-12 grid grid-cols-3 gap-x-8 gap-y-12"> <div className="mt-12 grid grid-cols-3 gap-x-8 gap-y-12">
{values.map((value, i) => ( {values.map((value, i) => (
<a <div
key={i} key={i}
href={value.href}
target="_blank"
rel="noopener noreferrer"
className="flex flex-col items-center text-center p-6 border border-gray-200 rounded-lg transition-transform duration-300 hover:scale-105 hover:shadow-lg" className="flex flex-col items-center text-center p-6 border border-gray-200 rounded-lg transition-transform duration-300 hover:scale-105 hover:shadow-lg"
> >
<value.animation /> <value.animation />
<CT className="text-gray-900 mt-4 font-semibold"> <CT className="text-gray-900 mt-4 font-semibold">
{value.title} {value.title}
</CT> </CT>
</a> </div>
))} ))}
</div> </div>
</Container> </Container>