11---
22import Icon from ' astro-icon' ;
3+ import fs from ' fs' ;
4+ import path from ' path' ;
35
46interface Props {
57 repo: string ;
@@ -12,25 +14,87 @@ let name = 'Loading';
1214let description = ' Loading' ;
1315let starDisplay = ' Loading' ;
1416
17+ let populated = false ;
18+
19+ // Try to read pre-fetched local JSON produced by CI at src/data/repos.json
1520try {
16- const res = await fetch (` https://api.github.com/repos/pixeljellyfish/${repo } ` , {
17- headers: {
18- Authorization: ` token ${import .meta .env .GITHUB_TOKEN } `
21+ const dataUrl = new URL (' ../data/repos.json' , import .meta .url );
22+ const dataPath = dataUrl .pathname ;
23+ if (fs .existsSync (dataPath )) {
24+ const file = fs .readFileSync (dataPath , ' utf-8' );
25+ const list = JSON .parse (file );
26+ const entry = Array .isArray (list ) ? list .find (e => {
27+ // match by repo name or full_name
28+ if (! e ) return false ;
29+ if (e .name === repo ) return true ;
30+ if (typeof e .full_name === ' string' && e .full_name .endsWith (` /${repo } ` )) return true ;
31+ return false ;
32+ }) : null ;
33+
34+ if (entry ) {
35+ name = entry .name || ' Unnamed Repo' ;
36+ description = entry .description || ' No description available' ;
37+ starDisplay = entry .stargazers_count === 0 ? ' No stars yet' : entry .stargazers_count ;
38+ populated = true ;
1939 }
20- });
21- if (! res .ok ) throw new Error (` HTTP error! status: ${res .status } ` );
22- const data = await res .json ();
23- name = data .name || ' Unnamed Repo' ;
24- description = data .description || ' No description available' ;
25- starDisplay = data .stargazers_count === 0 ? ' No stars yet' : data .stargazers_count ;
26- } catch (error ) {
27- console .error (` Failed to fetch repo ${repo } at build time: ` , error );
28- name = ' Error' ;
29- description = ' Could not load repository data' ;
30- starDisplay = ' N/A' ;
40+ }
41+ } catch (err ) {
42+ // silently continue to network fetch if local data is missing or invalid
43+ console .warn (' ProjectCard: local repo JSON not available or invalid:' , err );
3144}
32- ---
3345
46+ if (! populated ) {
47+ try {
48+ const url = ` https://api.github.com/repos/pixeljellyfish/${repo } ` ;
49+ const token = import .meta .env .GITHUB_TOKEN ;
50+ let res;
51+
52+ // If we have a token, try authenticated first (better rate limits), otherwise unauthenticated.
53+ if (token ) {
54+ res = await fetch (url , { headers: { Authorization: ` token ${token } ` } });
55+ // If auth fails (401/403) or rate-limited, try unauthenticated fallback:
56+ if (! res .ok && (res .status === 401 || res .status === 403 || res .status === 429 )) {
57+ const fallbackRes = await fetch (url );
58+ if (fallbackRes .ok ) {
59+ const fallbackData = await fallbackRes .json ();
60+ name = fallbackData .name || ' Unnamed Repo' ;
61+ description = fallbackData .description || ' No description available' ;
62+ starDisplay = fallbackData .stargazers_count === 0 ? ' No stars yet' : fallbackData .stargazers_count ;
63+ } else {
64+ throw new Error (` GitHub fetch failed (auth then fallback). Statuses: ${res .status }, ${fallbackRes .status } ` );
65+ }
66+ } else if (! res .ok ) {
67+ throw new Error (` GitHub fetch failed: ${res .status } ${res .statusText } ` );
68+ } else {
69+ const data = await res .json ();
70+ name = data .name || ' Unnamed Repo' ;
71+ description = data .description || ' No description available' ;
72+ starDisplay = data .stargazers_count === 0 ? ' No stars yet' : data .stargazers_count ;
73+ }
74+ } else {
75+ // No token: do a single unauthenticated fetch and handle common failure statuses gracefully
76+ res = await fetch (url );
77+ if (! res .ok ) {
78+ // if rate-limited or forbidden, show a friendly fallback instead of crashing
79+ console .warn (` GitHub unauthenticated fetch failed for ${repo }: ` , res .status , res .statusText );
80+ name = ' Unavailable' ;
81+ description = ' Repository data temporarily unavailable' ;
82+ starDisplay = ' N/A' ;
83+ } else {
84+ const data = await res .json ();
85+ name = data .name || ' Unnamed Repo' ;
86+ description = data .description || ' No description available' ;
87+ starDisplay = data .stargazers_count === 0 ? ' No stars yet' : data .stargazers_count ;
88+ }
89+ }
90+ } catch (error ) {
91+ console .error (` Failed to fetch repo ${repo } at build time: ` , error );
92+ name = ' Error' ;
93+ description = ' Could not load repository data' ;
94+ starDisplay = ' N/A' ;
95+ }
96+ }
97+ ---
3498<a
3599 href ={ ` https://github.com/pixeljellyfish/${repo } ` }
36100 rel =" noopener noreferrer"
0 commit comments