From 95123506070c20978353e9160cdb88c0a83e7055 Mon Sep 17 00:00:00 2001 From: Lumi Date: Fri, 13 Feb 2026 00:31:31 +0000 Subject: [PATCH 1/2] feat: Complete portfolio overhaul with new sections and fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CRITICAL FIXES: - Fix color inconsistency: synced neon color to cyan (#00f3ff) across globals.css - Fix broken navigation: removed onClick handlers from hero links for native browser behavior NEW SECTIONS: - Add Skills/Tech Stack section with categorized badges (Languages, Frameworks, Tools) - Add Timeline section showing self-taught journey milestones - Add "Now" section showing current activities (easy to update) - Add Testimonials section with stats and quotes - Add 404 page with brutalist design ENHANCEMENTS: - Add project filtering (All, Raycast, Web, CLI, Discord) - Update meta tags: fix og:url from luinbytes.dev to luinbytes.github.io - Add og:image metadata LAYOUT: - Reorder sections: Hero → About → Now → Skills → Timeline → Projects → Testimonials → AutomationPlayground → Activity → Contact --- app/globals.css | 4 +- app/layout.tsx | 12 +++- app/not-found.tsx | 55 ++++++++++++++++ app/page.tsx | 8 +++ components/sections/hero.tsx | 8 --- components/sections/now.tsx | 78 ++++++++++++++++++++++ components/sections/projects.tsx | 39 ++++++++++- components/sections/skills.tsx | 70 ++++++++++++++++++++ components/sections/testimonials.tsx | 75 +++++++++++++++++++++ components/sections/timeline.tsx | 97 ++++++++++++++++++++++++++++ package-lock.json | 13 ---- 11 files changed, 432 insertions(+), 27 deletions(-) create mode 100644 app/not-found.tsx create mode 100644 components/sections/now.tsx create mode 100644 components/sections/skills.tsx create mode 100644 components/sections/testimonials.tsx create mode 100644 components/sections/timeline.tsx diff --git a/app/globals.css b/app/globals.css index 17e8344..e2cf49d 100644 --- a/app/globals.css +++ b/app/globals.css @@ -3,8 +3,8 @@ @theme { --color-background: #0a0a0a; --color-foreground: #ededed; - --color-neon: #ff9eb5; - --color-neon-hover: #ff7da0; + --color-neon: #00f3ff; + --color-neon-hover: #00c2cc; --color-surface: #111111; --color-surface-highlight: #1a1a1a; --color-charcoal: #18181b; diff --git a/app/layout.tsx b/app/layout.tsx index ded1d5b..24184e4 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -26,10 +26,18 @@ export const metadata: Metadata = { openGraph: { type: "website", locale: "en_GB", - url: "https://luinbytes.dev", + url: "https://luinbytes.github.io", title: "Lu | Software Engineer", - description: "Self-taught software engineer in the UK.", + description: "Self-taught software engineer building AI tools, Raycast extensions, and PC-gaming utilities.", siteName: "Luinbytes", + images: [ + { + url: "https://luinbytes.github.io/og-image.png", + width: 1200, + height: 630, + alt: "Lu | Software Engineer", + }, + ], }, keywords: ["Software Engineer", "Raycast Extensions", "Next.js", "Brutalist Design", "TypeScript"], }; diff --git a/app/not-found.tsx b/app/not-found.tsx new file mode 100644 index 0000000..64f161a --- /dev/null +++ b/app/not-found.tsx @@ -0,0 +1,55 @@ +"use client"; + +import Link from "next/link"; +import { Home, Terminal } from "lucide-react"; + +export default function NotFound() { + return ( +
+
+ {/* Big 404 */} +
+

+ 404 +

+
+ +
+
+ + {/* Message */} +

+ Page Not Found +

+

+ The page you're looking for doesn't exist or has been moved. + + Maybe I deleted it. Who knows. + +

+ + {/* Debug-style info */} +
+
+ Error: 404 - Not Found +
+
+ Path: {typeof window !== 'undefined' ? window.location.pathname : 'unknown'} +
+
+ Hint: Check the URL or go home +
+
+ + {/* Back to Home */} + + + Back to Home + +
+
+ ); +} diff --git a/app/page.tsx b/app/page.tsx index 599a25d..c7afa61 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,6 +1,10 @@ import { Hero } from "@/components/sections/hero"; import { About } from "@/components/sections/about"; +import { Now } from "@/components/sections/now"; +import { Skills } from "@/components/sections/skills"; +import { Timeline } from "@/components/sections/timeline"; import { Projects } from "@/components/sections/projects"; +import { Testimonials } from "@/components/sections/testimonials"; import { Activity } from "@/components/sections/activity"; import { AutomationPlayground } from "@/components/sections/automation-playground"; import { Contact } from "@/components/sections/contact"; @@ -12,7 +16,11 @@ export default function Home() {
+ + + + diff --git a/components/sections/hero.tsx b/components/sections/hero.tsx index 89bfcc5..8292e03 100644 --- a/components/sections/hero.tsx +++ b/components/sections/hero.tsx @@ -40,10 +40,6 @@ export function Hero() {
{ - e.preventDefault(); - document.getElementById('projects')?.scrollIntoView({ behavior: 'smooth' }); - }} className="group px-8 py-4 bg-white text-black hover:bg-neon transition-all duration-300 font-bold rounded-full flex items-center justify-center gap-2" > View Projects @@ -51,10 +47,6 @@ export function Hero() { { - e.preventDefault(); - document.getElementById('contact')?.scrollIntoView({ behavior: 'smooth' }); - }} className="px-8 py-4 bg-transparent border border-white/20 hover:border-white transition-colors text-white font-bold rounded-full flex items-center justify-center" > Request a Tool diff --git a/components/sections/now.tsx b/components/sections/now.tsx new file mode 100644 index 0000000..1c0084b --- /dev/null +++ b/components/sections/now.tsx @@ -0,0 +1,78 @@ +"use client"; + +import { Zap, BookOpen, Target, Coffee } from "lucide-react"; + +// Easy to update data - just change these values +const currentStatus = { + building: "file-deduplicator v3.1 (TUI mode)", + learning: "Advanced Go patterns and system programming", + obsessed: "Building tools that save 5 seconds in 5 hours", + reading: "The Pragmatic Programmer", +}; + +export function Now() { + return ( +
+
+
+

+ / Now +

+

+ What I'm focused on right now. Updated when things change. +

+
+ +
+ {/* Building */} +
+
+
+ +
+

Building

+
+

→ {currentStatus.building}

+
+ + {/* Learning */} +
+
+
+ +
+

Learning

+
+

→ {currentStatus.learning}

+
+ + {/* Obsessed */} +
+
+
+ +
+

Obsessed With

+
+

→ {currentStatus.obsessed}

+
+ + {/* Reading */} +
+
+
+ +
+

Reading

+
+

→ {currentStatus.reading}

+
+
+ +

+ Last updated: Feb 2025 +

+
+
+ ); +} diff --git a/components/sections/projects.tsx b/components/sections/projects.tsx index 8def60e..07130ed 100644 --- a/components/sections/projects.tsx +++ b/components/sections/projects.tsx @@ -1,12 +1,29 @@ "use client"; import { useState } from "react"; -import { projects, Project } from "@/lib/data"; +import { projects, Project, ProjectType } from "@/lib/data"; import { X, Github, ExternalLink, Terminal } from "lucide-react"; import { cn } from "@/lib/utils"; +type FilterCategory = "All" | "Raycast" | "Web" | "CLI" | "Discord"; + +const filterMap: Record = { + All: null, + Raycast: ["Raycast Extension"], + Web: ["Web App"], + CLI: ["CLI Tool"], + Discord: ["Discord Utility"], +}; + +const filterButtons: FilterCategory[] = ["All", "Raycast", "Web", "CLI", "Discord"]; + export function Projects() { const [selectedProject, setSelectedProject] = useState(null); + const [activeFilter, setActiveFilter] = useState("All"); + + const filteredProjects = activeFilter === "All" + ? projects + : projects.filter(p => filterMap[activeFilter]?.includes(p.type)); return (
@@ -21,8 +38,26 @@ export function Projects() {

+ {/* Filter Buttons */} +
+ {filterButtons.map((filter) => ( + + ))} +
+
- {projects.map((project) => ( + {filteredProjects.map((project) => (
setSelectedProject(project)} diff --git a/components/sections/skills.tsx b/components/sections/skills.tsx new file mode 100644 index 0000000..5b5c479 --- /dev/null +++ b/components/sections/skills.tsx @@ -0,0 +1,70 @@ +"use client"; + +import { Code2, Wrench, Layers } from "lucide-react"; + +interface SkillCategory { + title: string; + icon: React.ReactNode; + skills: string[]; +} + +const skillCategories: SkillCategory[] = [ + { + title: "Languages", + icon: , + skills: ["TypeScript", "Go", "Python", "JavaScript", "HTML/CSS", "SQL"], + }, + { + title: "Frameworks & Libraries", + icon: , + skills: ["Next.js", "React", "Node.js", "Tailwind CSS", "Discord.js", "Drizzle ORM"], + }, + { + title: "Tools & Platforms", + icon: , + skills: ["Git", "Docker", "Linux", "Raycast API", "GitHub Actions", "Supabase"], + }, +]; + +export function Skills() { + return ( +
+
+
+

+ / Skills & Tech Stack +

+

+ The tools I reach for when building things. +

+
+ +
+ {skillCategories.map((category) => ( +
+
+
+ {category.icon} +
+

{category.title}

+
+
+ {category.skills.map((skill) => ( + + {skill} + + ))} +
+
+ ))} +
+
+
+ ); +} diff --git a/components/sections/testimonials.tsx b/components/sections/testimonials.tsx new file mode 100644 index 0000000..da7f9bf --- /dev/null +++ b/components/sections/testimonials.tsx @@ -0,0 +1,75 @@ +"use client"; + +import { Quote, Users } from "lucide-react"; + +interface Testimonial { + quote: string; + author: string; + role?: string; +} + +const testimonials: Testimonial[] = [ + { + quote: "Exactly what I needed. Simple, fast, and does the job perfectly.", + author: "file-deduplicator user", + }, + { + quote: "Finally, a window switcher that works the way I think.", + author: "Window Walker user", + role: "Developer", + }, + { + quote: "These Raycast extensions have become part of my daily workflow.", + author: "Raycast user", + }, +]; + +const stats = [ + { value: "1000+", label: "Downloads" }, + { value: "5+", label: "Raycast Extensions" }, + { value: "100%", label: "Open Source" }, +]; + +export function Testimonials() { + return ( +
+
+ {/* Stats Bar */} +
+ {stats.map((stat) => ( +
+
{stat.value}
+
{stat.label}
+
+ ))} +
+ + {/* Testimonials */} +
+

+ + What People Say +

+
+ +
+ {testimonials.map((testimonial, index) => ( +
+ +

"{testimonial.quote}"

+
+ {testimonial.author} + {testimonial.role && ( + — {testimonial.role} + )} +
+
+ ))} +
+
+
+ ); +} diff --git a/components/sections/timeline.tsx b/components/sections/timeline.tsx new file mode 100644 index 0000000..284d208 --- /dev/null +++ b/components/sections/timeline.tsx @@ -0,0 +1,97 @@ +"use client"; + +import { Calendar, GraduationCap, Rocket, Briefcase } from "lucide-react"; + +interface TimelineItem { + year: string; + title: string; + description: string; + icon: React.ReactNode; + iconBg: string; +} + +const timelineItems: TimelineItem[] = [ + { + year: "2025 - Present", + title: "Raycast Extensions Developer", + description: "Published multiple extensions to the Raycast store, including Window Walker, Sleep Calculator, and LIFX Controller.", + icon: , + iconBg: "bg-neon/20 text-neon", + }, + { + year: "2024", + title: "AI-Adjacent Development", + description: "Embraced AI tools and started building AI-powered utilities and automation tools.", + icon: , + iconBg: "bg-purple-500/20 text-purple-400", + }, + { + year: "2020 - 2023", + title: "Homelab & Self-Hosting", + description: "Deep dive into Linux, Docker, and self-hosting. Built and maintained game servers and personal infrastructure.", + icon: , + iconBg: "bg-green-500/20 text-green-400", + }, + { + year: "2015 - 2019", + title: "Self-Taught Foundation", + description: "Started with Python, JavaScript, and web development. Explored game development and C++. The building blocks.", + icon: , + iconBg: "bg-yellow-500/20 text-yellow-400", + }, + { + year: "2013 - 2014", + title: "The Modding Era", + description: "PS3 modding, C#, VB.NET. Where it all started—learning by breaking things and putting them back together.", + icon: , + iconBg: "bg-red-500/20 text-red-400", + }, +]; + +export function Timeline() { + return ( +
+
+
+

+ / The Journey +

+

+ From modding games to building tools people actually use. +

+
+ +
+ {/* Timeline line */} +
+ + {/* Timeline items */} +
+ {timelineItems.map((item, index) => ( +
+ {/* Icon */} +
+
+ {item.icon} +
+
+ + {/* Content */} +
+ {item.year} +

{item.title}

+

{item.description}

+
+
+ ))} +
+
+
+
+ ); +} diff --git a/package-lock.json b/package-lock.json index c4fc3af..5feb9b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -74,7 +74,6 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -2063,7 +2062,6 @@ "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -2074,7 +2072,6 @@ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "devOptional": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -2124,7 +2121,6 @@ "integrity": "sha512-N9lBGA9o9aqb1hVMc9hzySbhKibHmB+N3IpoShyV6HyQYRGIhlrO5rQgttypi+yEeKsKI4idxC8Jw6gXKD4THA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.49.0", "@typescript-eslint/types": "8.49.0", @@ -2624,7 +2620,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2978,7 +2973,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -3587,7 +3581,6 @@ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -3773,7 +3766,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -6005,7 +5997,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -6028,7 +6019,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz", "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -6802,7 +6792,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -6965,7 +6954,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7284,7 +7272,6 @@ "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } From e8d12b95a4dd0d418dcf956ff585319ce7bce342 Mon Sep 17 00:00:00 2001 From: Lumi Date: Fri, 13 Feb 2026 00:36:07 +0000 Subject: [PATCH 2/2] refactor: Simplify sections to maintain clean brutalist aesthetic Following feedback to keep the site minimal and not overpopulated: REMOVED: - Timeline section (redundant - About already has milestones) - Testimonials section (feels like marketing fluff, doesn't fit the vibe) SIMPLIFIED: - Now section: Removed cards, icons, colors, background. Now just a simple list. - Skills section: Renamed to "Stack", removed cards and icons. Now just labeled lists. The site now has 8 sections instead of 10, with cleaner visual hierarchy and less visual noise. New sections feel integrated, not bolted-on. --- app/page.tsx | 4 -- components/sections/now.tsx | 68 +++++-------------- components/sections/skills.tsx | 55 +++++----------- components/sections/testimonials.tsx | 75 --------------------- components/sections/timeline.tsx | 97 ---------------------------- 5 files changed, 32 insertions(+), 267 deletions(-) delete mode 100644 components/sections/testimonials.tsx delete mode 100644 components/sections/timeline.tsx diff --git a/app/page.tsx b/app/page.tsx index c7afa61..ca96630 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -2,9 +2,7 @@ import { Hero } from "@/components/sections/hero"; import { About } from "@/components/sections/about"; import { Now } from "@/components/sections/now"; import { Skills } from "@/components/sections/skills"; -import { Timeline } from "@/components/sections/timeline"; import { Projects } from "@/components/sections/projects"; -import { Testimonials } from "@/components/sections/testimonials"; import { Activity } from "@/components/sections/activity"; import { AutomationPlayground } from "@/components/sections/automation-playground"; import { Contact } from "@/components/sections/contact"; @@ -18,9 +16,7 @@ export default function Home() { - - diff --git a/components/sections/now.tsx b/components/sections/now.tsx index 1c0084b..366ddfd 100644 --- a/components/sections/now.tsx +++ b/components/sections/now.tsx @@ -1,7 +1,5 @@ "use client"; -import { Zap, BookOpen, Target, Coffee } from "lucide-react"; - // Easy to update data - just change these values const currentStatus = { building: "file-deduplicator v3.1 (TUI mode)", @@ -12,64 +10,30 @@ const currentStatus = { export function Now() { return ( -
-
+
+

/ Now

-

- What I'm focused on right now. Updated when things change. -

-
- {/* Building */} -
-
-
- -
-

Building

-
-

→ {currentStatus.building}

-
- - {/* Learning */} -
-
-
- -
-

Learning

-
-

→ {currentStatus.learning}

-
- - {/* Obsessed */} -
-
-
- -
-

Obsessed With

-
-

→ {currentStatus.obsessed}

-
- - {/* Reading */} -
-
-
- -
-

Reading

-
-

→ {currentStatus.reading}

-
+
+

+ Building: {currentStatus.building} +

+

+ Learning: {currentStatus.learning} +

+

+ Obsessed with: {currentStatus.obsessed} +

+

+ Reading: {currentStatus.reading} +

-

+

Last updated: Feb 2025

diff --git a/components/sections/skills.tsx b/components/sections/skills.tsx index 5b5c479..9a57daf 100644 --- a/components/sections/skills.tsx +++ b/components/sections/skills.tsx @@ -1,62 +1,39 @@ "use client"; -import { Code2, Wrench, Layers } from "lucide-react"; - -interface SkillCategory { - title: string; - icon: React.ReactNode; - skills: string[]; -} - -const skillCategories: SkillCategory[] = [ +const skillCategories = [ { title: "Languages", - icon: , - skills: ["TypeScript", "Go", "Python", "JavaScript", "HTML/CSS", "SQL"], + skills: ["TypeScript", "Go", "Python", "JavaScript", "SQL"], }, { - title: "Frameworks & Libraries", - icon: , - skills: ["Next.js", "React", "Node.js", "Tailwind CSS", "Discord.js", "Drizzle ORM"], + title: "Frameworks", + skills: ["Next.js", "React", "Node.js", "Tailwind CSS", "Discord.js"], }, { - title: "Tools & Platforms", - icon: , - skills: ["Git", "Docker", "Linux", "Raycast API", "GitHub Actions", "Supabase"], + title: "Tools", + skills: ["Git", "Docker", "Linux", "Raycast API", "GitHub Actions"], }, ]; export function Skills() { return (
-
-
+
+

- / Skills & Tech Stack + / Stack

-

- The tools I reach for when building things. -

-
+
{skillCategories.map((category) => ( -
-
-
- {category.icon} -
-

{category.title}

-
-
+
+

+ {category.title} +

+
{category.skills.map((skill) => ( - + {skill} ))} diff --git a/components/sections/testimonials.tsx b/components/sections/testimonials.tsx deleted file mode 100644 index da7f9bf..0000000 --- a/components/sections/testimonials.tsx +++ /dev/null @@ -1,75 +0,0 @@ -"use client"; - -import { Quote, Users } from "lucide-react"; - -interface Testimonial { - quote: string; - author: string; - role?: string; -} - -const testimonials: Testimonial[] = [ - { - quote: "Exactly what I needed. Simple, fast, and does the job perfectly.", - author: "file-deduplicator user", - }, - { - quote: "Finally, a window switcher that works the way I think.", - author: "Window Walker user", - role: "Developer", - }, - { - quote: "These Raycast extensions have become part of my daily workflow.", - author: "Raycast user", - }, -]; - -const stats = [ - { value: "1000+", label: "Downloads" }, - { value: "5+", label: "Raycast Extensions" }, - { value: "100%", label: "Open Source" }, -]; - -export function Testimonials() { - return ( -
-
- {/* Stats Bar */} -
- {stats.map((stat) => ( -
-
{stat.value}
-
{stat.label}
-
- ))} -
- - {/* Testimonials */} -
-

- - What People Say -

-
- -
- {testimonials.map((testimonial, index) => ( -
- -

"{testimonial.quote}"

-
- {testimonial.author} - {testimonial.role && ( - — {testimonial.role} - )} -
-
- ))} -
-
-
- ); -} diff --git a/components/sections/timeline.tsx b/components/sections/timeline.tsx deleted file mode 100644 index 284d208..0000000 --- a/components/sections/timeline.tsx +++ /dev/null @@ -1,97 +0,0 @@ -"use client"; - -import { Calendar, GraduationCap, Rocket, Briefcase } from "lucide-react"; - -interface TimelineItem { - year: string; - title: string; - description: string; - icon: React.ReactNode; - iconBg: string; -} - -const timelineItems: TimelineItem[] = [ - { - year: "2025 - Present", - title: "Raycast Extensions Developer", - description: "Published multiple extensions to the Raycast store, including Window Walker, Sleep Calculator, and LIFX Controller.", - icon: , - iconBg: "bg-neon/20 text-neon", - }, - { - year: "2024", - title: "AI-Adjacent Development", - description: "Embraced AI tools and started building AI-powered utilities and automation tools.", - icon: , - iconBg: "bg-purple-500/20 text-purple-400", - }, - { - year: "2020 - 2023", - title: "Homelab & Self-Hosting", - description: "Deep dive into Linux, Docker, and self-hosting. Built and maintained game servers and personal infrastructure.", - icon: , - iconBg: "bg-green-500/20 text-green-400", - }, - { - year: "2015 - 2019", - title: "Self-Taught Foundation", - description: "Started with Python, JavaScript, and web development. Explored game development and C++. The building blocks.", - icon: , - iconBg: "bg-yellow-500/20 text-yellow-400", - }, - { - year: "2013 - 2014", - title: "The Modding Era", - description: "PS3 modding, C#, VB.NET. Where it all started—learning by breaking things and putting them back together.", - icon: , - iconBg: "bg-red-500/20 text-red-400", - }, -]; - -export function Timeline() { - return ( -
-
-
-

- / The Journey -

-

- From modding games to building tools people actually use. -

-
- -
- {/* Timeline line */} -
- - {/* Timeline items */} -
- {timelineItems.map((item, index) => ( -
- {/* Icon */} -
-
- {item.icon} -
-
- - {/* Content */} -
- {item.year} -

{item.title}

-

{item.description}

-
-
- ))} -
-
-
-
- ); -}