"use client" import { useState } from "react" import { useSectionReveal } from "@/hooks/use-section-reveal" import { ExternalLink } from "lucide-react" interface NetworkNode { name: string domain: string description: string x: number y: number primary?: boolean } const NODES: NetworkNode[] = [ { name: "MycoStack", domain: "mycostack.xyz", description: "Technology-augmented commons", x: 50, y: 45, primary: true, }, { name: "Commons Stack", domain: "commonsstack.org", description: "Fund and govern the commons — primary root", x: 50, y: 8, }, { name: "P2P Foundation", domain: "wiki.p2pfoundation.net", description: "25,000 pages of commons knowledge", x: 50, y: 95, }, { name: "MycoFi", domain: "mycofi.earth", description: "Mycoeconomics & regenerative currencies", x: 20, y: 18, }, { name: "NoFi", domain: "nofi.lol", description: "Post-finance — making change, not money", x: 80, y: 18, }, { name: "Defect.fi", domain: "defect.fi", description: "Defecting from extractive finance", x: 92, y: 25, }, { name: "Mycopunk", domain: "mycopunk.xyz", description: "Building from beneath the surface", x: 8, y: 32, }, { name: "rFunds", domain: "rfunds.online", description: "Threshold-Based Flow Funding research", x: 30, y: 28, }, { name: "rStack", domain: "rstack.org", description: "Open source community coordination infrastructure", x: 78, y: 55, }, { name: "Compost Capitalism", domain: "compostcapitalism.xyz", description: "Decomposing extractive systems", x: 10, y: 55, }, { name: "The Undernet", domain: "undernet.earth", description: "Community-owned infrastructure", x: 92, y: 38, }, { name: "Post-Appitalism", domain: "post-appitalist.app", description: "Tools beyond extractive platforms", x: 15, y: 78, }, { name: "rSpace", domain: "yourspace.online", description: "Community-owned digital spaces", x: 65, y: 78, }, { name: "Psilo-Cyber", domain: "psilo-cyber.net", description: "Encrypted mesh networks", x: 88, y: 70, }, { name: "Trippin Balls", domain: "trippinballs.lol", description: "Expand your perspective", x: 38, y: 92, }, ] const CONNECTIONS: [string, string][] = [ ["mycostack.xyz", "commonsstack.org"], ["mycostack.xyz", "wiki.p2pfoundation.net"], ["mycostack.xyz", "mycofi.earth"], ["mycostack.xyz", "undernet.earth"], ["mycostack.xyz", "compostcapitalism.xyz"], ["mycostack.xyz", "yourspace.online"], ["mycostack.xyz", "rstack.org"], ["mycostack.xyz", "nofi.lol"], ["commonsstack.org", "wiki.p2pfoundation.net"], ["commonsstack.org", "mycofi.earth"], ["commonsstack.org", "mycopunk.xyz"], ["commonsstack.org", "rfunds.online"], ["commonsstack.org", "nofi.lol"], ["rfunds.online", "mycofi.earth"], ["nofi.lol", "mycofi.earth"], ["nofi.lol", "defect.fi"], ["defect.fi", "mycofi.earth"], ["rstack.org", "yourspace.online"], ["rstack.org", "undernet.earth"], ["wiki.p2pfoundation.net", "post-appitalist.app"], ["mycofi.earth", "mycopunk.xyz"], ["undernet.earth", "psilo-cyber.net"], ["compostcapitalism.xyz", "post-appitalist.app"], ["post-appitalist.app", "yourspace.online"], ["yourspace.online", "trippinballs.lol"], ["mycopunk.xyz", "psilo-cyber.net"], ["mycopunk.xyz", "undernet.earth"], ] function getNode(domain: string) { return NODES.find((n) => n.domain === domain) } export function NetworkMapSection() { const sectionRef = useSectionReveal() const [hovered, setHovered] = useState(null) const isConnected = (domain: string) => { if (!hovered) return false return CONNECTIONS.some( ([a, b]) => (a === hovered && b === domain) || (b === hovered && a === domain) ) } const getLineOpacity = (a: string, b: string) => { if (!hovered) return 0.15 if ( (a === hovered || b === hovered) && (isConnected(a) || isConnected(b) || a === hovered || b === hovered) ) return 0.5 return 0.06 } return (

The Network of Networks

Every node strengthens the whole. Every connection multiplies possibility.

{/* Desktop: SVG network map */}
{/* Connection lines */} {CONNECTIONS.map(([a, b]) => { const nodeA = getNode(a) const nodeB = getNode(b) if (!nodeA || !nodeB) return null return ( ) })} {/* Node cards */} {NODES.map((node) => { const isActive = hovered === node.domain const connected = isConnected(node.domain) const dimmed = hovered && !isActive && !connected return ( setHovered(node.domain)} onMouseLeave={() => setHovered(null)} >
{node.name}
{node.domain}
{isActive && (
{node.description}
)}
) })}
{/* Mobile: Simple card list */}
{NODES.map((node, i) => (
{node.name}
{node.domain}
{node.description}
))}
) }