// app/projects/code/page.tsx import MatrixRain from '@/app/components/MatrixRain'; import { FaCodeBranch, FaGithub, FaGitlab, FaGlobe, FaStar } from 'react-icons/fa'; import Image from 'next/image'; interface GithubProfile { html_url: string; avatar_url: string; name: string; login: string; bio: string; followers: number; public_repos: number; } interface GithubRepo { id: number; name: string; description: string; html_url: string; language: string; stargazers_count: number; forks: number; } interface GitlabRepo { id: number; name: string; description: string; web_url: string; star_count: number; forks_count: number; language?: string; } async function getProfile(): Promise { try { const res = await fetch('https://api.github.com/users/WilliamSoderberg', { next: { revalidate: 60 } }); if (!res.ok) return null; return res.json(); } catch { return null; } } async function getGithubRepos(): Promise { try { const res = await fetch('https://api.github.com/users/WilliamSoderberg/repos?sort=updated', { next: { revalidate: 60 } }); if (!res.ok) return []; return res.json(); } catch { return []; } } async function getGitlabRepos(): Promise { try { const res = await fetch('https://gitlab.soderberg.tech/api/v4/groups/soderberg-tech/projects', { next: { revalidate: 60 } }); if (!res.ok) return []; const projects: GitlabRepo[] = await res.json(); const projectsWithLanguages = await Promise.all( projects.map(async (repo) => { try { const langRes = await fetch(`https://gitlab.soderberg.tech/api/v4/projects/${repo.id}/languages`, { next: { revalidate: 60 } }); if (langRes.ok) { const languages = await langRes.json(); const topLanguage = Object.keys(languages).sort((a, b) => languages[b] - languages[a])[0]; return { ...repo, language: topLanguage }; } } catch { console.error(`Failed to fetch language for GitLab repo: ${repo.id}`); } return repo; }) ); return projectsWithLanguages; } catch { console.error("GitLab fetch failed, returning empty array"); return []; } } const langColors: Record = { JavaScript: 'bg-[#f1e05a]', TypeScript: 'bg-[#2b7489]', TSX: 'bg-[#2b7489]', Python: 'bg-[#3572A5]', PHP: 'bg-[#4F5D95]', CSS: 'bg-[#563d7c]', HTML: 'bg-[#e44b23]', Vue: 'bg-[#41b883]' }; export default async function CodePage() { const [profile, githubRepos, gitlabRepos] = await Promise.all([ getProfile(), getGithubRepos(), getGitlabRepos() ]); return (
{/* 2. Profile Card Section */} {profile && (
Avatar

{profile.name}

{profile.bio}

{profile.followers}
Followers
{profile.public_repos}
Repositories
)} {/* 3. GitLab Repositories Section */}

GitLab Projects

Self-hosted infrastructure and private development.

{gitlabRepos.length > 0 ? ( ) : (
No public GitLab repositories found or API is restricted.
)}
{/* 4. GitHub Repositories Section */}

Public Repositories

{/* 5. Hosted Websites Section */}

Hosted Websites

{/* Changed from Flex to Grid for perfect centering! */}
); }