diff --git a/package.json b/package.json
index 8b5870a..74466d2 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "atridotdad",
"type": "module",
- "version": "4.0.0",
+ "version": "4.1.0",
"scripts": {
"dev": "astro dev",
"build": "astro build",
diff --git a/src/components/ProjectsIsland.astro b/src/components/ProjectsIsland.astro
deleted file mode 100644
index faa1b71..0000000
--- a/src/components/ProjectsIsland.astro
+++ /dev/null
@@ -1,144 +0,0 @@
----
-import { Icon } from "astro-icon/components";
-import { config } from "../config";
-import { fetchGiteaInfoFromUrl, formatRelativeTime } from "../utils/gitea";
-import type { Project } from "../types";
-
-Astro.response.headers.set(
- "Cache-Control",
- "public, max-age=300, s-maxage=300, stale-while-revalidate=60",
-);
-
-function isGiteaDomain(url: string): boolean {
- if (!config.siteConfig.giteaDomains) return true;
- try {
- const urlObj = new URL(url);
- return config.siteConfig.giteaDomains.some(
- (domain) => urlObj.origin === new URL(domain).origin,
- );
- } catch {
- return false;
- }
-}
-
-const projectsWithGiteaInfo = await Promise.all(
- config.projects.map(async (project) => {
- if (
- project.gitLink &&
- !project.giteaInfo &&
- isGiteaDomain(project.gitLink)
- ) {
- const giteaInfo = await fetchGiteaInfoFromUrl(project.gitLink);
- if (giteaInfo) {
- return { ...project, giteaInfo } as Project;
- }
- }
- return project;
- }),
-);
-
-const sortedProjects = projectsWithGiteaInfo.sort((a, b) => {
- const aTime = a.giteaInfo?.updatedAt
- ? new Date(a.giteaInfo.updatedAt).getTime()
- : 0;
- const bTime = b.giteaInfo?.updatedAt
- ? new Date(b.giteaInfo.updatedAt).getTime()
- : 0;
- return bTime - aTime;
-});
----
-
-
- {
- sortedProjects.map((project) => (
- -
- {/* Project icon/avatar */}
-
-
- {/* Main content */}
-
-
-
{project.name}
- {project.giteaInfo?.updatedAt && (
-
- {formatRelativeTime(project.giteaInfo.updatedAt)}
-
- )}
-
-
-
{project.description}
-
- {/* Languages & Topics */}
-
- {project.giteaInfo?.languages?.slice(0, 3).map((lang: string) => (
- {lang}
- ))}
- {project.giteaInfo?.topics?.slice(0, 4).map((topic: string) => (
- {topic}
- ))}
-
-
-
- {/* Action buttons */}
-
- {project.webLink && (
-
-
-
- )}
- {project.gitLink && (
-
-
-
- )}
- {project.iosLink && (
-
-
-
- )}
- {project.androidLink && (
-
-
-
- )}
-
-
- ))
- }
-
-
-{
- sortedProjects.length === 0 && (
-
- No projects available yet. Check back soon!
-
- )
-}
diff --git a/src/components/ProjectsLoader.astro b/src/components/ProjectsLoader.astro
deleted file mode 100644
index fd8844c..0000000
--- a/src/components/ProjectsLoader.astro
+++ /dev/null
@@ -1,7 +0,0 @@
----
-
----
-
-
-
-
diff --git a/src/config.ts b/src/config.ts
index e963ef2..3b8cc6e 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -206,6 +206,7 @@ export const config: Config = {
id: "atrodotdad",
name: "Personal Site",
description: "My personal website built with Astro.",
+ webLink: "https://atri.dad",
gitLink: "https://git.atri.dad/atridad/atridotdad",
},
],
diff --git a/src/pages/projects.astro b/src/pages/projects.astro
index c21cb0e..fab24fe 100644
--- a/src/pages/projects.astro
+++ b/src/pages/projects.astro
@@ -1,21 +1,189 @@
---
import Layout from "../layouts/Layout.astro";
-import ProjectsIsland from "../components/ProjectsIsland.astro";
-import ProjectsLoader from "../components/ProjectsLoader.astro";
+import { Icon } from "astro-icon/components";
+import { config } from "../config";
+import { fetchGiteaInfoFromUrl, formatRelativeTime } from "../utils/gitea";
+import type { Project } from "../types";
export const prerender = false;
+
+Astro.response.headers.set(
+ "Cache-Control",
+ "public, max-age=300, s-maxage=300, stale-while-revalidate=60",
+);
+
+function isGiteaDomain(url: string): boolean {
+ if (!config.siteConfig.giteaDomains) return true;
+ try {
+ const urlObj = new URL(url);
+ return config.siteConfig.giteaDomains.some(
+ (domain) => urlObj.origin === new URL(domain).origin,
+ );
+ } catch {
+ return false;
+ }
+}
+
+const projectsWithGiteaInfo = await Promise.all(
+ config.projects.map(async (project) => {
+ if (
+ project.gitLink &&
+ !project.giteaInfo &&
+ isGiteaDomain(project.gitLink)
+ ) {
+ const giteaInfo = await fetchGiteaInfoFromUrl(project.gitLink);
+ if (giteaInfo) {
+ return { ...project, giteaInfo } as Project;
+ }
+ }
+ return project;
+ }),
+);
+
+const sortedProjects = projectsWithGiteaInfo.sort((a, b) => {
+ const aTime = a.giteaInfo?.updatedAt
+ ? new Date(a.giteaInfo.updatedAt).getTime()
+ : 0;
+ const bTime = b.giteaInfo?.updatedAt
+ ? new Date(b.giteaInfo.updatedAt).getTime()
+ : 0;
+ return bTime - aTime;
+});
---
-
+
Projects
-
-
-
+
+ {
+ sortedProjects.map((project) => (
+ -
+ {/* Project icon/avatar */}
+
+ {project.giteaInfo?.avatarUrl ? (
+

+ ) : (
+
+
+
+ )}
+
+
+ {/* Main content */}
+
+
+
+ {project.name}
+
+ {project.giteaInfo?.updatedAt && (
+
+ {formatRelativeTime(
+ project.giteaInfo.updatedAt,
+ )}
+
+ )}
+
+
+
+ {project.description}
+
+
+ {/* Languages & Topics */}
+
+ {project.giteaInfo?.languages
+ ?.slice(0, 3)
+ .map((lang: string) => (
+
+ {lang}
+
+ ))}
+ {project.giteaInfo?.topics
+ ?.slice(0, 4)
+ .map((topic: string) => (
+
+ {topic}
+
+ ))}
+
+
+
+ {/* Action buttons */}
+
+ {project.webLink && (
+
+
+
+ )}
+ {project.gitLink && (
+
+
+
+ )}
+ {project.iosLink && (
+
+
+
+ )}
+ {project.androidLink && (
+
+
+
+ )}
+
+
+ ))
+ }
+
+ {
+ sortedProjects.length === 0 && (
+
+ No projects available yet. Check back soon!
+
+ )
+ }
diff --git a/src/utils/gitea.ts b/src/utils/gitea.ts
index 9b0c1ca..b3d679e 100644
--- a/src/utils/gitea.ts
+++ b/src/utils/gitea.ts
@@ -4,6 +4,7 @@ export interface GiteaRepoInfo {
size: number;
defaultBranch: string;
topics: string[];
+ avatarUrl?: string;
}
export interface GiteaConfig {
@@ -74,6 +75,7 @@ export async function fetchGiteaRepoInfo(
size: data.size || 0,
defaultBranch: data.default_branch || "main",
topics: Array.isArray(data.topics) ? data.topics : [],
+ avatarUrl: data.avatar_url,
};
} catch (error) {
return null;