Compare commits
2 Commits
16cc67c415
...
107c60e592
Author | SHA1 | Date |
---|---|---|
Hammy | 107c60e592 | 4 weeks ago |
Hammy | fa20f1c6a6 | 4 weeks ago |
@ -1,3 +1,7 @@
|
|||||||
|
compressionLevel: mixed
|
||||||
|
|
||||||
|
enableGlobalCache: false
|
||||||
|
|
||||||
nodeLinker: node-modules
|
nodeLinker: node-modules
|
||||||
|
|
||||||
yarnPath: .yarn/releases/yarn-3.6.1.cjs
|
yarnPath: .yarn/releases/yarn-4.5.1.cjs
|
||||||
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 63 KiB |
@ -1,27 +0,0 @@
|
|||||||
import { FancyUnderline, GroupedText, Text } from "./utils/Text";
|
|
||||||
|
|
||||||
export const About = () => {
|
|
||||||
return (
|
|
||||||
<GroupedText className="text-center">
|
|
||||||
<Text>
|
|
||||||
I am a{" "}
|
|
||||||
<FancyUnderline className="font-semibold" decoration="decoration-green">
|
|
||||||
software engineer
|
|
||||||
</FancyUnderline>{" "}
|
|
||||||
at the BBC and a{" "}
|
|
||||||
<FancyUnderline className="font-semibold" decoration="decoration-red">student</FancyUnderline>,
|
|
||||||
currently pursuing a BSc in Software Engineering at the University of
|
|
||||||
Glasgow.
|
|
||||||
</Text>
|
|
||||||
<Text>
|
|
||||||
You'll usually find me nerding out about technology and playing
|
|
||||||
video games. I also really enjoy contributing to open source projects,
|
|
||||||
mainly{" "}
|
|
||||||
<FancyUnderline className="font-semibold" decoration="decoration-peach">
|
|
||||||
Catppuccin
|
|
||||||
</FancyUnderline>
|
|
||||||
.
|
|
||||||
</Text>
|
|
||||||
</GroupedText>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,14 +1,13 @@
|
|||||||
import { Wave } from "./icons/Wave";
|
import { Wave } from "./icons/Wave";
|
||||||
import { H1 } from "./utils/Titles";
|
|
||||||
|
|
||||||
export const Header = () => {
|
export const Header = () => {
|
||||||
return (
|
return (
|
||||||
<H1>
|
<h1 className="text-2xl lg:text-3xl xl:text-4xl 2xl:text-5xl font-bold tracking-tight text-center">
|
||||||
Hiya{" "}
|
Hiya{" "}
|
||||||
<div className="inline-block motion-safe:animate-waving-hand">
|
<div className="inline-block motion-safe:animate-waving-hand">
|
||||||
<Wave />
|
<Wave />
|
||||||
</div>
|
</div>
|
||||||
, I'm Goudham
|
, I'm Goudham
|
||||||
</H1>
|
</h1>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
import { fetchUserRepositories } from "@/app/lib/api";
|
|
||||||
import { Star } from "./icons/Star";
|
|
||||||
import Link from "next/link";
|
|
||||||
import { H2 } from "./utils/Titles";
|
|
||||||
import { ExternalLink } from "./icons/ExternalLink";
|
|
||||||
import { Archived } from "./icons/Archived";
|
|
||||||
|
|
||||||
export const Projects = async () => {
|
|
||||||
const projects = await fetchUserRepositories().then((res) =>
|
|
||||||
res
|
|
||||||
.filter(
|
|
||||||
(data) =>
|
|
||||||
!data.fork &&
|
|
||||||
data.name !== "uwuifyy" &&
|
|
||||||
data.name !== "Enso-Bot" &&
|
|
||||||
!data.archived
|
|
||||||
)
|
|
||||||
.sort((a, b) => (b.stargazers_count ?? 0) - (a.stargazers_count ?? 0))
|
|
||||||
.slice(0, 6)
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section className="flex flex-col items-center space-y-3 px-5">
|
|
||||||
<H2>Favourite Projects</H2>
|
|
||||||
<div className="rounded-lg text-md lg:text-lg xl:text-xl">
|
|
||||||
<div className="flex flex-col space-y-4">
|
|
||||||
{projects.map((project) => (
|
|
||||||
<Project key={project.name} project={project} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Project = ({ project }: { project: RepositoryData }) => {
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
href={project.html_url}
|
|
||||||
className="bg-base w-full rounded-xl outline-2 outline-mantle focus:ring-2 focus:ring-blue ring-offset-0 shadow-lg hover:scale-105 motion-safe:duration-300 p-3"
|
|
||||||
>
|
|
||||||
<div className="flex flex-col space-y-1 h-full justify-between">
|
|
||||||
<div>
|
|
||||||
<span className="font-semibold hover:underline">
|
|
||||||
{project.name} 
|
|
||||||
<ExternalLink />
|
|
||||||
</span>
|
|
||||||
{project.description && (
|
|
||||||
<div className="text-sm lg:text-md xl:text-lg text-subtext1">
|
|
||||||
{project.description}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="self-end flex flex-row gap-x-1">
|
|
||||||
{project.archived && (
|
|
||||||
<p className="text-md font-medium bg-mantle rounded-xl px-3">
|
|
||||||
<Archived />
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
<p className="text-md font-medium bg-mantle rounded-xl px-3">
|
|
||||||
{project.stargazers_count} <Star />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,13 +0,0 @@
|
|||||||
export const Archived = () => {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
className="h-5 w-5 xl:h-6 xl:w-6 inline align-text-bottom fill-yellow"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="32"
|
|
||||||
height="32"
|
|
||||||
viewBox="0 0 256 256"
|
|
||||||
>
|
|
||||||
<path d="M224,48H32A16,16,0,0,0,16,64V88a16,16,0,0,0,16,16v88a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V104a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48ZM208,192H48V104H208ZM224,88H32V64H224V88ZM96,136a8,8,0,0,1,8-8h48a8,8,0,0,1,0,16H104A8,8,0,0,1,96,136Z"></path>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,13 +0,0 @@
|
|||||||
export const Close = () => {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
className="h-8 w-8 fill-overlay0 group-hover:bg-subtext1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="32"
|
|
||||||
height="32"
|
|
||||||
viewBox="0 0 256 256"
|
|
||||||
>
|
|
||||||
<path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,13 +0,0 @@
|
|||||||
export const ExternalLink = () => {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
className="h-4 w-4 inline-block align-text-top fill-text opacity-50"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="32"
|
|
||||||
height="32"
|
|
||||||
viewBox="0 0 256 256"
|
|
||||||
>
|
|
||||||
<path d="M224,104a8,8,0,0,1-16,0V59.32l-66.33,66.34a8,8,0,0,1-11.32-11.32L196.68,48H152a8,8,0,0,1,0-16h64a8,8,0,0,1,8,8Zm-40,24a8,8,0,0,0-8,8v72H48V80h72a8,8,0,0,0,0-16H48A16,16,0,0,0,32,80V208a16,16,0,0,0,16,16H176a16,16,0,0,0,16-16V136A8,8,0,0,0,184,128Z"></path>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,18 +0,0 @@
|
|||||||
export const Heart = () => {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
className="h-5 w-5 lg:h-6 lg:w-6 xl:h-7 xl:w-7 inline-block align-text-bottom"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 256 256"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M128,216S24,160,24,94A54,54,0,0,1,78,40c22.59,0,41.94,12.31,50,32,8.06-19.69,27.41-32,50-32a54,54,0,0,1,54,54C232,160,128,216,128,216Z"
|
|
||||||
fill="red"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth="0"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,19 +0,0 @@
|
|||||||
export const Star = () => {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
className="h-5 w-5 xl:h-6 xl:w-6 inline align-text-bottom"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 256 256"
|
|
||||||
>
|
|
||||||
<rect width="256" height="256" fill="none" />
|
|
||||||
<path
|
|
||||||
d="M135.34,28.9l23.23,55.36a8,8,0,0,0,6.67,4.88l59.46,5.14a8,8,0,0,1,4.54,14.07L184.13,147.7a8.08,8.08,0,0,0-2.54,7.89l13.52,58.54a8,8,0,0,1-11.89,8.69l-51.1-31a7.93,7.93,0,0,0-8.24,0l-51.1,31a8,8,0,0,1-11.89-8.69l13.52-58.54a8.08,8.08,0,0,0-2.54-7.89L26.76,108.35A8,8,0,0,1,31.3,94.28l59.46-5.14a8,8,0,0,0,6.67-4.88L120.66,28.9A8,8,0,0,1,135.34,28.9Z"
|
|
||||||
fill="orange"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth="0"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,9 +0,0 @@
|
|||||||
export const Hamburger = () => {
|
|
||||||
return (
|
|
||||||
<div className="space-y-2">
|
|
||||||
<span className="block w-8 h-0.5 bg-overlay0 group-hover:bg-subtext1"></span>
|
|
||||||
<span className="block w-8 h-0.5 bg-overlay0 group-hover:bg-subtext1"></span>
|
|
||||||
<span className="block w-8 h-0.5 bg-overlay0 group-hover:bg-subtext1"></span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,30 +0,0 @@
|
|||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
export const Links = () => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<LinkWithAnimatedUnderline href="/" text="< Home />" />
|
|
||||||
<LinkWithAnimatedUnderline href="/projects" text="< Projects />" />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const LinkWithAnimatedUnderline = ({
|
|
||||||
href,
|
|
||||||
text,
|
|
||||||
}: {
|
|
||||||
href: string;
|
|
||||||
text: string;
|
|
||||||
}) => {
|
|
||||||
const animatedUnderline =
|
|
||||||
"md:block md:max-w-0 md:group-hover:max-w-full motion-safe:md:transition-all md:h-0.5 md:bg-blue motion-safe:md:duration-300";
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Link href={href} className="motion-safe:md:transition motion-safe:md:duration-300 group focus:text-blue">
|
|
||||||
<span className="group-hover:text-blue motion-safe:md:transition-all motion-safe:md:duration-300">
|
|
||||||
{text}
|
|
||||||
</span>
|
|
||||||
<span className={`${animatedUnderline}`}></span>
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,83 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { Dispatch, SetStateAction, useRef, useState } from "react";
|
|
||||||
import { ProfilePicture } from "../images/ProfilePicture";
|
|
||||||
import { Hamburger } from "./Hamburger";
|
|
||||||
import { Links } from "./Links";
|
|
||||||
import { Close } from "../icons/Close";
|
|
||||||
import Link from "next/link";
|
|
||||||
import { Dialog } from "@headlessui/react";
|
|
||||||
import { usePathname } from "next/navigation";
|
|
||||||
|
|
||||||
export const Navbar = () => {
|
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<nav className="self-center w-full max-w-xl lg:max-w-3xl xl:max-w-6xl">
|
|
||||||
<div className="p-4 flex flex-row items-center justify-between text-md lg:text-lg xl:text-xl">
|
|
||||||
<ProfilePicture />
|
|
||||||
<div className="hidden md:flex flex-row gap-x-4 font-bold tracking-tight">
|
|
||||||
<Links />
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
className="md:hidden px-4 py-2 hover:bg-crust dark:hover:bg-base rounded-lg"
|
|
||||||
aria-label="Open Menu"
|
|
||||||
onClick={() => setIsOpen((prev) => !prev)}
|
|
||||||
>
|
|
||||||
<Hamburger />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<MobileMenu isOpen={isOpen} setIsOpen={setIsOpen} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const MobileMenu = ({
|
|
||||||
isOpen,
|
|
||||||
setIsOpen,
|
|
||||||
}: {
|
|
||||||
isOpen: boolean;
|
|
||||||
setIsOpen: Dispatch<SetStateAction<boolean>>;
|
|
||||||
}) => {
|
|
||||||
const focusedRef = useRef(null);
|
|
||||||
const path = usePathname();
|
|
||||||
const checkPath = (href: string) => {
|
|
||||||
if (href === path) {
|
|
||||||
setIsOpen(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Dialog
|
|
||||||
className={
|
|
||||||
isOpen
|
|
||||||
? "block w-full h-screen absolute overflow-hidden inset-0 bg-base dark:bg-crust z-10 flex-col items-center"
|
|
||||||
: "hidden"
|
|
||||||
}
|
|
||||||
open={isOpen}
|
|
||||||
onClose={() => setIsOpen(false)}
|
|
||||||
>
|
|
||||||
<div className="max-w-xl mx-auto">
|
|
||||||
<div className="p-4 w-full flex flex-row items-center justify-between">
|
|
||||||
<ProfilePicture />
|
|
||||||
<button
|
|
||||||
className="px-4 py-1 hover:bg-crust dark:hover:bg-base rounded-lg focus:bg-crust dark:focus:bg-base"
|
|
||||||
onClick={() => setIsOpen((prev) => !prev)}
|
|
||||||
ref={focusedRef}
|
|
||||||
>
|
|
||||||
<Close />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<ul className="flex flex-col space-y-6 items-center text-2xl font-semibold justify-center">
|
|
||||||
<Link href="/" onClick={() => checkPath("/")}>
|
|
||||||
< Home />
|
|
||||||
</Link>
|
|
||||||
<Link href="/projects" onClick={() => checkPath("/projects")}>
|
|
||||||
< Projects />
|
|
||||||
</Link>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,16 +0,0 @@
|
|||||||
export const H1 = ({ children }: { children: React.ReactNode | string }) => {
|
|
||||||
return (
|
|
||||||
<h1 className="text-3xl lg:text-4xl xl:text-5xl font-bold tracking-tight text-center">
|
|
||||||
{children}
|
|
||||||
</h1>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const H2 = ({ children }: { children: React.ReactNode | string }) => {
|
|
||||||
return (
|
|
||||||
<h2 className="text-2xl lg:text-3xl xl:text-4xl font-bold">
|
|
||||||
{children}
|
|
||||||
</h2>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1000 B |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.1 KiB |
@ -1,36 +0,0 @@
|
|||||||
import { Octokit } from "octokit";
|
|
||||||
|
|
||||||
if (!process.env.REPOS_READ_ONLY) {
|
|
||||||
throw new Error("GITHUB TOKEN 'REPOS_READ_ONLY' is missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
const octokit = new Octokit({
|
|
||||||
auth: process.env.REPOS_READ_ONLY,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchUserRepositories = async (): Promise<RepositoryData[]> => {
|
|
||||||
return await octokit.paginate(
|
|
||||||
octokit.rest.repos.listForAuthenticatedUser,
|
|
||||||
{
|
|
||||||
per_page: 100,
|
|
||||||
visibility: "public",
|
|
||||||
affiliation: "owner",
|
|
||||||
},
|
|
||||||
(response) =>
|
|
||||||
response.data.map((data) => {
|
|
||||||
return {
|
|
||||||
name: data.name,
|
|
||||||
description: data.description,
|
|
||||||
html_url: data.html_url,
|
|
||||||
size: data.size,
|
|
||||||
archived: data.archived,
|
|
||||||
fork: data.fork,
|
|
||||||
stargazers_count: data.stargazers_count,
|
|
||||||
open_issues_count: data.open_issues,
|
|
||||||
created_at: data.created_at,
|
|
||||||
updated_at: data.updated_at,
|
|
||||||
topics: data.topics,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,13 +0,0 @@
|
|||||||
type RepositoryData = {
|
|
||||||
name: string;
|
|
||||||
description: string | null;
|
|
||||||
html_url: string;
|
|
||||||
size?: number;
|
|
||||||
archived?: boolean;
|
|
||||||
fork: boolean;
|
|
||||||
stargazers_count?: number;
|
|
||||||
open_issues_count?: number;
|
|
||||||
created_at: string | null | undefined;
|
|
||||||
updated_at: string | null | undefined;
|
|
||||||
topics?: string[];
|
|
||||||
};
|
|
@ -1,18 +1,49 @@
|
|||||||
import { Header } from "./components/Header";
|
import { Header } from "./components/Header";
|
||||||
import { About } from "./components/About";
|
import { StyledLink } from "./components/utils/StyledLink";
|
||||||
import { Projects } from "./components/Projects";
|
import { Text } from "./components/utils/Text";
|
||||||
import { Navbar } from "./components/nav/Navbar";
|
import { GroupedText, FancyUnderline } from "./components/utils/Text";
|
||||||
|
import { ProfilePicture } from "./components/images/ProfilePicture";
|
||||||
|
import { Footer } from "./components/Footer";
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
/* Inherits from the RootLayout */
|
<div className="flex flex-col gap-4">
|
||||||
<div className="flex flex-col">
|
<div className="self-center">
|
||||||
<Navbar />
|
<ProfilePicture />
|
||||||
<div className="self-center max-w-md lg:max-w-lg xl:max-w-xl flex flex-col space-y-10 grow">
|
</div>
|
||||||
|
<div className="self-center max-w-lg lg:max-w-xl xl:max-w-2xl flex flex-col space-y-10">
|
||||||
<Header />
|
<Header />
|
||||||
<About />
|
<GroupedText className="text-center">
|
||||||
<Projects />
|
<Text>
|
||||||
|
I am a{" "}
|
||||||
|
<FancyUnderline className="font-semibold" decoration="decoration-peach">
|
||||||
|
Software Engineer at the BBC
|
||||||
|
</FancyUnderline>.{" "}
|
||||||
|
I obtained my degree while working full-time, you can learn
|
||||||
|
more about that by visiting{" \""}
|
||||||
|
<StyledLink
|
||||||
|
href={"https://www.gla.ac.uk/schools/computing/undergraduate/graduateapprenticeships/"}>
|
||||||
|
Graduate Apprenticeships - University of Glasgow
|
||||||
|
</StyledLink>."
|
||||||
|
</Text>
|
||||||
|
<Text>
|
||||||
|
You'll usually find me nerding out about technology and playing
|
||||||
|
video games. Contributing to open-source is a big passion of mine and
|
||||||
|
I'm grateful to be a{" "}
|
||||||
|
<FancyUnderline className="font-semibold" decoration="decoration-peach">
|
||||||
|
Core Maintainer for Catppuccin
|
||||||
|
</FancyUnderline>
|
||||||
|
. When I'm not staring at a screen, I love taking my Canon EOS R50 out for a spin and capturing my friends and the world around me.
|
||||||
|
</Text>
|
||||||
|
<Text>
|
||||||
|
Eventually, I'd like to turn this website into a place where I can share my thoughts, projects, and photographs with everyone. Hopefully sometime soon<span className="text-blue font-bold">™</span>
|
||||||
|
</Text>
|
||||||
|
<Text>
|
||||||
|
<span className="text-red font-bold">~~~</span>
|
||||||
|
</Text>
|
||||||
|
</GroupedText>
|
||||||
</div>
|
</div>
|
||||||
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
import { Metadata } from "next";
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: "Projects by Goudham Suresh",
|
|
||||||
description:
|
|
||||||
"I am a software engineer by day, and an open source enthusiast by night. Welcome to my corner of the internet where I write about my experiences, projects, and more.",
|
|
||||||
openGraph: {
|
|
||||||
url: process.env.NEXT_PUBLIC_IS_PREVIEW
|
|
||||||
? "https://preview.goudham.com/projects"
|
|
||||||
: "https://goudham.com/projects",
|
|
||||||
title: `Projects by Goudham Suresh${
|
|
||||||
process.env.NEXT_PUBLIC_IS_PREVIEW ? " (Preview)" : ""
|
|
||||||
}`,
|
|
||||||
description:
|
|
||||||
"I am a software engineer by day, and an open source enthusiast by night. Welcome to my corner of the internet where I write about my experiences, projects, and more.",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function ProjectsLayout({
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
children: React.ReactNode;
|
|
||||||
}) {
|
|
||||||
return <section>{children}</section>;
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
import { fetchUserRepositories } from "../lib/api";
|
|
||||||
import { Project } from "../components/Projects";
|
|
||||||
import { Text } from "../components/utils/Text";
|
|
||||||
import { H1 } from "../components/utils/Titles";
|
|
||||||
import { Navbar } from "../components/nav/Navbar";
|
|
||||||
|
|
||||||
export default async function Projects() {
|
|
||||||
const projects = await fetchUserRepositories().then((res) =>
|
|
||||||
res
|
|
||||||
.filter((data) => !data.fork)
|
|
||||||
.sort((a, b) => (b.stargazers_count ?? 0) - (a.stargazers_count ?? 0))
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
/* Inherits from the RootLayout */
|
|
||||||
<div className="flex flex-col">
|
|
||||||
<Navbar />
|
|
||||||
<div className="self-center max-w-md lg:max-w-lg xl:max-w-xl 2xl:max-w-4xl flex flex-col space-y-10 grow">
|
|
||||||
<H1>All Projects</H1>
|
|
||||||
<div className="flex flex-col mx-3 gap-3 text-center">
|
|
||||||
<Text>
|
|
||||||
Here's a list of all my public projects, they are sorted by
|
|
||||||
most starred. Note that some projects are still under development
|
|
||||||
and/or unfinished, but I'd like to get around to finishing them
|
|
||||||
at some point in the future!
|
|
||||||
</Text>
|
|
||||||
<Text>
|
|
||||||
I promise I'll implement sorting options soon
|
|
||||||
<span className="text-blue font-bold">™</span>
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-1 2xl:grid-cols-2 gap-y-4 gap-x-6 px-5">
|
|
||||||
{projects.map((project) => (
|
|
||||||
<div
|
|
||||||
key={project.name}
|
|
||||||
className="rounded-lg text-md lg:text-lg xl:text-xl flex justify-center"
|
|
||||||
>
|
|
||||||
<Project key={project.name} project={project} />
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
Before Width: | Height: | Size: 282 KiB After Width: | Height: | Size: 246 KiB |