Built Who Am I page route

X-Lovable-Edit-ID: edt-cf20132e-babe-437e-9974-d084871d82d3
Co-authored-by: Damaj301damaj-lol <90093996+Damaj301damaj-lol@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot] 2026-05-19 15:13:03 +00:00
commit ba5e0a7418
3 changed files with 223 additions and 24 deletions

View file

@ -4,6 +4,7 @@ import { TooltipProvider } from "@/components/ui/tooltip";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Index from "./pages/Index";
import WhoAmI from "./pages/WhoAmI";
import NotFound from "./pages/NotFound";
const queryClient = new QueryClient();
@ -16,6 +17,7 @@ const App = () => (
<BrowserRouter>
<Routes>
<Route path="/" element={<Index />} />
<Route path="/whoami" element={<WhoAmI />} />
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
<Route path="*" element={<NotFound />} />
</Routes>

View file

@ -1,10 +1,11 @@
import { useRef, useState, useEffect, useCallback } from 'react';
import { Link } from 'react-router-dom';
import { GlassCard } from '@/components/GlassCard';
import avatar from '@/assets/avatar.png';
import { Home, MessageCircle, Rss, GitBranch, Search, ExternalLink } from 'lucide-react';
import { MessageCircle, Rss, GitBranch, Search, ExternalLink, ArrowUpRight } from 'lucide-react';
const items = [
{ icon: MessageCircle, label: 'Who Am I?', href: 'https://damaj.tech/site/whoami', desc: 'About me' },
{ icon: MessageCircle, label: 'Who Am I?', href: '/whoami', desc: 'About me', internal: true },
{ icon: Rss, label: 'Blog', href: 'https://damaj.tech/site/blog', desc: 'My writings' },
{ icon: GitBranch, label: 'Git Server', href: 'https://git.damaj.tech/', desc: 'Self-hosted Forgejo' },
{ icon: Search, label: 'SearXNG', href: 'https://searxng.damaj.tech/', desc: 'Private search' },
@ -151,28 +152,36 @@ const Index = () => {
const cardW = isMobile ? 110 : 130;
const cardH = isMobile ? 80 : 90;
return (
<a
key={item.label}
ref={(el) => { cardRefs.current[i] = el; }}
href={item.href}
target="_blank"
rel="noopener noreferrer"
className="absolute"
style={{
left: `calc(50% + ${x}px - ${cardW / 2}px)`,
top: `calc(50% + ${y}px - ${cardH / 2}px)`,
width: cardW,
}}
>
const cardContent = (
<GlassCard className="p-3 md:p-4 link-arrow-parent cursor-pointer">
<div className="flex items-start justify-between">
<item.icon className="w-4 h-4 text-primary mb-1.5" />
<ExternalLink className="w-3 h-3 text-muted-foreground link-arrow" />
{item.internal
? <ArrowUpRight className="w-3 h-3 text-muted-foreground link-arrow" />
: <ExternalLink className="w-3 h-3 text-muted-foreground link-arrow" />}
</div>
<p className="font-heading font-semibold text-foreground text-xs md:text-sm leading-tight">{item.label}</p>
<p className="text-[10px] text-muted-foreground mt-0.5 leading-tight">{item.desc}</p>
</GlassCard>
);
const commonProps = {
ref: (el: HTMLAnchorElement | null) => { cardRefs.current[i] = el; },
className: 'absolute',
style: {
left: `calc(50% + ${x}px - ${cardW / 2}px)`,
top: `calc(50% + ${y}px - ${cardH / 2}px)`,
width: cardW,
},
};
return item.internal ? (
<Link key={item.label} to={item.href} {...commonProps}>
{cardContent}
</Link>
) : (
<a key={item.label} href={item.href} target="_blank" rel="noopener noreferrer" {...commonProps}>
{cardContent}
</a>
);
})}

188
src/pages/WhoAmI.tsx Normal file
View file

@ -0,0 +1,188 @@
import { useRef, useState, useCallback } from 'react';
import { Link } from 'react-router-dom';
import { GlassCard } from '@/components/GlassCard';
import avatar from '@/assets/avatar.png';
import { ArrowLeft, MessageSquare, Mail, KeyRound, Code2, Heart, Server } from 'lucide-react';
const WhoAmI = () => {
const containerRef = useRef<HTMLDivElement>(null);
const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
const handleMouseMove = useCallback((e: React.MouseEvent) => {
setMousePos({ x: e.clientX, y: e.clientY });
}, []);
return (
<div
ref={containerRef}
onMouseMove={handleMouseMove}
className="min-h-screen bg-background relative overflow-hidden"
>
{/* Global mouse glow */}
<div
className="fixed pointer-events-none z-0"
style={{
left: mousePos.x,
top: mousePos.y,
width: 500,
height: 500,
transform: 'translate(-50%, -50%)',
background: 'radial-gradient(circle, hsl(25 95% 55% / 0.06) 0%, transparent 70%)',
}}
/>
<div className="relative z-10 max-w-3xl mx-auto px-4 py-10 md:py-16">
{/* Back link */}
<Link
to="/"
className="inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-primary transition-colors mb-8 font-mono"
>
<ArrowLeft className="w-4 h-4" />
back to hub
</Link>
{/* Header */}
<GlassCard className="p-6 md:p-8 mb-5">
<div className="flex flex-col sm:flex-row items-center sm:items-start gap-5">
<img
src={avatar}
alt="Mohamad"
className="w-24 h-24 md:w-28 md:h-28 rounded-full ring-2 ring-primary/30 shrink-0"
/>
<div className="text-center sm:text-left">
<p className="text-xs font-mono uppercase tracking-widest text-primary mb-1">
$ whoami
</p>
<h1 className="text-3xl md:text-4xl font-heading font-bold text-foreground">
Who Am I?
</h1>
<p className="text-muted-foreground mt-2 leading-relaxed">
My name is <span className="text-gradient font-semibold">Mohamad</span>, from the beautiful country of{' '}
<a href="https://en.wikipedia.org/wiki/Lebanon" target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">
Lebanon 🇱🇧
</a>.
</p>
</div>
</div>
</GlassCard>
{/* About cards */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-5">
<GlassCard className="p-5">
<Code2 className="w-5 h-5 text-primary mb-3" />
<h3 className="font-heading font-semibold text-foreground mb-1">Aspiring Engineer</h3>
<p className="text-sm text-muted-foreground leading-relaxed">
I spend my free time improving my skills in computing and dream of being a Computer Engineer 🖥.
</p>
</GlassCard>
<GlassCard className="p-5">
<Heart className="w-5 h-5 text-primary mb-3" />
<h3 className="font-heading font-semibold text-foreground mb-1">Open Source Lover</h3>
<p className="text-sm text-muted-foreground leading-relaxed">
I love reading source code and using open source software such as{' '}
<a href="https://en.wikipedia.org/wiki/Linux" target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">
Linux 🐧
</a>.
</p>
</GlassCard>
<GlassCard className="p-5 md:col-span-2">
<Server className="w-5 h-5 text-primary mb-3" />
<h3 className="font-heading font-semibold text-foreground mb-1">Sole Sysadmin</h3>
<p className="text-sm text-muted-foreground leading-relaxed">
I am currently the only sysadmin of this server. This website is very lightweight and was written 100% by hand using{' '}
<span className="font-mono text-primary">vim</span> ;)
</p>
</GlassCard>
</div>
{/* Contact section */}
<h2 className="text-xs font-mono uppercase tracking-widest text-muted-foreground mb-3 px-1">
Ways to get in touch
</h2>
<div className="grid grid-cols-1 gap-4">
<a
href="https://matrix.to/#/@mohamad:damaj.tech"
target="_blank"
rel="noopener noreferrer"
className="block"
>
<GlassCard className="p-5 link-arrow-parent cursor-pointer">
<div className="flex items-start gap-4">
<div className="p-2.5 rounded-lg bg-primary/10 ring-1 ring-primary/20">
<MessageSquare className="w-5 h-5 text-primary" />
</div>
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2 flex-wrap">
<h3 className="font-heading font-semibold text-foreground">Matrix</h3>
<span className="text-[10px] font-mono uppercase tracking-wider px-2 py-0.5 rounded-full bg-primary/10 text-primary">
Fastest
</span>
</div>
<p className="text-sm text-muted-foreground mt-1">
Secure, encrypted instant messaging.
</p>
<p className="text-sm font-mono text-primary/90 mt-1 truncate">
@mohamad:damaj.tech
</p>
</div>
</div>
</GlassCard>
</a>
<a
href="mailto:mohamad@damaj.tech"
className="block"
>
<GlassCard className="p-5 link-arrow-parent cursor-pointer">
<div className="flex items-start gap-4">
<div className="p-2.5 rounded-lg bg-primary/10 ring-1 ring-primary/20">
<Mail className="w-5 h-5 text-primary" />
</div>
<div className="flex-1 min-w-0">
<h3 className="font-heading font-semibold text-foreground">Email</h3>
<p className="text-sm text-muted-foreground mt-1">
Common and widely available. Business mail denied if you fail SPF, DKIM or DMARC.
</p>
<p className="text-sm font-mono text-primary/90 mt-1 truncate">
mohamad@damaj.tech
</p>
</div>
</div>
</GlassCard>
</a>
<a
href="https://git.damaj.tech/Damaj301damaj.gpg"
target="_blank"
rel="noopener noreferrer"
className="block"
>
<GlassCard className="p-5 link-arrow-parent cursor-pointer">
<div className="flex items-start gap-4">
<div className="p-2.5 rounded-lg bg-primary/10 ring-1 ring-primary/20">
<KeyRound className="w-5 h-5 text-primary" />
</div>
<div className="flex-1 min-w-0">
<h3 className="font-heading font-semibold text-foreground">GPG Key</h3>
<p className="text-sm text-muted-foreground mt-1">
Use my public key to encrypt messages or verify signed content.
</p>
</div>
</div>
</GlassCard>
</a>
</div>
{/* Footer */}
<p className="text-center text-xs text-muted-foreground font-mono mt-10">
damaj.tech / whoami
</p>
</div>
</div>
);
};
export default WhoAmI;