PO
portfolio-components
Production-ready portfolio components including Hero, About, Projects, Experience, Contact sections with modern design patterns.
Install
mkdir -p .claude/skills/portfolio-components && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/14196" && unzip -o skill.zip -d .claude/skills/portfolio-components && rm skill.zipInstalls to .claude/skills/portfolio-components
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Production-ready portfolio components including Hero, About, Projects, Experience, Contact sections with modern design patterns.128 charsno explicit “when” trigger
About this skill
Portfolio Components Library
Core Philosophy
Portfolio components should be memorable, professional, and performant. Each component tells a story about you as a developer. We build with composition, accessibility, and animation in mind.
Project Structure
components/
├── ui/ # Primitives (Button, Card, Badge)
│ ├── button.tsx
│ ├── card.tsx
│ ├── badge.tsx
│ ├── skeleton.tsx
│ └── icons.tsx
├── sections/ # Page sections
│ ├── hero.tsx
│ ├── about.tsx
│ ├── projects.tsx
│ ├── experience.tsx
│ ├── skills.tsx
│ ├── testimonials.tsx
│ └── contact.tsx
├── layout/ # Structure
│ ├── header.tsx
│ ├── footer.tsx
│ ├── navigation.tsx
│ └── mobile-nav.tsx
└── shared/ # Shared components
├── section-header.tsx
├── project-card.tsx
├── tech-stack.tsx
└── social-links.tsx
UI Primitives
Button Component
// components/ui/button.tsx
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
import { forwardRef } from "react";
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 rounded-lg font-medium transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-background disabled:pointer-events-none disabled:opacity-50 active:scale-95",
{
variants: {
variant: {
primary:
"bg-brand-500 text-white hover:bg-brand-600 focus:ring-brand-400",
secondary:
"bg-zinc-800 text-white hover:bg-zinc-700 focus:ring-zinc-600",
outline:
"border border-zinc-700 bg-transparent hover:bg-zinc-800 focus:ring-zinc-600",
ghost: "bg-transparent hover:bg-zinc-800/50 focus:ring-zinc-600",
link: "text-brand-400 underline-offset-4 hover:underline focus:ring-brand-400",
},
size: {
sm: "h-9 px-4 text-sm",
md: "h-11 px-6 text-base",
lg: "h-14 px-8 text-lg",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "primary",
size: "md",
},
},
);
interface ButtonProps
extends
React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
isLoading?: boolean;
}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
(
{ className, variant, size, isLoading, children, disabled, ...props },
ref,
) => {
return (
<button
ref={ref}
className={cn(buttonVariants({ variant, size }), className)}
disabled={disabled || isLoading}
{...props}
>
{isLoading && (
<svg
className="h-4 w-4 animate-spin"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
/>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
/>
</svg>
)}
{children}
</button>
);
},
);
Button.displayName = "Button";
Card Component
// components/ui/card.tsx
import { cn } from "@/lib/utils";
interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
hover?: boolean;
}
export function Card({
className,
hover = false,
children,
...props
}: CardProps) {
return (
<div
className={cn(
"rounded-2xl border border-zinc-800 bg-zinc-900/50 p-6",
hover &&
"transition-all duration-300 hover:border-zinc-700 hover:bg-zinc-900",
className,
)}
{...props}
>
{children}
</div>
);
}
export function CardHeader({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) {
return <div className={cn("mb-4", className)} {...props} />;
}
export function CardTitle({
className,
...props
}: React.HTMLAttributes<HTMLHeadingElement>) {
return <h3 className={cn("text-xl font-bold", className)} {...props} />;
}
export function CardDescription({
className,
...props
}: React.HTMLAttributes<HTMLParagraphElement>) {
return <p className={cn("text-sm text-muted", className)} {...props} />;
}
export function CardContent({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) {
return <div className={cn("", className)} {...props} />;
}
export function CardFooter({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) {
return (
<div className={cn("mt-4 flex items-center gap-4", className)} {...props} />
);
}
Badge Component
// components/ui/badge.tsx
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const badgeVariants = cva(
"inline-flex items-center rounded-full px-3 py-1 text-xs font-medium transition-colors",
{
variants: {
variant: {
default: "bg-zinc-800 text-zinc-300",
brand: "bg-brand-500/10 text-brand-400 border border-brand-500/20",
success: "bg-green-500/10 text-green-400 border border-green-500/20",
warning: "bg-yellow-500/10 text-yellow-400 border border-yellow-500/20",
outline: "border border-zinc-700 text-zinc-400",
},
},
defaultVariants: {
variant: "default",
},
},
);
interface BadgeProps
extends
React.HTMLAttributes<HTMLSpanElement>,
VariantProps<typeof badgeVariants> {}
export function Badge({ className, variant, ...props }: BadgeProps) {
return (
<span className={cn(badgeVariants({ variant }), className)} {...props} />
);
}
Section Components
Hero Section
// components/sections/hero.tsx
"use client";
import { motion } from "framer-motion";
import { ArrowRight, Download, Github, Linkedin, Twitter } from "lucide-react";
import { Button } from "@/components/ui/button";
import Image from "next/image";
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: { staggerChildren: 0.1, delayChildren: 0.3 },
},
};
const itemVariants = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 },
};
export function HeroSection() {
return (
<section className="relative min-h-screen overflow-hidden">
{/* Background Effects */}
<div className="absolute inset-0 -z-10">
<div className="absolute inset-0 bg-gradient-to-b from-brand-500/10 via-transparent to-transparent" />
<div className="absolute left-1/2 top-1/4 -z-10 h-[500px] w-[500px] -translate-x-1/2 rounded-full bg-brand-500/20 blur-[120px]" />
<div className="absolute bottom-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-zinc-700 to-transparent" />
</div>
<div className="container flex min-h-screen items-center py-20">
<motion.div
variants={containerVariants}
initial="hidden"
animate="visible"
className="grid gap-12 lg:grid-cols-2 lg:items-center"
>
{/* Text Content */}
<div className="order-2 lg:order-1">
{/* Status Badge */}
<motion.div variants={itemVariants} className="mb-6">
<span className="inline-flex items-center gap-2 rounded-full border border-green-500/20 bg-green-500/10 px-4 py-1.5 text-sm text-green-400">
<span className="relative flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-400 opacity-75" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-green-500" />
</span>
Available for work
</span>
</motion.div>
{/* Headline */}
<motion.h1
variants={itemVariants}
className="font-heading text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl"
>
Hi, I'm{" "}
<span className="bg-gradient-to-r from-brand-400 via-purple-400 to-pink-400 bg-clip-text text-transparent">
John Doe
</span>
</motion.h1>
{/* Subtitle */}
<motion.p
variants={itemVariants}
className="mt-4 text-xl text-muted sm:text-2xl"
>
Full-Stack Developer
</motion.p>
{/* Description */}
<motion.p
variants={itemVariants}
className="mt-6 max-w-lg text-lg text-zinc-400"
>
I build exceptional digital experiences with modern technologies.
Focused on React, Next.js, and creating interfaces that users
love.
</motion.p>
{/* CTA Buttons */}
<motion.div
variants={itemVariants}
className="mt-8 flex flex-col gap-4 sm:flex-row"
>
<Button size="lg" className="group">
View My Work
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</Button>
<Button variant="outline" size="lg">
<Download className="h-4 w-4" />
Download CV
</Button>
</motion.div>
{/* Social Links */}
<motion.div
variants={itemVariants}
className="mt-8 flex items-center gap-4"
>
<span className="text-sm text-zinc-500">Find me on</span>
<div className="flex gap-3">
{[
{
icon: Github,
href: "https://github.com/johndoe",
label: "GitHub",
},
{
icon: Linkedin,
href: "https:
---
*Content truncated.*