-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcourse-projects.ts
More file actions
88 lines (83 loc) · 2.53 KB
/
Copy pathcourse-projects.ts
File metadata and controls
88 lines (83 loc) · 2.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { cache } from "react";
export type CourseProjectEntry = {
id: string;
href: string;
title: string;
institution?: string;
grade?: string;
summary: string;
tags: string[];
external?: boolean;
hintLabel?: string;
/** GitHub repo backing this entry — About/Topics/stars are fetched live */
repo?: string;
/** Live star count merged in by getCourseProjects */
stars?: number;
};
/**
* Course projects shown on /proj. For GitHub-backed entries the
* summary, tags, and stars mirror the repo's About, Topics, and star count —
* fetched live; the values below are fallbacks kept in sync by hand.
*/
export const COURSE_PROJECTS: CourseProjectEntry[] = [
{
id: "kai-course-notes",
href: "https://kai-course-notes.kaichen.dev",
title: "Kai Course Notes",
summary:
"Course notes & materials — handwritten & LaTeX notes, homework, and projects. Web-native notes on the Notion branch.",
tags: [
"computer-science",
"course-notes",
"coursework",
"latex",
"lecture-notes",
"mathematics",
"oxford",
"statistics",
"study-notes",
"sustech",
"uc-berkeley",
],
external: true,
hintLabel: "kai-course-notes.kaichen.dev",
repo: "kaiiiichen/Kai-Course-Notes",
},
];
const REVALIDATE_SECONDS = 120;
/**
* COURSE_PROJECTS with the GitHub-backed fields (About → summary,
* Topics → tags, stars) merged in live — same cadence as personal projects.
*/
export const getCourseProjects = cache(async function getCourseProjects(): Promise<
CourseProjectEntry[]
> {
const token = process.env.GITHUB_TOKEN;
return Promise.all(
COURSE_PROJECTS.map(async (entry) => {
if (!entry.repo) return entry;
try {
const res = await fetch(`https://api.github.com/repos/${entry.repo}`, {
headers: token ? { Authorization: `Bearer ${token}` } : undefined,
next: { revalidate: REVALIDATE_SECONDS, tags: ["github-stars"] },
});
if (!res.ok) return entry;
const json: {
description?: string | null;
topics?: string[];
stargazers_count?: number;
} = await res.json();
return {
...entry,
// GitHub data takes priority; fallback only if null/undefined
summary: json.description ?? entry.summary,
tags: json.topics ?? entry.tags,
stars:
typeof json.stargazers_count === "number" ? json.stargazers_count : entry.stars,
};
} catch {
return entry;
}
})
);
});