The portfolio is built with a clean, well-organized React + TypeScript component architecture that separates concerns between pages, reusable UI components, and custom features.
Directory Structure
The component architecture follows a three-tier organization:
src/
├── pages/ # Top-level page components
│ ├── home.tsx
│ ├── projects.tsx
│ ├── layout.tsx
│ └── blog/
│ ├── index.tsx
│ └── [slug].tsx
├── components/ # Reusable UI components
│ └── ui/
│ └── button.tsx
└── custom/ # Custom feature components
└── nav.tsx
Component Categories
Pages Top-level route components that define page structure and content
UI Components Reusable, styled components following design system patterns
Custom Application-specific components with business logic
Design Patterns
Component Composition
The portfolio uses React composition patterns to build complex UIs from simple, reusable pieces:
import { Layout } from "@/pages/layout" ;
import { Navbar } from "@/custom/nav" ;
import { Button } from "@/components/ui/button" ;
// Layout wraps all pages and provides consistent structure
function App () {
return (
< Layout >
< Navbar />
{ /* Page content */ }
</ Layout >
);
}
Type Safety
All components are built with TypeScript for complete type safety:
type BannerTheme = "swe" | "sports" | "hxi" ;
const bannerConfig : Record < BannerTheme , BannerConfig > = {
swe: {
text: "breaking, building & engineering things" ,
bgColor: "bg-[#CECEDC]" ,
// ...
},
};
Variant-Based Styling
UI components use class-variance-authority (CVA) for type-safe variant-based styling:
const buttonVariants = cva (
"inline-flex items-center justify-center gap-2 whitespace-nowrap" ,
{
variants: {
variant: {
default: "bg-primary text-primary-foreground" ,
destructive: "bg-destructive text-white" ,
outline: "border bg-background" ,
},
size: {
default: "h-9 px-4 py-2" ,
sm: "h-8 gap-1.5 px-3" ,
lg: "h-10 px-6" ,
},
},
}
);
Import Patterns
The portfolio uses TypeScript path aliases for clean imports:
UI Components
Custom Components
Pages
import { Button } from "@/components/ui/button" ;
import { cn } from "@/lib/utils" ;
The @/ prefix is configured in tsconfig.json to map to the src/ directory, enabling absolute imports throughout the codebase.
Animation & Motion
Components leverage Framer Motion for smooth, performant animations:
import { motion } from "framer-motion" ;
function Home () {
return (
< motion.div
initial = { { opacity: 0 , y: 50 } }
animate = { { opacity: 1 , y: 0 } }
transition = { { duration: 0.8 , ease: [ 0.25 , 0.1 , 0.25 , 1 ] } }
>
{ /* Content */ }
</ motion.div >
);
}
Common Animation Patterns
Page transitions : opacity: 0 → 1 with y: 50 → 0 slide-up effect
Staggered lists : Sequential delays using index * 0.1 for cascade effect
Hover states : CSS transitions for underline effects and opacity changes
Pulse animations : CSS animate-pulse for status indicators
Pages use react-helmet-async for dynamic meta tag management:
import { Helmet } from "react-helmet-async" ;
function Home () {
return (
<>
< Helmet >
< title > abena | swe </ title >
< meta name = "description" content = "hi, i'm Abena..." />
< meta property = "og:title" content = "Abena — swe" />
< meta property = "og:image" content = "https://..." />
</ Helmet >
{ /* Page content */ }
</>
);
}
Next Steps
UI Components Explore reusable UI components and their props
Layout Components Learn about layout structure and navigation