feat: Major update
This commit is contained in:
@@ -1,17 +1,42 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const activitySvg =
|
||||
"https://gitact.spaceistyping.com/activity.svg?days=365&source=all&theme=dark";
|
||||
|
||||
export function Activity() {
|
||||
const [dailyActivity, setDailyActivity] = useState<string | null>(null);
|
||||
const [projectCount, setProjectCount] = useState<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Fetch a string of how long i have coded today, e.g. "2h 35m"
|
||||
fetch(
|
||||
"https://shsf-api.reversed.dev/api/exec/6/842aa52f-1a9e-43e1-b630-00286b44897a",
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then((hourText) => {
|
||||
setDailyActivity(hourText.text);
|
||||
setProjectCount(hourText.across);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<section className="w-full max-w-6xl mx-auto space-y-8 px-4">
|
||||
<div className="text-center space-y-4">
|
||||
<h2 className="text-3xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-500">
|
||||
Activity
|
||||
Code Activity
|
||||
</h2>
|
||||
<p className="text-gray-400 max-w-2xl mx-auto">
|
||||
A live snapshot of my recent Git activity.
|
||||
Today, i've already been coding for
|
||||
<span className="font-mono text-base text-green-400 ml-1">
|
||||
{dailyActivity || "..."}
|
||||
</span>
|
||||
, across approximately
|
||||
<span className="font-mono text-base text-green-400 ml-1">
|
||||
{projectCount !== null ? projectCount : "..."}
|
||||
</span>{" "}
|
||||
projects .
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -26,6 +51,38 @@ export function Activity() {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-center text-gray-500 text-sm">
|
||||
Data from my <strong>public</strong>{" "}
|
||||
<a
|
||||
href="https://github.com/Space-Banane"
|
||||
className="text-blue-400 hover:underline"
|
||||
>
|
||||
Github
|
||||
</a>{" "}
|
||||
&{" "}
|
||||
<a
|
||||
href="https://gitea.reversed.dev/space"
|
||||
className="text-blue-400 hover:underline"
|
||||
>
|
||||
Gitea
|
||||
</a>{" "}
|
||||
contributions. Via{" "}
|
||||
<a
|
||||
href="https://gitea.reversed.dev/space/git-activity-merger"
|
||||
className="text-blue-400 hover:underline"
|
||||
>
|
||||
Git Activity Merger
|
||||
</a>
|
||||
. Possibly cached & delayed.
|
||||
</p>
|
||||
<p className="text-center text-gray-500 text-sm max-w-2xl justify-center mx-auto mt-1">
|
||||
Coding time is estimated based on Wakapi data, which tracks my coding
|
||||
activity across a lot of projects, but also gets things wrong. So take
|
||||
it with a grain of salt. An <a href="https://github.com/Space-Banane/shsf" className="text-blue-400 hover:underline">SHSF Function</a> fetches the data and makes it available via an API.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,22 +6,28 @@ type Affiliate = {
|
||||
bad: string[];
|
||||
link: string;
|
||||
icon: string;
|
||||
location: string;
|
||||
provides: string[];
|
||||
};
|
||||
|
||||
const affiliates: Affiliate[] = [
|
||||
{
|
||||
name: "SparkedHost",
|
||||
good: ["Decent Support", "Good Bot Hosting", "Generous Webhosting"],
|
||||
bad: ["Staff"],
|
||||
bad: ["Staff can be hit or miss"],
|
||||
link: "https://billing.sparkedhost.com/aff.php?aff=1843",
|
||||
icon: "https://sparkedhost.com/_next/static/media/logo-text.fce7e4c5.svg",
|
||||
location: "Global",
|
||||
provides: ["A ton of Game Hosting", "Web Hosting", "VPS", "Bot Hosting", "Domains"],
|
||||
},
|
||||
{
|
||||
name: "Datalix",
|
||||
good: ["Uptime", "Hardware", "Prices", "Support"],
|
||||
bad: ["nothin"],
|
||||
bad: ["Nothing"],
|
||||
link: "https://datalix.de/a/space",
|
||||
icon: "https://cdn.datalix.de/images/header.png",
|
||||
location: "Germany",
|
||||
provides: ["KVM VPS", "Web Hosting", "Dedicated Servers", "Game Servers", "S3", "Nextcloud", "Reselling"],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -32,6 +38,9 @@ export function Affiliates() {
|
||||
<h2 className="text-3xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-500">
|
||||
Affiliates
|
||||
</h2>
|
||||
<p className="text-gray-400 max-w-2xl mx-auto">
|
||||
Looking for hosting? I recommend checking out Datalix!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
|
||||
@@ -49,12 +58,36 @@ export function Affiliates() {
|
||||
alt={affiliate.name}
|
||||
className="h-7 max-w-[130px] w-auto object-contain rounded"
|
||||
/>
|
||||
<h3 className="text-lg font-semibold text-white">{affiliate.name}</h3>
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-white">
|
||||
{affiliate.name}
|
||||
</h3>
|
||||
<p className="text-[10px] uppercase tracking-widest text-gray-500 font-medium leading-none mt-1">
|
||||
{affiliate.location}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<p className="text-xs font-semibold text-emerald-300 mb-1.5">Good</p>
|
||||
<p className="text-xs font-semibold text-blue-300 mb-1.5">
|
||||
Provides
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{affiliate.provides.map((item) => (
|
||||
<span
|
||||
key={item}
|
||||
className="inline-flex items-center gap-1.5 rounded-full border border-blue-400/30 bg-blue-500/10 px-2.5 py-1 text-xs text-blue-200"
|
||||
>
|
||||
{item}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs font-semibold text-emerald-300 mb-1.5">
|
||||
Good
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{affiliate.good.map((item) => (
|
||||
<span
|
||||
@@ -68,7 +101,9 @@ export function Affiliates() {
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs font-semibold text-rose-300 mb-1.5">Bad</p>
|
||||
<p className="text-xs font-semibold text-rose-300 mb-1.5">
|
||||
Bad
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{affiliate.bad.map((item) => (
|
||||
<span
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
"use client";
|
||||
|
||||
import { useProfile } from "../context/ProfileContext";
|
||||
|
||||
export function AgentSkills() {
|
||||
const { skills } = useProfile();
|
||||
|
||||
return (
|
||||
<section className="w-full max-w-6xl mx-auto px-4 space-y-8">
|
||||
<div className="text-center space-y-3">
|
||||
<h2 className="text-4xl font-bold leading-tight text-transparent bg-clip-text bg-gradient-to-r from-amber-400 to-orange-500">
|
||||
Agent Skills
|
||||
</h2>
|
||||
<p className="text-gray-400 max-w-2xl mx-auto">
|
||||
Skills i throw at my Agents to help them solve my prompts.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{skills.length === 0 ? (
|
||||
<div className="rounded-3xl border border-white/10 bg-white/5 px-6 py-10 text-center text-gray-400">
|
||||
No agent skills published yet.
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
{skills.map((skill, index) => (
|
||||
<article
|
||||
key={`${skill.name}-${index}`}
|
||||
className="group rounded-3xl border border-amber-500/20 bg-gradient-to-br from-amber-500/10 via-white/5 to-orange-500/5 p-6 md:p-7 shadow-[0_0_0_1px_rgba(245,158,11,0.08)] backdrop-blur-sm transition-all duration-300 hover:border-amber-500/40"
|
||||
>
|
||||
<div className="flex flex-wrap items-start justify-between gap-4">
|
||||
<div className="space-y-2">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{(skill.emojis || []).map((emoji, emojiIndex) => (
|
||||
<span
|
||||
key={`${skill.name}-emoji-${emojiIndex}`}
|
||||
className="inline-flex h-9 w-9 items-center justify-center rounded-xl bg-amber-500/15 text-lg border border-amber-500/20"
|
||||
title={emoji}
|
||||
>
|
||||
{emoji}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<h3 className="text-2xl font-semibold text-white">{skill.name}</h3>
|
||||
</div>
|
||||
|
||||
{skill.link ? (
|
||||
<a
|
||||
href={skill.link}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="inline-flex items-center rounded-full border border-amber-400/30 bg-amber-400/10 px-4 py-2 text-xs font-semibold text-amber-100 transition-colors hover:bg-amber-400/20"
|
||||
>
|
||||
Open Link
|
||||
</a>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="mt-5 space-y-4 text-sm leading-6 text-gray-300">
|
||||
<p>
|
||||
<span className="font-semibold text-amber-200">Description:</span> {skill.description}
|
||||
</p>
|
||||
<p>
|
||||
<span className="font-semibold text-amber-200">Purpose:</span> {skill.purpose}
|
||||
</p>
|
||||
<p>
|
||||
<span className="font-semibold text-amber-200">Solves:</span> {skill.what_it_solves}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 flex flex-wrap gap-2">
|
||||
{(skill.tags || []).map((tag, tagIndex) => (
|
||||
<span
|
||||
key={`${skill.name}-tag-${tagIndex}`}
|
||||
className="rounded-full border border-white/10 bg-black/20 px-3 py-1 text-xs font-medium text-gray-200"
|
||||
>
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
"use client";
|
||||
|
||||
export function Goals() {
|
||||
return (
|
||||
<section className="w-full space-y-8">
|
||||
<div className="text-center space-y-2">
|
||||
<h2 className="text-3xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-500">
|
||||
My Goals
|
||||
</h2>
|
||||
<p className="text-gray-400 max-w-2xl mx-auto">Next 4 Years are going to look fun</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div className="p-6 rounded-2xl bg-gradient-to-br from-blue-500/10 to-purple-500/5 backdrop-blur-sm border border-blue-500/20">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="p-3 rounded-lg bg-blue-500/20 text-3xl">🚀</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-bold text-white mb-2">
|
||||
Not Just Semi-Fullstack
|
||||
</h3>
|
||||
<p className="text-gray-400 leading-relaxed">
|
||||
I want to work more with Serverless Architectures and Cloud
|
||||
Services to build scalable applications.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-6 rounded-2xl bg-gradient-to-br from-purple-500/10 to-pink-500/5 backdrop-blur-sm border border-purple-500/20">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="p-3 rounded-lg bg-purple-500/20 text-3xl">
|
||||
💻
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-bold text-white mb-2">
|
||||
Contribute More to Open Source
|
||||
</h3>
|
||||
<p className="text-gray-400 leading-relaxed">
|
||||
I want to commit more to Open-Source Projects. That's it...
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-6 rounded-2xl bg-gradient-to-br from-green-500/10 to-blue-500/5 backdrop-blur-sm border border-green-500/20">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="p-3 rounded-lg bg-green-500/20 text-3xl">
|
||||
⚡
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-bold text-white mb-2">
|
||||
Expand on Existing Projects
|
||||
</h3>
|
||||
<p className="text-gray-400 leading-relaxed">
|
||||
I want to make SHSF more stable and usable.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-6 rounded-2xl bg-gradient-to-br from-yellow-500/10 to-orange-500/5 backdrop-blur-sm border border-yellow-500/20">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="p-3 rounded-lg bg-yellow-500/20 text-3xl">
|
||||
🧪
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-bold text-white mb-2">
|
||||
Testing before Breaking
|
||||
</h3>
|
||||
<p className="text-gray-400 leading-relaxed">In the future i want to write more tests and improve my code quality.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="md:col-span-2 p-6 rounded-2xl bg-gradient-to-br from-yellow-500/10 to-orange-500/5 backdrop-blur-sm border border-yellow-500/20">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="p-3 rounded-lg bg-yellow-500/20 text-3xl">
|
||||
🏠
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-bold text-white mb-2">
|
||||
Embrace Self-Hosting
|
||||
</h3>
|
||||
<p className="text-gray-400 leading-relaxed">
|
||||
I want to learn more about self-hosting my own services and reduce reliance on cloud providers for personal projects.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
+10
-2
@@ -1,5 +1,6 @@
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import { useState, useRef } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { TimezoneClockBlock } from "../components/TimezoneClockBlock";
|
||||
|
||||
export function Hero({
|
||||
glowColor,
|
||||
@@ -8,6 +9,7 @@ export function Hero({
|
||||
rotatingMessages,
|
||||
statusMessage,
|
||||
oldUsernames,
|
||||
timeGapWarningThreshold = 5,
|
||||
}: {
|
||||
glowColor: string;
|
||||
borderStatus: string;
|
||||
@@ -15,6 +17,7 @@ export function Hero({
|
||||
rotatingMessages: string[];
|
||||
statusMessage: string;
|
||||
oldUsernames: string[];
|
||||
timeGapWarningThreshold?: number;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [movementCount, setMovementCount] = useState(0);
|
||||
@@ -104,6 +107,9 @@ export function Hero({
|
||||
on Discord
|
||||
</p>
|
||||
</div>
|
||||
<p className="text-xs text-gray-400/70 mt-1">
|
||||
Data from <a href="https://github.com/Space-Banane/shsf-discord-status" className="text-blue-400 hover:underline">Discord</a> (cached & delayed)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -131,7 +137,7 @@ export function Hero({
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<a
|
||||
href="https://luna.reversed.dev"
|
||||
href="https://luna.spaceistyping.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group relative flex items-center gap-3 px-6 py-2.5 rounded-full bg-white/5 border border-white/10 hover:bg-white/10 hover:border-purple-500/50 transition-all duration-300 shadow-lg hover:shadow-purple-500/10"
|
||||
@@ -169,6 +175,8 @@ export function Hero({
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<TimezoneClockBlock warningThresholdHours={timeGapWarningThreshold} />
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
"use client";
|
||||
|
||||
import { ExperienceCard } from "@/components/ExperienceCard";
|
||||
import type { Experience } from "../types";
|
||||
|
||||
const ENABLE_SKILLS_EXPERIENCE = true;
|
||||
|
||||
interface SkillsExperienceProps {
|
||||
experiences: Experience[];
|
||||
onSelectExperience: (experience: Experience) => void;
|
||||
}
|
||||
|
||||
export function SkillsExperience({
|
||||
experiences,
|
||||
onSelectExperience,
|
||||
}: SkillsExperienceProps) {
|
||||
if (!ENABLE_SKILLS_EXPERIENCE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const groupedExperiences = experiences.reduce(
|
||||
(acc, exp) => {
|
||||
if (!acc[exp.type]) acc[exp.type] = [];
|
||||
acc[exp.type].push(exp);
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, Experience[]>,
|
||||
);
|
||||
|
||||
return (
|
||||
<section className="w-full max-w-6xl mx-auto space-y-12 px-4 pb-20">
|
||||
<div className="text-center space-y-4">
|
||||
<h2 className="text-3xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-500">
|
||||
Skills & Experience
|
||||
</h2>
|
||||
<p className="text-gray-400">
|
||||
<span className="text-red-400">
|
||||
THIS IS MISSING A LOT OF THINGS, BE AWARE
|
||||
</span>{" "}
|
||||
- Things I've worked with over the years.
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-12">
|
||||
{Object.entries(groupedExperiences).map(([type, items]) => (
|
||||
<div key={type} className="space-y-6">
|
||||
<h3 className="text-xl font-semibold border-l-4 border-blue-500 pl-4 capitalize">
|
||||
{type}
|
||||
</h3>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
{items.map((exp, index) => (
|
||||
<ExperienceCard
|
||||
key={index}
|
||||
experience={exp}
|
||||
onClick={() => onSelectExperience(exp)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
+36
-15
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
import { cn } from "../components/cn";
|
||||
|
||||
const ENABLE_TECH_STACK = false;
|
||||
|
||||
const techStack = [
|
||||
{
|
||||
@@ -45,40 +46,60 @@ const techStack = [
|
||||
{
|
||||
title: "Servers",
|
||||
items: [
|
||||
{ name: "KVMS from datalix.de", description: "Cloud server provider" },
|
||||
{ name: "KVMs from datalix.de", description: "Cloud provider" },
|
||||
{ name: "Home server", description: "Self-hosted option" },
|
||||
{ name: "AWS", description: "Cloud computing" }
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export function TechStack() {
|
||||
if (!ENABLE_TECH_STACK) {
|
||||
// Disabled
|
||||
return (
|
||||
<section className="w-full max-w-4xl mx-auto px-4 space-y-12 mt-16 mb-24">
|
||||
<div className="text-center space-y-3">
|
||||
<h2 className="text-4xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 to-blue-500">
|
||||
Tech Stack
|
||||
</h2>
|
||||
<p className="text-gray-400 max-w-2xl mx-auto text-sm md:text-base">
|
||||
This section is currently disabled. It may be re-enabled in the future, but for now, it's hidden.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<section className="w-full max-w-4xl mx-auto px-4 space-y-8 mt-8">
|
||||
<div className="text-center space-y-2">
|
||||
<h2 className="text-3xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 to-blue-500">
|
||||
<section className="w-full max-w-4xl mx-auto px-4 space-y-12 mt-16 mb-24">
|
||||
<div className="text-center space-y-3">
|
||||
<h2 className="text-4xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 to-blue-500">
|
||||
Tech Stack
|
||||
</h2>
|
||||
<p className="text-gray-400 max-w-2xl mx-auto">
|
||||
My current infrastructure and software stack, from server to
|
||||
monitoring.
|
||||
<p className="text-gray-400 max-w-2xl mx-auto text-sm md:text-base">
|
||||
A overview of the tools and technologies I use to build and host my applications.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="max-w-2xl mx-auto space-y-4">
|
||||
{techStack.map((layer) => (
|
||||
<div
|
||||
key={layer.title}
|
||||
className="p-6 md:p-8 rounded-2xl bg-gradient-to-br from-cyan-500/10 to-blue-500/5 backdrop-blur-sm border border-cyan-500/20 space-y-5"
|
||||
className="p-5 rounded-2xl bg-gradient-to-br from-cyan-500/[0.07] to-blue-500/[0.03] backdrop-blur-md border border-cyan-500/10 hover:border-cyan-500/30 transition-all duration-500"
|
||||
>
|
||||
<h3 className="text-2xl font-semibold text-white">{layer.title}</h3>
|
||||
<ul className="flex flex-wrap gap-2">
|
||||
<h3 className="text-lg font-bold text-white mb-3 flex items-center gap-2">
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-cyan-500" />
|
||||
{layer.title}
|
||||
</h3>
|
||||
<ul className="space-y-3">
|
||||
{layer.items.map((item) => (
|
||||
<li
|
||||
key={item.name}
|
||||
className="px-3 py-1 rounded-full text-xs font-semibold bg-cyan-500/20 text-cyan-200 border border-cyan-500/30"
|
||||
className="flex flex-col group cursor-default"
|
||||
>
|
||||
<span className="font-medium">{item.name}</span>
|
||||
<span className="ml-2 text-[10px] text-cyan-100/70 font-normal border-l border-cyan-500/30 pl-2">
|
||||
<span className="text-sm font-semibold text-cyan-100 group-hover:text-cyan-400 transition-colors">
|
||||
{item.name}
|
||||
</span>
|
||||
<span className="text-[11px] text-gray-500 font-normal leading-relaxed">
|
||||
{item.description}
|
||||
</span>
|
||||
</li>
|
||||
|
||||
@@ -7,12 +7,15 @@ export function Uptime() {
|
||||
<h2 className="text-3xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-500">
|
||||
Downtime
|
||||
</h2>
|
||||
<p className="text-gray-400 max-w-2xl mx-auto">
|
||||
I love selfhosting stuff, can you tell?
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<div className="p-6 rounded-2xl bg-gradient-to-br from-gray-800/20 to-transparent backdrop-blur-sm border border-white/6">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4 text-center">
|
||||
I love my homelab
|
||||
Github vs HomeLab Uptime
|
||||
</h3>
|
||||
<div className="flex gap-6 items-center justify-between">
|
||||
<div className="flex-1 text-center">
|
||||
|
||||
@@ -57,7 +57,7 @@ export function WorkExperience({ realWork }: WorkExperienceProps) {
|
||||
Work Experience
|
||||
</h2>
|
||||
<p className="text-gray-400 max-w-2xl mx-auto">
|
||||
Professional collaborations and product work I have contributed to.
|
||||
Actual work that i did at actual companies.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user