Initial Website

main
Carsten Kragelund 2023-05-19 14:04:12 +02:00
parent a7f1c4c1ef
commit d30c4015a7
Signed by: nyx
GPG Key ID: CADDADEEC9F753C0
9 changed files with 714 additions and 112 deletions

@ -1,4 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {}
const nextConfig = {
output: "export",
};
module.exports = nextConfig
module.exports = nextConfig;

62
package-lock.json generated

@ -8,17 +8,20 @@
"name": "portfolio",
"version": "0.1.0",
"dependencies": {
"@tanstack/react-query": "^4.29.5",
"@types/node": "20.1.4",
"@types/react": "18.2.6",
"@types/react-dom": "18.2.4",
"autoprefixer": "10.4.14",
"eslint": "8.40.0",
"eslint-config-next": "13.4.2",
"moment": "^2.29.4",
"next": "13.4.2",
"postcss": "8.4.23",
"react": "18.2.0",
"react-dom": "18.2.0",
"tailwindcss": "3.3.2",
"tailwindcss-animate": "^1.0.5",
"typescript": "5.0.4"
}
},
@ -386,6 +389,41 @@
"tslib": "^2.4.0"
}
},
"node_modules/@tanstack/query-core": {
"version": "4.29.5",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.29.5.tgz",
"integrity": "sha512-xXIiyQ/4r9KfaJ3k6kejqcaqFXXBTzN2aOJ5H1J6aTJE9hl/nbgAdfF6oiIu0CD5xowejJEJ6bBg8TO7BN4NuQ==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/react-query": {
"version": "4.29.5",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.29.5.tgz",
"integrity": "sha512-F87cibC3s3eG0Q90g2O+hqntpCrudKFnR8P24qkH9uccEhXErnJxBC/AAI4cJRV2bfMO8IeGZQYf3WyYgmSg0w==",
"dependencies": {
"@tanstack/query-core": "4.29.5",
"use-sync-external-store": "^1.2.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-native": "*"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@ -2771,6 +2809,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/moment": {
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
"engines": {
"node": "*"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@ -3960,6 +4006,14 @@
"node": ">=14.0.0"
}
},
"node_modules/tailwindcss-animate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.5.tgz",
"integrity": "sha512-UU3qrOJ4lFQABY+MVADmBm+0KW3xZyhMdRvejwtXqYOL7YjHYxmuREFAZdmVG5LPe5E9CAst846SLC4j5I3dcw==",
"peerDependencies": {
"tailwindcss": ">=3.0.0 || insiders"
}
},
"node_modules/tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
@ -4160,6 +4214,14 @@
"punycode": "^2.1.0"
}
},
"node_modules/use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",

@ -9,17 +9,20 @@
"lint": "next lint"
},
"dependencies": {
"@tanstack/react-query": "^4.29.5",
"@types/node": "20.1.4",
"@types/react": "18.2.6",
"@types/react-dom": "18.2.4",
"autoprefixer": "10.4.14",
"eslint": "8.40.0",
"eslint-config-next": "13.4.2",
"moment": "^2.29.4",
"next": "13.4.2",
"postcss": "8.4.23",
"react": "18.2.0",
"react-dom": "18.2.0",
"tailwindcss": "3.3.2",
"tailwindcss-animate": "^1.0.5",
"typescript": "5.0.4"
}
}

@ -0,0 +1,6 @@
TODO: more equal ratio of content to card
TODO: apple tiles summary (figma community)
TODO: maybe bigger fonts
TODO: smaller gap
TODO: more opacity on glow, maybe just get rid of it
TODO: services in dot matrix (maybe color code for the legends)

@ -0,0 +1,13 @@
import { HTMLAttributes } from "react";
export const LinkBubble: React.FC<HTMLAttributes<HTMLDivElement> & { href: string }> = ({
className,
children,
href
}) => {
return (
<a className={`${className} rounded-full flex justify-center items-center`} href={href}>
{children}
</a>
);
};

@ -0,0 +1,18 @@
import { HTMLAttributes, ReactNode } from "react";
export const ShowcaseCard: React.FC<
HTMLAttributes<HTMLDivElement> & { bg: string; alt: string }
> = ({ className, children, bg, alt }) => {
return (
<div className={`${className} w-full h-full relative`}>
<div className="absolute bg-black-base/40 rounded-2xl p-12 flex justify-center backdrop-blur items-center w-full h-full flex-col gap-2">
{children}
</div>
<img
src={bg}
alt={alt}
className="rounded-2xl h-full w-full object-cover"
/>
</div>
);
};

@ -15,7 +15,9 @@ export default function RootLayout({
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<body className={inter.className}>
{children}
</body>
</html>
)
);
}

@ -1,113 +1,551 @@
import Image from 'next/image'
import React, { HTMLAttributes } from "react";
import { LinkBubble } from "./components/LinkBubble";
import { ShowcaseCard } from "./components/ShowcaseCard";
export default function Home() {
type Rows = [1, 2, 3, 4, 5, 6, 7, 8, 9][number];
type Columns = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13][number];
type OpacitySteps = [
0,
5,
10,
20,
25,
30,
40,
50,
60,
70,
75,
80,
90,
95,
100
][number];
type OpacityClass = `opacity-${OpacitySteps}` | "none";
export type CardContent<T = {}> = React.FC<
{ styles: string } & HTMLAttributes<HTMLSpanElement> & T
>;
type Card<T = any> = {
row: `row-start-${Rows} row-end-${Rows}`;
col: `col-start-${Columns} col-end-${Columns}`;
style?: string;
content: CardContent<T>;
};
function SimpleSpan(text: string): CardContent {
return function simpleSpan({ className, styles }) {
return <div className={`${className} ${styles}`}>{text}</div>;
};
}
function Glow(child: JSX.Element, opacity?: OpacityClass): CardContent {
return function glow({ className, styles }) {
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<div className="z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex">
<p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">
Get started by editing&nbsp;
<code className="font-mono font-bold">src/app/page.tsx</code>
</p>
<div className="fixed bottom-0 left-0 flex h-48 w-full items-end justify-center bg-gradient-to-t from-white via-white dark:from-black dark:via-black lg:static lg:h-auto lg:w-auto lg:bg-none">
<a
className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0"
href="https://vercel.com?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
By{' '}
<Image
src="/vercel.svg"
alt="Vercel Logo"
className="dark:invert"
width={100}
height={24}
priority
/>
</a>
</div>
<div className={`relative ${className}`}>
<div
className={`absolute -inset-2 ${styles} blur ${
opacity == "none" ? "" : opacity ?? "opacity-50"
}`}
></div>
<div className={`relative h-full ${styles}`}>{child}</div>
</div>
);
};
}
<div className="relative flex place-items-center before:absolute before:h-[300px] before:w-[480px] before:-translate-x-1/2 before:rounded-full before:bg-gradient-radial before:from-white before:to-transparent before:blur-2xl before:content-[''] after:absolute after:-z-20 after:h-[180px] after:w-[240px] after:translate-x-1/3 after:bg-gradient-conic after:from-sky-200 after:via-blue-200 after:blur-2xl after:content-[''] before:dark:bg-gradient-to-br before:dark:from-transparent before:dark:to-blue-700 before:dark:opacity-10 after:dark:from-sky-900 after:dark:via-[#0141ff] after:dark:opacity-40 before:lg:h-[360px]">
<Image
className="relative dark:drop-shadow-[0_0_0.3rem_#ffffff70] dark:invert"
src="/next.svg"
alt="Next.js Logo"
width={180}
height={37}
priority
/>
function infocard(
title: string,
binder: string,
subject: string,
subject_link: string
) {
return (
<div>
<span>{title}</span>
<br />
<span className="font-normal text-xl">
<span className="text-gray-800/30">{binder}</span>&nbsp;
<a className="underline" href={subject_link}>
{subject}
</a>
</span>
</div>
);
}
<div className="mb-32 grid text-center lg:mb-0 lg:grid-cols-4 lg:text-left">
<a
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
target="_blank"
rel="noopener noreferrer"
>
<h2 className={`mb-3 text-2xl font-semibold`}>
Docs{' '}
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
-&gt;
</span>
</h2>
<p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
Find in-depth information about Next.js features and API.
</p>
</a>
const aboutMe = `
<p class="my-2">Greetings! I'm Carsten. I'm a software engineer who loves diving deep into
whatever I end up hacking on. My language of choice is Rust, and I'm using Nix
to configure my system. My editors of choice are Emacs and CLion.</p>
<p class="my-2">At <a class="underline" href="https://catppuccin.com/">Catppuccin</a> I maintain the Emacs port.</p>
<p class="my-2">When I'm not coding, you can probably find me listening
to music, running or reading a book, paticularly nordic noir.</p>
`
.replaceAll("\n", " ")
.trim();
<a
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800 hover:dark:bg-opacity-30"
target="_blank"
rel="noopener noreferrer"
>
<h2 className={`mb-3 text-2xl font-semibold`}>
Learn{' '}
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
-&gt;
</span>
</h2>
<p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
Learn about Next.js in an interactive course with&nbsp;quizzes!
let cards: { [key: string]: Card | Card[] } = {
title: {
row: "row-start-1 row-end-3",
col: "col-start-1 col-end-7",
style: "text-6xl font-bold flex justify-center items-center",
content: SimpleSpan("TODO: Fill out with something witty"),
},
infocards: [
{
row: "row-start-3 row-end-6",
col: "col-start-1 col-end-3",
style:
"bg-gradient-to-r from-green-400 to-teal-400 dark:bg-emerald-700 flex justify-center items-center text-center font-bold text-2xl",
content: Glow(
infocard(
"Systems Engineer",
"@",
"MiR",
"https://mobile-industrial-robots.com/"
)
),
},
{
row: "row-start-3 row-end-6",
col: "col-start-3 col-end-5",
style:
"bg-gradient-to-r from-teal-400 to-cyan-400 dark:bg-emerald-700 flex justify-center items-center text-center font-bold text-2xl",
content: Glow(
infocard(
"Maintainer & Mod",
"@",
"Catppuccin",
"https://catppuccin.com/"
)
),
},
{
row: "row-start-3 row-end-6",
col: "col-start-5 col-end-7",
style:
"bg-gradient-to-r from-cyan-400 to-blue-400 dark:bg-emerald-700 flex justify-center items-center text-center font-bold text-2xl",
content: Glow(
infocard(
"Creator",
"of",
"Sanctureplicum Nix Config",
"https://gitea.pid1.sh/sanctureplicum/"
)
),
},
],
init_system: {
row: "row-start-1 row-end-6",
col: "col-start-7 col-end-10",
style: "flex flex-col justify-between",
content: ({ styles, className }) => {
return (
<div className={`${className} ${styles}`}>
<div className="flex flex-col gap-2">
<h1 className="font-bold text-3xl pb-2">
Services on the Init System
</h1>
<p>
🍵{" "}
<a className="underline" href="https://gitea.pid1.sh">
Gitea
</a>{" "}
</p>
<p>
🪄{" "}
<a className="line-through" href="#">
Hocus
</a>{" "}
🚧
</p>
<p>
{" "}
<a className="line-through" href="#">
Snip.sh
</a>{" "}
🚧
</p>
<p>
🍽{" "}
<a className="line-through" href="#">
Mealie
</a>{" "}
🚧
</p>
<p>
📄{" "}
<a className="line-through" href="#">
Stirling
</a>{" "}
🚧
</p>
<p>
👨🍳{" "}
<a className="underline" href="https://chef.pid1.sh">
CyberChef
</a>{" "}
</p>
<p>
👾{" "}
<a className="line-through" href="#">
EmulatorJS
</a>{" "}
🚧
</p>
<p>
🏠{" "}
<a className="underline" href="https://pid1.sh">
Homepage (This Page)
</a>{" "}
</p>
<p>
📜{" "}
<a className="line-through" href="#">
PSNR License
</a>{" "}
🚧
</p>
<p>
📷{" "}
<a className="line-through" href="#">
Immich
</a>{" "}
🛑
</p>
<p>
🎞{" "}
<a className="line-through" href="#">
Jellyfin
</a>{" "}
🛑
</p>
<p>
🖼{" "}
<a className="line-through" href="#">
Imgproxy
</a>{" "}
🚧
</p>
<p>
📦{" "}
<a className="line-through" href="#">
Minio
</a>{" "}
🛑
</p>
</div>
<div>
<h2 className="font-semibold text-lg">Glossary</h2>
<p>: Managed by Nix</p>
<p>🐳: Managed with Docker</p>
<p>🚧: Under Construction</p>
<p>🛑: Private Use Only</p>
</div>
</div>
);
},
},
name: {
row: "row-start-1 row-end-2",
col: "col-start-10 col-end-13",
style: "text-3xl font-semibold flex items-center",
content: SimpleSpan("Carsten Kragelund (NyxKrage)"),
},
commit: {
row: "row-start-2 row-end-5",
col: "col-start-10 col-end-13",
style:
"bg-300 animate-bg-scroll bg-gradient-to-tr from-sky-300 via-violet-300 to-pink-300 dark:bg-pink-700 flex flex-col justify-around",
content: Glow(<span>Loading latest commit</span>, "none"),
},
links: {
row: "row-start-5 row-end-6",
col: "col-start-10 col-end-13",
style: "flex justify-between px-12 py-4",
content: ({ styles, className }) => (
<div
className={`${className} ${styles} grid grid-cols-4 justify-around items-center gap-12`}
>
<LinkBubble
className="bg-white-mantle aspect-square"
href="https://github.com/nyxkrage"
>
<svg
role="img"
height="50%"
width="50%"
fill="#181717"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>GitHub</title>
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
</svg>
</LinkBubble>
<LinkBubble
className="bg-white-mantle aspect-square"
href="https://gitea.pid1.sh/nyx"
>
<svg
height="50%"
width="50%"
fill="#609926"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>Gitea</title>
<path d="M4.209 4.603c-.247 0-.525.02-.84.088-.333.07-1.28.283-2.054 1.027C-.403 7.25.035 9.685.089 10.052c.065.446.263 1.687 1.21 2.768 1.749 2.141 5.513 2.092 5.513 2.092s.462 1.103 1.168 2.119c.955 1.263 1.936 2.248 2.89 2.367 2.406 0 7.212-.004 7.212-.004s.458.004 1.08-.394c.535-.324 1.013-.893 1.013-.893s.492-.527 1.18-1.73c.21-.37.385-.729.538-1.068 0 0 2.107-4.471 2.107-8.823-.042-1.318-.367-1.55-.443-1.627-.156-.156-.366-.153-.366-.153s-4.475.252-6.792.306c-.508.011-1.012.023-1.512.027v4.474l-.634-.301c0-1.39-.004-4.17-.004-4.17-1.107.016-3.405-.084-3.405-.084s-5.399-.27-5.987-.324c-.187-.011-.401-.032-.648-.032zm.354 1.832h.111s.271 2.269.6 3.597C5.549 11.147 6.22 13 6.22 13s-.996-.119-1.641-.348c-.99-.324-1.409-.714-1.409-.714s-.73-.511-1.096-1.52C1.444 8.73 2.021 7.7 2.021 7.7s.32-.859 1.47-1.145c.395-.106.863-.12 1.072-.12zm8.33 2.554c.26.003.509.127.509.127l.868.422-.529 1.075a.686.686 0 0 0-.614.359.685.685 0 0 0 .072.756l-.939 1.924a.69.69 0 0 0-.66.527.687.687 0 0 0 .347.763.686.686 0 0 0 .867-.206.688.688 0 0 0-.069-.882l.916-1.874a.667.667 0 0 0 .237-.02.657.657 0 0 0 .271-.137 8.826 8.826 0 0 1 1.016.512.761.761 0 0 1 .286.282c.073.21-.073.569-.073.569-.087.29-.702 1.55-.702 1.55a.692.692 0 0 0-.676.477.681.681 0 1 0 1.157-.252c.073-.141.141-.282.214-.431.19-.397.515-1.16.515-1.16.035-.066.218-.394.103-.814-.095-.435-.48-.638-.48-.638-.467-.301-1.116-.58-1.116-.58s0-.156-.042-.27a.688.688 0 0 0-.148-.241l.516-1.062 2.89 1.401s.48.218.583.619c.073.282-.019.534-.069.657-.24.587-2.1 4.317-2.1 4.317s-.232.554-.748.588a1.065 1.065 0 0 1-.393-.045l-.202-.08-4.31-2.1s-.417-.218-.49-.596c-.083-.31.104-.691.104-.691l2.073-4.272s.183-.37.466-.497a.855.855 0 0 1 .35-.077z" />
</svg>
</LinkBubble>
{/* <LinkBubble
className="bg-white-mantle aspect-square"
href="https://gitea.pid1.sh/sanctureplicum"
>
<svg
height="50%"
width="50%"
fill="#5277C3"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>NixOS</title>
<path d="M7.352 1.592l-1.364.002L5.32 2.75l1.557 2.713-3.137-.008-1.32 2.34H14.11l-1.353-2.332-3.192-.006-2.214-3.865zm6.175 0l-2.687.025 5.846 10.127 1.341-2.34-1.59-2.765 2.24-3.85-.683-1.182h-1.336l-1.57 2.705-1.56-2.72zm6.887 4.195l-5.846 10.125 2.696-.008 1.601-2.76 4.453.016.682-1.183-.666-1.157-3.13-.008L21.778 8.1l-1.365-2.313zM9.432 8.086l-2.696.008-1.601 2.76-4.453-.016L0 12.02l.666 1.157 3.13.008-1.575 2.71 1.365 2.315L9.432 8.086zM7.33 12.25l-.006.01-.002-.004-1.342 2.34 1.59 2.765-2.24 3.85.684 1.182H7.35l.004-.006h.001l1.567-2.698 1.558 2.72 2.688-.026-.004-.006h.01L7.33 12.25zm2.55 3.93l1.354 2.332 3.192.006 2.215 3.865 1.363-.002.668-1.156-1.557-2.713 3.137.008 1.32-2.34H9.881Z" />
</svg>
</LinkBubble> */}
<LinkBubble
className="bg-white-mantle aspect-square"
href="https://discordapp.com/users/233967347763904522"
>
<svg
height="50%"
width="50%"
fill="#5865F2"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>Discord</title>
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z" />
</svg>
</LinkBubble>
<LinkBubble
className="bg-white-mantle aspect-square"
href="https://twitter.com/nyxkrage"
>
<svg
height="50%"
width="50%"
fill="#1DA1F2"
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<title>Twitter</title>
<path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z" />
</svg>
</LinkBubble>
</div>
),
},
showcase: {
row: "row-start-6 row-end-9",
col: "col-start-1 col-end-8",
content: ({ styles, className }) => {
return (
<div
className={`${className} ${styles} grid grid-cols-4 items-center gap-12`}
>
<ShowcaseCard
className="h-full w-full relative bg-gradient-to-l from-black-base to-white-base rounded-2xl"
bg="https://github.com/catppuccin/emacs/raw/main/assets/Screenshot.webp"
alt="screenshot of emacs with the catppuccin flavors"
>
<span className="text-white mix-blend-difference text-lg font-extrabold text-center">
Catppuccin/Emacs
</span>
<span className="text-white mix-blend-difference text-lg font-semibold text-center">
Soothing pastel colors for Emacs
</span>
<br />
<span className="text-white mix-blend-difference text-lg font-semibold text-center">
135
</span>
</ShowcaseCard>
<ShowcaseCard
className="h-full w-full relative bg-gradient-to-bl from-fuchsia-400 to-violet-400 rounded-2xl"
bg="https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/EmacsIcon.svg/1024px-EmacsIcon.svg.png"
alt="the emacs logo"
>
<span className="text-white mix-blend-difference text-lg font-extrabold text-center">
Emacs-OS
</span>
<br />
<span className="text-white mix-blend-difference text-lg font-semibold text-center">
Emacs running as pid1 on modern linux
</span>
<br />
<span className="text-white mix-blend-difference text-lg font-semibold text-center">
35
</span>
</ShowcaseCard>
<ShowcaseCard
className="h-full w-full relative bg-gradient-to-r from-sky-400 to-blue-300 rounded-2xl"
bg="https://upload.wikimedia.org/wikipedia/commons/thumb/2/28/Nix_snowflake.svg/886px-Nix_snowflake.svg.png"
alt="the nix snowflake"
>
<span className="text-white mix-blend-difference text-lg font-extrabold text-center">
Sanctureplicum
</span>
<br />
<span className="text-white mix-blend-difference text-lg font-semibold text-center">
Dotfiles using nix with flakes
</span>
<br />
<span className="text-white mix-blend-difference text-lg font-semibold text-center">
3
</span>
</ShowcaseCard>
<ShowcaseCard
className="h-full w-full relative bg-gradient-to-br from-emerald-400 to-violet-400 rounded-2xl"
bg=""
alt=""
>
<span className="text-white mix-blend-difference text-lg font-extrabold text-center">
See more...
</span>
<br />
<span className="text-white mix-blend-difference text-lg font-semibold text-center">
More projects on{" "}
<a href="https://gitea.pid1.sh" className="underline">
my gitea instance
</a>{" "}
&{" "}
<a href="https://github.com/nyxkrage" className="underline">
my github profile
</a>
</span>
<br />
</ShowcaseCard>
</div>
);
},
},
about: {
row: "row-start-6 row-end-9",
col: "col-start-8 col-end-13",
style: "text-xl",
content: ({ styles, className }) => {
return (
<div className={`${className} ${styles}`}>
<p className="font-bold text-3xl mb-4">About me</p>
<div dangerouslySetInnerHTML={{ __html: aboutMe }}></div>
</div>
);
},
},
};
import moment from "moment";
async function generateCommitCard() {
const data = await fetch("https://api.github.com/users/nyxkrage/events").then(
(res) => res.json()
);
let commit = (data as any[]).find((v) => v.type === "PushEvent");
let commit_repo = await fetch(commit.repo.url).then((res) => res.json());
if (commit_repo.fork) {
commit.repo.name = commit_repo.parent.full_name;
}
const pr = (data as any[]).find(
(v) => v.type === "PullRequestEvent" && v.payload.action === "opened"
);
return Glow(
<>
<div>
<p className="font-bold text-3xl mb-2">Latest Commit</p>
<span>
<a
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
target="_blank"
rel="noopener noreferrer"
>
<h2 className={`mb-3 text-2xl font-semibold`}>
Templates{' '}
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
-&gt;
</span>
</h2>
<p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
Explore the Next.js 13 playground.
</p>
className="underline"
href={`https://github.com/${commit.repo.name}/commit/${commit.payload.commits[0].sha}`}
>
{commit.payload.commits[0].message}
</a>{" "}
<span className="text-gray-800/30">on</span>{" "}
<a className="underline" href={commit.repo.url}>
{commit.repo.name}
</a>
<br />
<span className="text-gray-800/60">
{moment(new Date(commit.created_at)).fromNow()}
</span>
</span>
</div>
<div>
<p className="font-bold text-3xl mb-2">Latest PR</p>
<span>
<a
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
target="_blank"
rel="noopener noreferrer"
>
<h2 className={`mb-3 text-2xl font-semibold`}>
Deploy{' '}
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
-&gt;
</span>
</h2>
<p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
Instantly deploy your Next.js site to a shareable URL with Vercel.
</p>
className="underline"
href={`https://github.com/${pr.repo.name}/pull/${pr.payload.number}`}
>
{pr.payload.pull_request.title}
</a>{" "}
<span className="text-gray-800/30">on</span>{" "}
<a className="underline" href={pr.repo.url}>
{pr.repo.name}
</a>
<br />
<span className="text-gray-800/60">
{moment(new Date(pr.created_at)).fromNow()}
</span>
</span>
</div>
</>,
"none"
);
}
function cardToElement(card: Card, key?: string) {
let commonCardStyles = "rounded-4xl";
let commonCardClass = "w-full h-full";
return (
<card.content
key={key}
className={`${card.col} ${card.row} ${commonCardClass}`}
styles={`${commonCardStyles} ${
card.style?.includes("p-") ||
card.style?.includes("px-") ||
card.style?.includes("py-") ||
"p-8"
} ${card.style?.includes("bg-") || "bg-white-base dark:bg-black-base"} ${
card.style
}`}
></card.content>
);
}
export default async function Home() {
if (cards.commit && !Array.isArray(cards.commit)) {
cards.commit.content = await generateCommitCard();
}
return (
<main className="grid grid-rows-8 grid-cols-12 gap-8 min-h-screen flex-col items-center justify-between p-12 bg-white-crust text-black dark:bg-black-crust dark:text-white">
{Object.entries(cards).flatMap(([k, v]) => {
if (Array.isArray(v)) {
return v.map((c, i) => {
return cardToElement(c, `${k}-${i}`);
});
} else {
return cardToElement(v, k);
}
})}
</main>
)
);
}

@ -1,18 +1,76 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
darkMode: "class",
theme: {
extend: {
colors: {
"white-base": "#eff1f5",
"white-mantle": "#e6e9ef",
"white-crust": "#dce0e8",
"black-base": "#1e1e2e",
"black-mantle": "#181825",
"black-crust": "#11111b",
},
backgroundImage: {
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
'gradient-conic':
'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
"gradient-conic":
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
},
gridTemplateRows: {
8: "repeat(8, minmax(0, 1fr))",
},
gridRow: {
"span-7": "span 7 / span 7",
},
gridRowStart: {
7: "7",
8: "8",
},
gridRowEnd: {
7: "7",
8: "8",
9: "9",
},
gridColumn: {
"span-13": "span 13 / span 13",
},
gridColumnEnd: {
13: "13",
},
borderRadius: {
"4xl": "2rem",
},
backgroundSize: {
300: "300%",
400: "400%",
500: "500%",
600: "600%",
},
animation: {
"bg-scroll": "bgscroll 10s linear infinite",
},
keyframes: {
bgscroll: {
"0%, 100%": {
"background-position": "0 50%",
},
"50%": {
"background-position": "100% 50%",
},
},
},
aspectRatio: {
square: "auto 1 / 1",
},
transitionProperty: {
location: "height, width, top, left, right, bottom",
},
},
},
plugins: [],
}
plugins: [require("tailwindcss-animate")],
};