import { env } from "../../lib/env"; import { notFound } from "next/navigation"; import { graphql } from "@octokit/graphql"; 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 } from "@octokit/graphql-schema"; import styles from "./page.module.css"; export const metadata = addMetadata({ title: "Projects", description: `Most-starred repositories by @${config.authorSocial?.github} on GitHub`, alternates: { canonical: "/projects", }, }); const getRepos = async () => { // don't fail the entire site build if the required API key for this page is missing if (!env.GITHUB_TOKEN) { console.warn(`ERROR: I can't fetch any GitHub projects without "GITHUB_TOKEN" set! Disabling projects page.`); // just return a 404 since this page would be blank anyways notFound(); } // 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 ${env.GITHUB_TOKEN}`, }, request: { // override fetch() to use next's extension to cache the response // https://nextjs.org/docs/app/api-reference/functions/fetch#fetchurl-options fetch: (url: string | URL | Request, options?: RequestInit) => { return fetch(url, { ...options, cache: "force-cache", next: { revalidate: 600, // 10 minutes tags: ["github-api"], }, }); }, }, } ); return user.repositories.edges?.map((edge) => edge!.node); }; const Page = async () => { const repos = await getRepos(); return ( <> Projects
{repos?.map((repo) => (
{repo!.name} {repo!.description &&

{repo!.description}

}
{repo!.primaryLanguage && (
{repo!.primaryLanguage.color && ( )} {repo!.primaryLanguage.name}
)} {repo!.stargazerCount > 0 && (
{Intl.NumberFormat(env.NEXT_PUBLIC_SITE_LOCALE).format(repo!.stargazerCount)}
)} {repo!.forkCount > 0 && (
{Intl.NumberFormat(env.NEXT_PUBLIC_SITE_LOCALE).format(repo!.forkCount)}
)}
Updated
))}

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

); }; export default Page;