"use client"; import { useMemo } from "react"; import { useGitHubStats } from "@/hooks/useGitHubStats"; import { OpenSourceCard } from "@/components/OpenSourceCard"; import { MaintainedProject, OpenSourceContribution, HostedService, } from "@/lib/types"; import ExternalLink from "@/components/ExternalLink"; import { SiGithub } from "react-icons/si"; import { ArrowUpRight } from "lucide-react"; interface OpenSourceContentProps { projects: MaintainedProject[]; contributions: OpenSourceContribution[]; services: HostedService[]; } export function OpenSourceContent({ projects, contributions, services, }: OpenSourceContentProps) { // Collect all GitHub repos for stats fetching const allRepos = useMemo(() => { const repos: string[] = []; projects.forEach((p) => repos.push(p.repo)); contributions.forEach((c) => repos.push(c.repo)); services.filter((s) => s.repo).forEach((s) => repos.push(s.repo!)); return [...new Set(repos)]; // Deduplicate }, [projects, contributions, services]); const { stats, loading } = useGitHubStats(allRepos); // Sort projects: featured first, then by stars const sortedProjects = useMemo(() => { return [...projects].sort((a, b) => { if (a.featured && !b.featured) return -1; if (!a.featured && b.featured) return 1; const starsA = stats[a.repo]?.stars || 0; const starsB = stats[b.repo]?.stars || 0; return starsB - starsA; }); }, [projects, stats]); return (
{/* Page intro */}

I believe in open source software. Here are the projects I maintain, my contributions to others, and the services I host.

{/* Section 1: Maintained Projects */}

Maintained Projects

Projects I actively maintain and develop.

{sortedProjects.map((project) => ( ))}
{/* Section 2: Contributions */} {contributions.length > 0 && (

Contributions to Other Projects

Open source projects I've contributed to.

{contributions.map((contribution, index) => (
{contribution.project} {contribution.contributionType}
{contribution.description && (

{contribution.description}

)}
))}
)} {/* Section 3: Hosted Services */} {services.length > 0 && (

Hosted Services

Live services and applications I host and maintain.

{services.map((service, index) => (

{service.name}

{service.status === "alpha" && ( Alpha )} {service.status === "beta" && ( Beta )} {service.status === "deprecated" && ( Deprecated )}
{service.repo && ( )}

{service.description}

))}
)}
); }