import { graphql } from "@octokit/graphql"; import commaNumber from "comma-number"; import { GitForkIcon, StarIcon } from "lucide-react"; import PageTitle from "../../components/PageTitle"; import Link from "../../components/Link"; import RelativeTime from "../../components/RelativeTime"; import { addMetadata } from "../../lib/helpers/metadata"; import * as config from "../../lib/config"; import type { User, Repository } from "@octokit/graphql-schema"; import styles from "./page.module.css"; export const revalidate = 600; // 10 minutes export const metadata = addMetadata({ title: "Projects", description: `Most-starred repositories by @${config.authorSocial?.github} on GitHub`, alternates: { canonical: "/projects", }, }); type Project = { name: string; url: string; description?: string; language?: { name: string; color?: string; }; stars?: number; forks?: number; updatedAt: string; }; const getRepos = async (): Promise => { // don't fail the entire site build if the required API key for this page is missing if (!process.env.GITHUB_TOKEN) { console.warn(`ERROR: I can't fetch any GitHub projects without "GITHUB_TOKEN" set! Skipping for now...`); return null; } // https://docs.github.com/en/graphql/reference/objects#repository const { user } = await graphql<{ user: User }>( ` query ($username: String!, $sort: RepositoryOrderField!, $limit: Int) { user(login: $username) { repositories( first: $limit isLocked: false isFork: false ownerAffiliations: OWNER privacy: PUBLIC orderBy: { field: $sort, direction: DESC } ) { edges { node { name url description pushedAt stargazerCount forkCount primaryLanguage { name color } } } } } } `, { username: config.authorSocial.github, sort: "STARGAZERS", limit: 12, headers: { accept: "application/vnd.github.v3+json", authorization: `token ${process.env.GITHUB_TOKEN}`, }, } ); const results = user.repositories.edges as Array<{ node: Repository }>; const repos = results.map(({ node: repo }) => ({ name: repo.name, url: repo.url, description: repo.description as string, updatedAt: repo.pushedAt, stars: repo.stargazerCount, forks: repo.forkCount, language: repo.primaryLanguage as Project["language"], })); return repos; }; const Page = async () => { const repos = await getRepos(); return ( <> Projects
{repos?.map((repo) => (
{repo.name} {repo.description &&

{repo.description}

}
{repo.language && (
{repo.language.color && ( )} {repo.language.name}
)} {repo.stars && repo.stars > 0 && (
{commaNumber(repo.stars)}
)} {repo.forks && repo.forks > 0 && (
{commaNumber(repo.forks)}
)} {/* only use relative "time ago" on client side, since it'll be outdated via SSG and cause hydration errors */}
))}

View more on{" "} {" "} GitHub...

); }; export default Page;