Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
12 changes: 10 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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"],
};
Expand Down
55 changes: 55 additions & 0 deletions app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"use client";

import Link from "next/link";
import { Home, Terminal } from "lucide-react";

export default function NotFound() {
return (
<div className="min-h-screen flex items-center justify-center bg-background px-4">
<div className="text-center max-w-2xl">
{/* Big 404 */}
<div className="relative mb-8">
<h1 className="text-[12rem] md:text-[16rem] font-bold tracking-tighter text-white/5 leading-none">
404
</h1>
<div className="absolute inset-0 flex items-center justify-center">
<Terminal className="w-24 h-24 md:w-32 md:h-32 text-neon animate-pulse" />
</div>
</div>

{/* Message */}
<h2 className="text-3xl md:text-4xl font-bold tracking-tight text-white mb-4">
Page Not Found
</h2>
<p className="text-xl text-gray-400 mb-8 max-w-md mx-auto">
The page you're looking for doesn't exist or has been moved.
<span className="block mt-2 text-neon">
Maybe I deleted it. Who knows.
</span>
</p>

{/* Debug-style info */}
<div className="bg-surface border border-white/10 rounded-lg p-4 mb-8 text-left font-mono text-sm">
<div className="text-gray-500">
<span className="text-red-400">Error:</span> 404 - Not Found
</div>
<div className="text-gray-500">
<span className="text-yellow-400">Path:</span> {typeof window !== 'undefined' ? window.location.pathname : 'unknown'}
</div>
<div className="text-gray-500">
<span className="text-neon">Hint:</span> Check the URL or go home
</div>
</div>

{/* Back to Home */}
<Link
href="/"
className="inline-flex items-center gap-2 px-8 py-4 bg-neon text-black font-bold rounded-full hover:bg-neon/90 transition-colors"
>
<Home className="w-4 h-4" />
Back to Home
</Link>
</div>
</div>
);
}
4 changes: 4 additions & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,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 { Projects } from "@/components/sections/projects";
import { Activity } from "@/components/sections/activity";
import { AutomationPlayground } from "@/components/sections/automation-playground";
Expand All @@ -12,6 +14,8 @@ export default function Home() {
<Hero />
<div className="h-16" />
<About />
<Now />
<Skills />
<Projects />
<SectionErrorBoundary>
<AutomationPlayground />
Expand Down
8 changes: 0 additions & 8 deletions components/sections/hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,13 @@ export function Hero() {
<div className="flex flex-col sm:flex-row gap-4 w-full sm:w-auto">
<Link
href="#projects"
onClick={(e) => {
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
<ArrowRight className="w-4 h-4 group-hover:translate-x-1 transition-transform" />
</Link>
<Link
href="#contact"
onClick={(e) => {
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
Expand Down
42 changes: 42 additions & 0 deletions components/sections/now.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"use client";

// 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 (
<section id="now" className="py-24 relative border-t border-white/5">
<div className="container px-4 mx-auto max-w-4xl">
<div className="mb-12">
<h2 className="text-4xl md:text-5xl font-bold tracking-tighter mb-6 flex items-center gap-3">
<span className="text-neon">/</span> Now
</h2>
</div>

<div className="space-y-4 font-mono">
<p className="text-gray-300">
<span className="text-gray-500">→</span> Building: <span className="text-white">{currentStatus.building}</span>
</p>
<p className="text-gray-300">
<span className="text-gray-500">→</span> Learning: <span className="text-white">{currentStatus.learning}</span>
</p>
<p className="text-gray-300">
<span className="text-gray-500">→</span> Obsessed with: <span className="text-white">{currentStatus.obsessed}</span>
</p>
<p className="text-gray-300">
<span className="text-gray-500">→</span> Reading: <span className="text-white">{currentStatus.reading}</span>
</p>
</div>

<p className="mt-12 text-sm text-gray-600">
Last updated: Feb 2025
</p>
</div>
</section>
);
}
39 changes: 37 additions & 2 deletions components/sections/projects.tsx
Original file line number Diff line number Diff line change
@@ -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<FilterCategory, ProjectType[] | null> = {
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<Project | null>(null);
const [activeFilter, setActiveFilter] = useState<FilterCategory>("All");

const filteredProjects = activeFilter === "All"
? projects
: projects.filter(p => filterMap[activeFilter]?.includes(p.type));

return (
<section id="projects" className="py-24 relative border-t border-white/5">
Expand All @@ -21,8 +38,26 @@ export function Projects() {
</p>
</div>

{/* Filter Buttons */}
<div className="flex flex-wrap gap-3 mb-12">
{filterButtons.map((filter) => (
<button
key={filter}
onClick={() => setActiveFilter(filter)}
className={cn(
"px-4 py-2 text-sm font-mono font-bold uppercase tracking-wider border-2 transition-all duration-200 rounded-full",
activeFilter === filter
? "bg-neon text-black border-neon"
: "bg-transparent text-gray-400 border-white/20 hover:border-neon hover:text-neon"
)}
>
{filter}
</button>
))}
</div>

<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{projects.map((project) => (
{filteredProjects.map((project) => (
<div
key={project.id}
onClick={() => setSelectedProject(project)}
Expand Down
47 changes: 47 additions & 0 deletions components/sections/skills.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"use client";

const skillCategories = [
{
title: "Languages",
skills: ["TypeScript", "Go", "Python", "JavaScript", "SQL"],
},
{
title: "Frameworks",
skills: ["Next.js", "React", "Node.js", "Tailwind CSS", "Discord.js"],
},
{
title: "Tools",
skills: ["Git", "Docker", "Linux", "Raycast API", "GitHub Actions"],
},
];

export function Skills() {
return (
<section id="skills" className="py-24 relative border-t border-white/5">
<div className="container px-4 mx-auto max-w-4xl">
<div className="mb-12">
<h2 className="text-4xl md:text-5xl font-bold tracking-tighter mb-6 flex items-center gap-3">
<span className="text-neon">/</span> Stack
</h2>
</div>

<div className="space-y-8">
{skillCategories.map((category) => (
<div key={category.title}>
<h3 className="text-sm font-mono text-gray-500 uppercase tracking-wider mb-3">
{category.title}
</h3>
<div className="flex flex-wrap gap-x-4 gap-y-2">
{category.skills.map((skill) => (
<span key={skill} className="text-gray-300">
{skill}
</span>
))}
</div>
</div>
))}
</div>
</div>
</section>
);
}
13 changes: 0 additions & 13 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading