1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2025-09-18 13:25:32 -04:00

Migrate to app router (#2254)

This commit is contained in:
2025-02-07 11:33:38 -05:00
committed by GitHub
parent e97613dda5
commit 8aabb4a66f
179 changed files with 4095 additions and 4951 deletions

View File

@@ -0,0 +1,86 @@
.grid {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
align-items: flex-start;
width: 100%;
line-height: 1.1;
}
.card {
flex-grow: 1;
margin: 0.6em;
width: 370px;
padding: 1.2em 1.2em 0.8em 1.2em;
border: 1px solid var(--colors-kindaLight);
border-radius: var(--radii-corner);
font-size: 0.85em;
color: var(--colors-mediumDark);
transition: border var(--transitions-fade);
}
.card .name {
font-size: 1.2em;
font-weight: 600;
}
.card .description {
margin-top: 0.7em;
margin-bottom: 0.5em;
line-height: 1.7;
}
.card .meta {
display: flex;
flex-wrap: wrap;
align-items: baseline;
}
.card .metaItem {
margin-right: 1.5em;
line-height: 2;
color: var(--colors-medium);
}
.card .metaLink {
color: inherit !important;
}
.card .metaLink:hover,
.card .metaLink:focus-visible {
color: var(--colors-link) !important;
}
.card .metaIcon {
display: inline;
width: 16px;
height: 16px;
vertical-align: -0.3em;
margin-right: 0.5em;
stroke-width: 0.75;
}
.card .metaLanguage {
display: inline-block;
position: relative;
width: 1.15em;
height: 1.15em;
margin-right: 0.5em;
border-radius: 50%;
vertical-align: text-top;
}
.viewMore {
text-align: center;
margin-bottom: 0;
font-weight: 500px;
}
.githubIcon {
display: inline;
width: 1.2em;
height: 1.2em;
vertical-align: -0.2em;
margin: 0 0.15em;
fill: var(--colors-text);
}

175
app/projects/page.tsx Normal file
View File

@@ -0,0 +1,175 @@
import { graphql } from "@octokit/graphql";
import Content from "../../components/Content";
import PageTitle from "../../components/PageTitle";
import Link from "../../components/Link";
import RelativeTime from "../../components/RelativeTime";
import commaNumber from "comma-number";
import config from "../../lib/config";
import { metadata as defaultMetadata } from "../layout";
import { GoStar, GoRepoForked } from "react-icons/go";
import { SiGithub } from "react-icons/si";
import type { Metadata } from "next";
import type { User, Repository } from "@octokit/graphql-schema";
import type { Project } from "../../types";
import styles from "./page.module.css";
export const revalidate = 600; // 10 minutes
export const metadata: Metadata = {
title: "Projects",
openGraph: {
...defaultMetadata.openGraph,
title: "Projects",
url: "/projects",
},
alternates: {
...defaultMetadata.alternates,
canonical: "/projects",
},
};
async function getRepos(): Promise<Project[] | null> {
// don't fail the entire site build if the required API key for this page is missing
if (!process.env.GH_PUBLIC_TOKEN || process.env.GH_PUBLIC_TOKEN === "") {
console.warn(`ERROR: I can't fetch any GitHub projects without "GH_PUBLIC_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.GH_PUBLIC_TOKEN}`,
},
}
);
const results = user.repositories.edges as Array<{ node: Repository }>;
const repos = results.map<Project>(({ 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;
}
export default async function Page() {
const repos = await getRepos();
return (
<>
<PageTitle>💾 Projects</PageTitle>
<Content>
<div className={styles.grid}>
{repos?.map((repo) => (
<div key={repo.name} className={styles.card}>
<Link
// @ts-ignore
href={repo.url}
className={styles.name}
>
{repo.name}
</Link>
{repo.description && <p className={styles.description}>{repo.description}</p>}
<div className={styles.meta}>
{repo.language && (
<div className={styles.metaItem}>
{repo.language.color && (
<span className={styles.metaLanguage} style={{ backgroundColor: repo.language.color }} />
)}
{repo.language.name}
</div>
)}
{repo.stars && repo.stars > 0 && (
<div className={styles.metaItem}>
<Link
// @ts-ignore
href={`${repo.url}/stargazers`}
title={`${commaNumber(repo.stars)} ${repo.stars === 1 ? "star" : "stars"}`}
underline={false}
className={styles.metaLink}
>
<GoStar className={styles.metaIcon} />
{commaNumber(repo.stars)}
</Link>
</div>
)}
{repo.forks && repo.forks > 0 && (
<div className={styles.metaItem}>
<Link
// @ts-ignore
href={`${repo.url}/network/members`}
title={`${commaNumber(repo.forks)} ${repo.forks === 1 ? "fork" : "forks"}`}
underline={false}
className={styles.metaLink}
>
<GoRepoForked className={styles.metaIcon} />
{commaNumber(repo.forks)}
</Link>
</div>
)}
{/* only use relative "time ago" on client side, since it'll be outdated via SSG and cause hydration errors */}
<div className={styles.metaItem}>
<RelativeTime date={repo.updatedAt} verb="Updated" staticFormat="MMM D, YYYY" />
</div>
</div>
</div>
))}
</div>
<p className={styles.viewMore}>
<Link href={`https://github.com/${config.authorSocial.github}`}>
View more on <SiGithub className={styles.githubIcon} /> GitHub...
</Link>
</p>
</Content>
</>
);
}