Proffesional freelance ui

This commit is contained in:
2026-01-21 02:52:49 +01:00
parent 3824322aa9
commit e226455c96
24 changed files with 1739 additions and 912 deletions
-22
View File
@@ -1,22 +0,0 @@
"use client";
import React from "react";
export default function Background({
children,
}: Readonly<{ children: React.ReactNode }>) {
return (
<div className="relative w-full min-h-screen overflow-hidden bg-black">
<div
className="absolute inset-0 bg-black"
style={{
backgroundImage:
"radial-gradient(circle, rgba(100, 116, 139, 0.5) 1px, transparent 1px)",
backgroundSize: "20px 20px",
}}
/>
<div className="relative z-50 overflow-y-scroll overflow-x-hidden">{children}</div>
</div>
);
}
-73
View File
@@ -1,73 +0,0 @@
import React from "react";
import Markdown from "react-markdown";
import remarkGfm from "remark-gfm";
import remarkBreaks from "remark-breaks";
import remarkMath from "remark-math";
import rehypeRaw from "rehype-raw";
import rehypeKatex from "rehype-katex";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { gruvboxDark } from "react-syntax-highlighter/dist/esm/styles/prism";
import "katex/dist/katex.min.css";
type MarkdownRendererProps = {
children: string;
};
export default function MarkdownRenderer({
children: markdown,
}: MarkdownRendererProps) {
return (
<Markdown
remarkPlugins={[remarkGfm, remarkMath, remarkBreaks]}
rehypePlugins={[rehypeRaw, rehypeKatex]}
components={{
code({ node, inline, className, children, ...props }: any) {
const match = /language-(\w+)/.exec(className || "");
return !inline && match ? (
<SyntaxHighlighter
style={gruvboxDark}
PreTag="div"
language={match[1]}
{...props}
>
{String(children).replace(/\n$/, "")}
</SyntaxHighlighter>
) : (
<code className={className} {...props}>
{children}
</code>
);
},
ul({ children, ...props }) {
return (
<ul
style={{ listStyleType: "disc", listStylePosition: "inside" }}
{...props}
>
{children}
</ul>
);
},
ol({ children, ...props }) {
return (
<ol
style={{ listStyleType: "decimal", listStylePosition: "inside" }}
{...props}
>
{children}
</ol>
);
},
li({ children, ...props }) {
return (
<li style={{ marginBottom: "4px" }} {...props}>
{children}
</li>
);
},
}}
>
{markdown}
</Markdown>
);
}
-35
View File
@@ -1,35 +0,0 @@
"use client";
import { usePathname } from "next/navigation";
import Link from "next/link";
export default function Navbar() {
const pathname = usePathname();
return (
<nav className="py-4 flex">
<div className="mx-auto flex">
<div className="space-x-4 text-white block font-bold">
<Link
href="/"
className={
"hover:slate-200 transition-colors duration-300" +
(pathname === "/" ? " slate-200" : "")
}
>
Home
</Link>
<Link
href="/pricing"
className={
"hover:slate-200 transition-colors duration-300" +
(pathname === "/pricing" ? " slate-200" : "")
}
>
Pricing
</Link>
</div>
</div>
</nav>
);
}
-178
View File
@@ -1,178 +0,0 @@
"use client";
import { useEffect, useState } from "react";
import { motion } from "framer-motion";
import { fadeInUp, fadeInUp2, staggerContainer } from "./effects";
type PinnedRepo = {
author: string;
name: string;
description: string;
language: string;
stars: number;
forks: number;
href?: string;
};
export function Repo({
name,
description: desc,
language: lang,
stars,
forks,
href,
}: PinnedRepo) {
return (
<motion.div
variants={fadeInUp2}
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.2 }}
className="group relative flex size-full overflow-hidden rounded-xl h-full border border-slate-400 hover:shadow-md transition-shadow duration-300 backdrop-blur-[2px]"
>
<div className="w-full">
<div className="rounded-xl border text-card-foreground shadow h-full bg-transparent border-none flex flex-col">
<div className="flex flex-col space-y-1.5 p-6 flex-grow">
<h3 className="tracking-tight text-base sm:text-lg font-semibold text-slate-300">
<a
href={href}
target="_blank"
rel="noreferrer"
className="hover:underline"
style={{ cursor: "pointer" }}
>
{name}
</a>
</h3>
<p className="text-xs sm:text-sm text-gray-300 line-clamp-2 mt-1">
{desc}
</p>
</div>
<div className="p-6 pt-0 mt-auto">
<div className="flex flex-wrap justify-between items-center gap-2">
<div className="flex items-center gap-2 sm:gap-4">
<div
className="flex items-center gap-1 text-xs sm:text-sm"
data-state="closed"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="lucide lucide-star text-gray-300 h-3 w-3 sm:h-4 sm:w-4"
>
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" />
</svg>
<span className="text-gray-300">{stars}</span>
</div>
<div
className="flex items-center gap-1 text-xs sm:text-sm"
data-state="closed"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="lucide lucide-git-fork text-gray-500 h-3 w-3 sm:h-4 sm:w-4"
>
<circle cx="12" cy="18" r="3" />
<circle cx="6" cy="6" r="3" />
<circle cx="18" cy="6" r="3" />
<path d="M18 9v2c0 .6-.4 1-1 1H7c-.6 0-1-.4-1-1V9" />
<path d="M12 12v3" />
</svg>
<span className="text-gray-300">{forks}</span>
</div>
</div>
{lang && (
<div
className="inline-flex items-center rounded-md border px-2.5 py-0.5 font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 text-foreground text-xs bg-slate-400/10 border-slate-400"
data-sentry-component="Badge"
data-sentry-source-file="badge.tsx"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="lucide lucide-code-xml h-3 w-3 mr-1"
>
<path d="m18 16 4-4-4-4" />
<path d="m6 8-4 4 4 4" />
<path d="m14.5 4-5 16" />
</svg>
{lang}
</div>
)}
</div>
</div>
</div>
</div>
</motion.div>
);
}
export default function PinnedRepos() {
try {
const [pinned, setPinned] = useState<PinnedRepo[]>([]);
useEffect(() => {
fetch("https://pinned.berrysauce.dev/get/selimaj-dev")
.then((r) => {
r.json()
.then((p) => {
setPinned(p);
})
.catch((e) => {
console.error(e);
});
})
.catch((e) => {
console.error(e);
});
}, []);
return (
<motion.div
variants={staggerContainer}
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.2 }}
className="grid grid-cols-1 sm:grid-cols-2 gap-4 sm:gap-6 bg-transparent"
>
{pinned &&
pinned.map((repo, i) => (
<Repo
key={i}
author={repo.author}
name={repo.name}
description={repo.description}
language={repo.language}
stars={repo.stars}
forks={repo.forks}
href={`https://github.com/${repo.author}/${repo.name}`}
/>
))}
</motion.div>
);
} catch (e: any) {
return <p>{e.toString()}</p>;
}
}
-29
View File
@@ -1,29 +0,0 @@
import { IconProp } from "@fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
export default function Skill({
skill,
icon,
classInsert,
}: {
skill: string;
icon: IconProp;
classInsert?: string;
}) {
return (
<div className="relative flex items-center justify-center group">
<span
className="absolute bottom-full mb-2 left-1/2 -translate-x-1/2
bg-black text-white text-sm px-2 py-1 rounded
opacity-0 group-hover:opacity-100 transition-opacity duration-300 whitespace-nowrap"
>
Skilled in {skill}
</span>
<FontAwesomeIcon
icon={icon}
className={`text-slate-400 ${classInsert} size-[2.3rem]`}
/>
</div>
);
}
-32
View File
@@ -1,32 +0,0 @@
import { easeOut, spring } from "framer-motion";
export const fadeInUp = {
hidden: { opacity: 0, y: 20 },
show: { opacity: 1, y: 0, transition: { duration: 0.5 } },
};
export const fadeInUp2 = {
hidden: { opacity: 0, y: 20 },
visible: {
opacity: 1,
y: 0,
transition: { duration: 0.4, ease: easeOut },
},
};
export const staggerContainer = {
show: {
transition: {
staggerChildren: 0.12,
},
},
};
export const popIn = {
hidden: { opacity: 0, scale: 0.8 },
show: {
opacity: 1,
scale: 1,
transition: { type: spring, stiffness: 120 },
},
};
+39
View File
@@ -0,0 +1,39 @@
import { ArrowRight } from "lucide-react";
import Link from "next/link";
export function CTASection() {
return (
<section className="py-24 bg-card/50 relative overflow-hidden">
{/* Background Effects */}
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-[800px] h-[400px] bg-accent/5 rounded-full blur-3xl" />
<div className="container mx-auto px-6 relative z-10">
<div className="max-w-3xl mx-auto text-center">
<h2 className="text-3xl md:text-5xl font-bold text-foreground mb-6">
Ready to build something{" "}
<span className="text-gradient-gold">extraordinary</span>?
</h2>
<p className="text-lg text-muted-foreground mb-10 max-w-xl mx-auto">
Whether you need a complex system, a modern web application, or specialized tooling,
I'm here to bring your vision to life.
</p>
<div className="flex flex-col sm:flex-row items-center justify-center gap-4">
<Link
href="/pricing"
className="group flex items-center gap-2 bg-accent text-accent-foreground px-8 py-4 rounded-xl font-medium hover:bg-accent/90 transition-all hover:gap-3 glow-gold"
>
View Pricing Plans
<ArrowRight className="w-4 h-4 transition-transform group-hover:translate-x-1" />
</Link>
<Link
href="/about"
className="flex items-center gap-2 text-foreground hover:text-accent font-medium transition-colors"
>
Learn more about me
</Link>
</div>
</div>
</div>
</section>
);
}
+97
View File
@@ -0,0 +1,97 @@
import { ArrowRight, Github, Linkedin, Youtube } from "lucide-react";
import Link from "next/link";
export function HeroSection() {
return (
<section className="relative min-h-[90vh] flex items-center justify-center overflow-hidden">
{/* Background Effects */}
<div className="absolute inset-0 bg-gradient-to-b from-background via-background to-card" />
<div className="absolute top-1/4 left-1/4 w-96 h-96 bg-accent/5 rounded-full blur-3xl" />
<div className="absolute bottom-1/4 right-1/4 w-96 h-96 bg-accent/10 rounded-full blur-3xl" />
<div className="container mx-auto px-6 relative z-10">
<div className="max-w-4xl mx-auto text-center">
{/* Status Badge */}
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full glass-card mb-8 animate-fade-in">
<span className="w-2 h-2 rounded-full bg-accent animate-pulse" />
<span className="text-sm text-muted-foreground">
Available for new projects
</span>
</div>
{/* Main Heading */}
<h1 className="text-4xl md:text-6xl lg:text-7xl font-bold mb-6 animate-fade-in-up">
<span className="text-foreground">Building</span>{" "}
<span className="text-gradient-gold">exceptional</span>
<br />
<span className="text-foreground">digital experiences</span>
</h1>
{/* Subheading */}
<p className="text-lg md:text-xl text-muted-foreground max-w-2xl mx-auto mb-10 animate-fade-in-delay-1">
I'm{" "}
<span className="text-foreground font-medium">Klesti Selimaj</span>,
a 16-year-old software engineer with 6+ years of experience.
Passionate about low-level systems, modern web apps, and crafting
tools that make a difference.
</p>
{/* CTA Buttons */}
<div className="flex flex-col sm:flex-row items-center justify-center gap-4 mb-12 animate-fade-in-delay-2">
<Link
href="/pricing"
className="group flex items-center gap-2 bg-accent text-accent-foreground px-8 py-4 rounded-xl font-medium hover:bg-accent/90 transition-all hover:gap-3"
>
Work with me
<ArrowRight className="w-4 h-4 transition-transform group-hover:translate-x-1" />
</Link>
<a
href="https://github.com/selimaj-dev"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 bg-secondary text-secondary-foreground px-8 py-4 rounded-xl font-medium hover:bg-secondary/80 transition-colors"
>
<Github className="w-4 h-4" />
View GitHub
</a>
</div>
{/* Social Links */}
<div className="flex items-center justify-center gap-6 animate-fade-in-delay-3">
<a
href="https://github.com/selimaj-dev"
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-accent transition-colors"
>
<Github className="w-5 h-5" />
</a>
<a
href="https://www.linkedin.com/in/klesti-selimaj-7a0162343/"
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-accent transition-colors"
>
<Linkedin className="w-5 h-5" />
</a>
<a
href="https://www.youtube.com/@0xkleo"
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-accent transition-colors"
>
<Youtube className="w-5 h-5" />
</a>
</div>
</div>
</div>
{/* Scroll Indicator */}
<div className="absolute bottom-8 left-1/2 -translate-x-1/2 animate-bounce">
<div className="w-6 h-10 border-2 border-muted-foreground/30 rounded-full flex items-start justify-center p-2">
<div className="w-1 h-2 bg-accent rounded-full animate-pulse" />
</div>
</div>
</section>
);
}
+159
View File
@@ -0,0 +1,159 @@
import { ExternalLink, Github, Star } from "lucide-react";
const projects = [
{
name: "DockShip",
description: "A powerful self-hosted Deployment Platform for modern teams.",
tech: ["TypeScript", "Docker", "React"],
stars: 1,
github: "https://github.com/orus-dev/dockship",
featured: true,
},
{
name: "OSUI",
description:
"A TUI library written in Rust for building beautiful terminal interfaces.",
tech: ["Rust", "TUI", "Systems"],
stars: 8,
github: "https://github.com/osui-rs/osui",
featured: true,
},
{
name: "Linear Linux",
description:
"Linux support for linear.app - bringing seamless project management to Linux users.",
tech: ["JavaScript", "Electron", "Linux"],
stars: 23,
github: "https://github.com/selimaj-dev/linear-linux",
featured: true,
},
{
name: "Saturn Client",
description:
"A Minecraft client full of customizability and free cosmetics.",
tech: ["Java", "Minecraft", "Gaming"],
stars: 3,
github: "https://github.com/saturnclientmc/saturnclient",
featured: false,
},
{
name: "Axiom Chat",
description: "A modern, feature-rich chat application built for teams.",
tech: ["TypeScript", "Real-time", "WebSockets"],
stars: 1,
github: "https://github.com/AxiomChat/axiom",
featured: false,
},
{
name: "Drift",
description: "An organized productivity app to get rid of distractions.",
tech: ["TypeScript", "Productivity", "Focus"],
stars: 1,
github: "https://github.com/orus-dev/drift",
featured: false,
},
];
export function ProjectsSection() {
return (
<section className="py-24 bg-card/50">
<div className="container mx-auto px-6">
{/* Section Header */}
<div className="max-w-2xl mb-16">
<span className="text-accent text-sm font-medium uppercase tracking-wider">
Portfolio
</span>
<h2 className="text-3xl md:text-4xl font-bold text-foreground mt-2 mb-4">
Featured Projects
</h2>
<p className="text-muted-foreground">
A selection of my open-source work and personal projects that
showcase my skills in systems programming, web development, and
tooling.
</p>
</div>
{/* Projects Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{projects.map((project, index) => (
<article
key={project.name}
className={"group glass-card rounded-2xl p-6 hover-lift"}
style={{ animationDelay: `${index * 100}ms` }}
>
{/* Header */}
<div className="flex items-start justify-between mb-4">
<div className="flex items-center gap-2">
{project.featured && (
<span className="px-2 py-1 text-xs font-medium bg-accent/10 text-accent rounded-full">
Featured
</span>
)}
</div>
<div className="flex items-center gap-1 text-muted-foreground">
<Star className="w-4 h-4" />
<span className="text-sm">{project.stars}</span>
</div>
</div>
{/* Content */}
<h3 className="text-xl font-semibold text-foreground mb-2 group-hover:text-accent transition-colors">
{project.name}
</h3>
<p className="text-muted-foreground text-sm mb-4 line-clamp-2">
{project.description}
</p>
{/* Tech Stack */}
<div className="flex flex-wrap gap-2 mb-6">
{project.tech.map((tech) => (
<span
key={tech}
className="px-2 py-1 text-xs font-mono bg-secondary text-secondary-foreground rounded"
>
{tech}
</span>
))}
</div>
{/* Actions */}
<div className="flex items-center gap-4">
<a
href={project.github}
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 text-sm text-muted-foreground hover:text-accent transition-colors"
>
<Github className="w-4 h-4" />
Source
</a>
<a
href={project.github}
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 text-sm text-muted-foreground hover:text-accent transition-colors"
>
<ExternalLink className="w-4 h-4" />
View
</a>
</div>
</article>
))}
</div>
{/* View All CTA */}
<div className="text-center mt-12">
<a
href="https://github.com/selimaj-dev?tab=repositories"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 text-accent hover:text-accent/80 font-medium transition-colors"
>
View all projects on GitHub
<ExternalLink className="w-4 h-4" />
</a>
</div>
</div>
</section>
);
}
+112
View File
@@ -0,0 +1,112 @@
const skills = [
{
category: "Languages",
items: [
{ name: "Rust", level: 90 },
{ name: "TypeScript", level: 95 },
{ name: "JavaScript", level: 95 },
{ name: "Python", level: 80 },
{ name: "Go", level: 75 },
{ name: "Java", level: 85 },
],
},
{
category: "Frontend",
items: [
{ name: "React", level: 95 },
{ name: "Next.js", level: 85 },
{ name: "Tailwind CSS", level: 95 },
{ name: "Framer Motion", level: 80 },
],
},
{
category: "Systems & Tools",
items: [
{ name: "Linux", level: 90 },
{ name: "Docker", level: 85 },
{ name: "Git", level: 95 },
{ name: "TUI Development", level: 90 },
],
},
];
const stats = [
{ label: "Years Experience", value: "6+" },
{ label: "GitHub Followers", value: "32" },
{ label: "Open Source Projects", value: "10+" },
{ label: "Technologies Mastered", value: "15+" },
];
export function SkillsSection() {
return (
<section className="py-24 bg-background">
<div className="container mx-auto px-6">
{/* Stats */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-6 mb-20">
{stats.map((stat, index) => (
<div
key={stat.label}
className="text-center p-6 glass-card rounded-2xl hover-lift"
style={{ animationDelay: `${index * 100}ms` }}
>
<div className="text-3xl md:text-4xl font-bold text-gradient-gold mb-2">
{stat.value}
</div>
<div className="text-sm text-muted-foreground">{stat.label}</div>
</div>
))}
</div>
{/* Section Header */}
<div className="max-w-2xl mb-16">
<span className="text-accent text-sm font-medium uppercase tracking-wider">
Expertise
</span>
<h2 className="text-3xl md:text-4xl font-bold text-foreground mt-2 mb-4">
Technical Skills
</h2>
<p className="text-muted-foreground">
From low-level systems programming to modern web development, I
bring a diverse skill set to every project.
</p>
</div>
{/* Skills Grid */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{skills.map((category, categoryIndex) => (
<div
key={category.category}
className="glass-card rounded-2xl p-6"
style={{ animationDelay: `${categoryIndex * 150}ms` }}
>
<h3 className="text-lg font-semibold text-foreground mb-6 flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-accent" />
{category.category}
</h3>
<div className="space-y-4">
{category.items.map((skill) => (
<div key={skill.name}>
<div className="flex justify-between text-sm mb-2">
<span className="text-foreground font-medium">
{skill.name}
</span>
<span className="text-muted-foreground">
{skill.level}%
</span>
</div>
<div className="h-1.5 bg-secondary rounded-full overflow-hidden">
<div
className="h-full bg-accent rounded-full transition-all duration-1000 ease-out"
style={{ width: `${skill.level}%` }}
/>
</div>
</div>
))}
</div>
</div>
))}
</div>
</div>
</section>
);
}
+118
View File
@@ -0,0 +1,118 @@
import Link from "next/link";
export function Footer() {
const currentYear = new Date().getFullYear();
return (
<footer className="border-t border-border bg-card/50">
<div className="container mx-auto px-6 py-12">
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
{/* Brand */}
<div className="md:col-span-2">
<Link href="/" className="flex items-center gap-2 mb-4">
<img
className="w-8 h-8 rounded-lg bg-accent flex items-center justify-center"
src="/logo.png"
alt="Logo"
/>
<span className="font-semibold text-foreground">selimaj.dev</span>
</Link>
<p className="text-muted-foreground text-sm max-w-sm">
Building digital experiences with precision and passion.
Specializing in low-level systems, modern web applications, and
everything in between.
</p>
</div>
{/* Quick Links */}
<div>
<h4 className="font-medium text-foreground mb-4">Quick Links</h4>
<ul className="space-y-2">
<li>
<Link
href="/"
className="text-sm text-muted-foreground hover:text-accent transition-colors"
>
Home
</Link>
</li>
<li>
<Link
href="/about"
className="text-sm text-muted-foreground hover:text-accent transition-colors"
>
About
</Link>
</li>
<li>
<Link
href="/pricing"
className="text-sm text-muted-foreground hover:text-accent transition-colors"
>
Hire Me
</Link>
</li>
</ul>
</div>
{/* Connect */}
<div>
<h4 className="font-medium text-foreground mb-4">Connect</h4>
<ul className="space-y-2">
<li>
<a
href="https://github.com/selimaj-dev"
target="_blank"
rel="noopener noreferrer"
className="text-sm text-muted-foreground hover:text-accent transition-colors"
>
GitHub
</a>
</li>
<li>
<a
href="https://www.linkedin.com/in/klesti-selimaj-7a0162343/"
target="_blank"
rel="noopener noreferrer"
className="text-sm text-muted-foreground hover:text-accent transition-colors"
>
LinkedIn
</a>
</li>
<li>
<a
href="https://www.youtube.com/@0xkleo"
target="_blank"
rel="noopener noreferrer"
className="text-sm text-muted-foreground hover:text-accent transition-colors"
>
YouTube
</a>
</li>
<li>
<a
href="https://www.instagram.com/selimaj.dev/"
target="_blank"
rel="noopener noreferrer"
className="text-sm text-muted-foreground hover:text-accent transition-colors"
>
Instagram
</a>
</li>
</ul>
</div>
</div>
<div className="border-t border-border mt-8 pt-8 flex flex-col md:flex-row justify-between items-center gap-4">
<p className="text-sm text-muted-foreground">
© {currentYear} Klesti Selimaj. All rights reserved.
</p>
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<span className="w-2 h-2 rounded-full bg-accent animate-pulse" />
Available for work
</div>
</div>
</div>
</footer>
);
}
+19
View File
@@ -0,0 +1,19 @@
"use client";
import { ReactNode } from "react";
import { Footer } from "./Footer";
import { Navbar } from "./Navbar";
interface LayoutProps {
children: ReactNode;
}
export function Layout({ children }: LayoutProps) {
return (
<div className="min-h-screen flex flex-col bg-background dark">
<Navbar />
<main className="flex-1 pt-16">{children}</main>
<Footer />
</div>
);
}
+152
View File
@@ -0,0 +1,152 @@
"use client";
import { cn } from "@/lib/utils";
import { CoffeeIcon, Github, Menu, X } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useState } from "react";
import { motion } from "framer-motion";
const navLinks = [
{ href: "/", label: "Home" },
{ href: "/about", label: "About" },
{ href: "/pricing", label: "Hire Me" },
];
export function Navbar() {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const pathname = usePathname();
return (
<header className="fixed top-0 left-0 right-0 z-50 glass-card border-b">
<nav className="container mx-auto px-6 h-16 flex items-center justify-between">
<Link href="/" className="flex items-center gap-2 group">
<img
className="w-8 h-8 rounded-lg bg-accent flex items-center justify-center"
src="/logo.png"
alt="Logo"
/>
<span className="font-semibold text-foreground group-hover:text-accent transition-colors">
selimaj.dev
</span>
</Link>
{/* Desktop Nav */}
<ul className="hidden md:flex items-center gap-8">
{navLinks.map((link) => {
const isActive = pathname === link.href;
return (
<li key={link.href}>
<Link
href={link.href}
className={cn(
"text-sm font-medium transition-colors hover:text-accent relative py-2",
isActive ? "text-accent" : "text-muted-foreground",
)}
>
{link.label}
{isActive && (
<span className="absolute bottom-0 left-0 right-0 h-0.5 bg-accent rounded-full" />
)}
</Link>
</li>
);
})}
</ul>
<div className="hidden md:flex items-center gap-4">
<motion.li
animate={{ y: [0, -3, 0] }}
transition={{ repeat: Infinity, duration: 3 }}
>
<a href="https://ko-fi.com/X8X01OX1WR" target="_blank">
<motion.span
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
className="text-muted-foreground hover:text-foreground transition-colors"
>
<CoffeeIcon />
</motion.span>
</a>
</motion.li>
<a
href="https://github.com/selimaj-dev"
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<Github />
</a>
<Link
href="/pricing"
className="bg-accent text-accent-foreground px-4 py-2 rounded-lg text-sm font-medium hover:bg-accent/90 transition-colors"
>
Get in Touch
</Link>
</div>
{/* Mobile Menu Button */}
<button
className="md:hidden text-foreground p-2"
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
>
{mobileMenuOpen ? (
<X className="w-5 h-5" />
) : (
<Menu className="w-5 h-5" />
)}
</button>
</nav>
{/* Mobile Menu */}
{mobileMenuOpen && (
<div className="md:hidden glass-card border-t animate-fade-in">
<ul className="container mx-auto px-6 py-4 space-y-4">
{navLinks.map((link) => (
<li key={link.href}>
<Link
href={link.href}
onClick={() => setMobileMenuOpen(false)}
className={cn(
"block text-sm font-medium transition-colors",
location.pathname === link.href
? "text-accent"
: "text-muted-foreground",
)}
>
{link.label}
</Link>
</li>
))}
<li>
<Link
href="https://github.com/selimaj-dev"
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<Github />
</Link>
</li>
<motion.li
animate={{ y: [0, -3, 0] }}
transition={{ repeat: Infinity, duration: 3 }}
>
<a href="https://ko-fi.com/X8X01OX1WR" target="_blank">
<motion.span
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
className="text-muted-foreground hover:text-foreground transition-colors"
>
<CoffeeIcon />
</motion.span>
</a>
</motion.li>
</ul>
</div>
)}
</header>
);
}