Merge pull request #1 from Quinta0/refactor

update
This commit was merged in pull request #1.
This commit is contained in:
Quinta
2025-06-26 15:49:03 +02:00
committed by GitHub
8 changed files with 839 additions and 98 deletions
+6 -1
View File
@@ -1,3 +1,8 @@
{ {
"extends": ["next/core-web-vitals", "next/typescript"] "extends": ["next/core-web-vitals", "next/typescript"],
"rules": {
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/no-explicit-any": "warn",
"react-hooks/exhaustive-deps": "warn"
}
} }
+24 -27
View File
@@ -1,36 +1,33 @@
import type { Metadata } from "next"; import type { Metadata } from 'next'
import localFont from "next/font/local"; import './globals.css'
import "./globals.css";
import React from "react";
const geistSans = localFont({
src: "./fonts/GeistVF.woff",
variable: "--font-geist-sans",
weight: "100 900",
});
const geistMono = localFont({
src: "./fonts/GeistMonoVF.woff",
variable: "--font-geist-mono",
weight: "100 900",
});
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Quintavalle Pietro", title: 'Pietro Quintavalle - Economics Student & Developer',
description: "My personal website", description: 'Economics student at USI with extensive data analytics and web development expertise. Google-certified in Data Analytics and IT Support.',
}; keywords: ['Pietro Quintavalle', 'Economics', 'Data Analytics', 'Web Development', 'Switzerland', 'USI'],
authors: [{ name: 'Pietro Quintavalle' }],
openGraph: {
title: 'Pietro Quintavalle - Economics Student & Developer',
description: 'Economics student at USI with extensive data analytics and web development expertise.',
url: 'https://your-domain.com',
siteName: 'Pietro Quintavalle Portfolio',
type: 'website',
},
twitter: {
card: 'summary_large_image',
title: 'Pietro Quintavalle - Economics Student & Developer',
description: 'Economics student at USI with extensive data analytics and web development expertise.',
},
}
export default function RootLayout({ export default function RootLayout({
children, children,
}: Readonly<{ }: {
children: React.ReactNode; children: React.ReactNode
}>) { }) {
return ( return (
<html lang="en"> <html lang="en">
<body <body>{children}</body>
className={`${geistSans.variable} ${geistMono.variable} antialiasing`}
>
{children}
</body>
</html> </html>
); )
} }
+721
View File
@@ -0,0 +1,721 @@
'use client';
import React, { useState, useEffect } from 'react';
import { Github, Linkedin, Mail, ExternalLink, ChevronDown, Code, Database, BarChart3, Globe, Award, GraduationCap, Image, ExternalLink as LinkIcon } from 'lucide-react';
// Types
interface NordColors {
bg: string;
bgLight: string;
bgLighter: string;
bgLightest: string;
text: string;
textMuted: string;
accent: string;
blue: string;
darkBlue: string;
cyan: string;
green: string;
yellow: string;
orange: string;
red: string;
purple: string;
}
interface Project {
title: string;
period: string;
description: string;
tech: string[];
icon: React.ReactNode;
status: string;
images: string[];
features: string[];
github?: string;
demo?: string;
}
interface Education {
institution: string;
degree: string;
period: string;
status: string;
}
interface ProjectGalleryProps {
project: Project;
onClose: () => void;
}
const Portfolio: React.FC = () => {
const [activeSection, setActiveSection] = useState<string>('home');
const [scrolled, setScrolled] = useState<boolean>(false);
const [showProjectGallery, setShowProjectGallery] = useState<Project | false>(false);
// Nord Color Palette
const nordColors: NordColors = {
bg: '#2E3440',
bgLight: '#3B4252',
bgLighter: '#434C5E',
bgLightest: '#4C566A',
text: '#D8DEE9',
textMuted: 'rgba(216, 222, 233, 0.6)',
accent: '#88C0D0',
blue: '#81A1C1',
darkBlue: '#5E81AC',
cyan: '#8FBCBB',
green: '#A3BE8C',
yellow: '#EBCB8B',
orange: '#D08770',
red: '#BF616A',
purple: '#B48EAD'
};
useEffect(() => {
const handleScroll = (): void => {
setScrolled(window.scrollY > 50);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
const skills: Record<string, string[]> = {
'Data & Analytics': ['Python', 'R', 'SQL', 'Statistical Analysis', 'Data Visualization', 'Business Intelligence'],
'Web Development': ['JavaScript', 'TypeScript', 'React', 'Next.js', 'HTML5', 'CSS3', 'Tailwind CSS'],
'Backend & Tools': ['Flask', 'Express', 'MongoDB', 'SQLite', 'Git', 'Linux'],
'Other': ['Java', 'LaTeX', 'Project Planning', 'Financial Analysis']
};
const projects: Project[] = [
{
title: 'Valgo - Algorithm Visualizer',
period: 'Jun 2024 - Present',
description: 'Interactive web application designed to help users understand and visualize various sorting algorithms. Built with Next.js and React to make learning algorithms more engaging and intuitive.',
tech: ['Next.js', 'React', 'JavaScript', 'Algorithm Visualization'],
icon: <Code className="w-6 h-6" />,
status: 'Live',
images: [
'https://via.placeholder.com/600x400/81A1C1/2E3440?text=Algorithm+Visualizer',
'https://via.placeholder.com/600x400/88C0D0/2E3440?text=Sorting+Demo',
'https://via.placeholder.com/600x400/5E81AC/2E3440?text=Interactive+UI'
],
features: ['Real-time algorithm visualization', 'Multiple sorting algorithms', 'Step-by-step breakdown', 'Performance comparison'],
github: 'https://github.com/Quinta0/valgo',
demo: 'https://valgo-demo.vercel.app'
},
{
title: 'Boston Housing Price Prediction',
period: 'May 2024 - Present',
description: 'Machine learning model to predict housing prices in the Boston area based on various features such as crime rate, average number of rooms per dwelling, and accessibility to radial highways.',
tech: ['Python', 'Machine Learning', 'Data Analysis', 'Statistical Modeling'],
icon: <BarChart3 className="w-6 h-6" />,
status: 'In Progress',
images: [
'https://via.placeholder.com/600x400/A3BE8C/2E3440?text=Data+Visualization',
'https://via.placeholder.com/600x400/EBCB8B/2E3440?text=ML+Model',
'https://via.placeholder.com/600x400/D08770/2E3440?text=Results+Analysis'
],
features: ['Predictive modeling', 'Feature engineering', 'Data visualization', 'Statistical analysis'],
github: 'https://github.com/Quinta0/boston-housing'
},
{
title: 'Forest Fire Simulation',
period: 'Mar 2024 - Present',
description: 'Probability & Statistics course project modeling the spread of forest fires over a grid. Accounts for vegetation types, terrain elevation, wind patterns, humidity levels, and spontaneous ignition.',
tech: ['Python', 'Statistical Modeling', 'Simulation', 'Data Science'],
icon: <Database className="w-6 h-6" />,
status: 'Academic Project',
images: [
'https://via.placeholder.com/600x400/BF616A/2E3440?text=Fire+Simulation',
'https://via.placeholder.com/600x400/B48EAD/2E3440?text=Statistical+Model',
'https://via.placeholder.com/600x400/8FBCBB/2E3440?text=Data+Analysis'
],
features: ['Monte Carlo simulation', 'Environmental factors modeling', 'Statistical analysis', 'Visualization tools'],
github: 'https://github.com/Quinta0/forest-fire-sim'
}
];
const education: Education[] = [
{
institution: 'USI Università della Svizzera italiana',
degree: "Bachelor's degree Economics",
period: 'Sep 2024 - Jun 2027',
status: 'Current'
},
{
institution: 'USI Università della Svizzera italiana',
degree: 'Bachelor of Science - BS Informatics',
period: 'Jan 2022 - Jan 2024',
status: 'Completed'
},
{
institution: 'Scuola cantonale di commercio',
degree: 'Maturità Cantonale e AFC Economics',
period: 'Sep 2017 - Jun 2021',
status: 'GPA: 4.5/5'
}
];
const certificates: string[] = [
'Google Data Analytics Professional Certificate',
'Google IT Support Professional Certificate',
'IT Security: Defense against the digital dark arts',
'Python for Data Science, AI & Development'
];
const scrollToSection = (sectionId: string): void => {
document.getElementById(sectionId)?.scrollIntoView({ behavior: 'smooth' });
setActiveSection(sectionId);
};
const ProjectGallery: React.FC<ProjectGalleryProps> = ({ project, onClose }) => (
<div
className="fixed inset-0 z-50 flex items-center justify-center p-4"
style={{ backgroundColor: 'rgba(46, 52, 64, 0.95)' }}
onClick={onClose}
>
<div
className="max-w-4xl w-full max-h-[90vh] overflow-y-auto rounded-lg"
style={{ backgroundColor: nordColors.bgLight }}
onClick={(e: React.MouseEvent) => e.stopPropagation()}
>
<div className="p-6">
<div className="flex justify-between items-start mb-6">
<div>
<h3 className="text-2xl font-bold mb-2" style={{ color: nordColors.text }}>
{project.title}
</h3>
<div className="flex items-center gap-4">
<span className="text-sm" style={{ color: nordColors.blue }}>
{project.period}
</span>
<span
className="px-3 py-1 rounded-full text-xs"
style={{
backgroundColor: nordColors.darkBlue,
color: nordColors.text
}}
>
{project.status}
</span>
</div>
</div>
<button
onClick={onClose}
className="text-2xl hover:opacity-70"
style={{ color: nordColors.textMuted }}
>
×
</button>
</div>
{/* Project Images */}
<div className="grid md:grid-cols-2 gap-4 mb-6">
{project.images.map((image: string, idx: number) => (
<div key={idx} className="aspect-video rounded-lg overflow-hidden">
<img
src={image}
alt={`${project.title} screenshot ${idx + 1}`}
className="w-full h-full object-cover"
/>
</div>
))}
</div>
{/* Description */}
<div className="mb-6">
<h4 className="text-lg font-semibold mb-3" style={{ color: nordColors.blue }}>
About This Project
</h4>
<p className="leading-relaxed" style={{ color: nordColors.textMuted }}>
{project.description}
</p>
</div>
{/* Features */}
<div className="mb-6">
<h4 className="text-lg font-semibold mb-3" style={{ color: nordColors.blue }}>
Key Features
</h4>
<div className="grid md:grid-cols-2 gap-2">
{project.features.map((feature: string, idx: number) => (
<div key={idx} className="flex items-center">
<div
className="w-2 h-2 rounded-full mr-3"
style={{ backgroundColor: nordColors.accent }}
></div>
<span style={{ color: nordColors.text }}>{feature}</span>
</div>
))}
</div>
</div>
{/* Tech Stack */}
<div className="mb-6">
<h4 className="text-lg font-semibold mb-3" style={{ color: nordColors.blue }}>
Technology Stack
</h4>
<div className="flex flex-wrap gap-2">
{project.tech.map((tech: string) => (
<span
key={tech}
className="px-3 py-1 rounded text-sm"
style={{
backgroundColor: nordColors.bg,
color: nordColors.accent
}}
>
{tech}
</span>
))}
</div>
</div>
{/* Links */}
<div className="flex gap-4">
{project.github && (
<a
href={project.github}
className="flex items-center gap-2 px-4 py-2 rounded hover:opacity-80 transition-opacity"
style={{ backgroundColor: nordColors.bgLighter, color: nordColors.text }}
target="_blank"
rel="noopener noreferrer"
>
<Github className="w-4 h-4" />
View Code
</a>
)}
{project.demo && (
<a
href={project.demo}
className="flex items-center gap-2 px-4 py-2 rounded hover:opacity-80 transition-opacity"
style={{ backgroundColor: nordColors.darkBlue, color: nordColors.text }}
target="_blank"
rel="noopener noreferrer"
>
<LinkIcon className="w-4 h-4" />
Live Demo
</a>
)}
</div>
</div>
</div>
</div>
);
return (
<div className="min-h-screen font-sans" style={{ backgroundColor: nordColors.bg, color: nordColors.text }}>
{/* Navigation */}
<nav
className="fixed top-0 w-full z-40 transition-all duration-300"
style={{
backgroundColor: scrolled ? 'rgba(46, 52, 64, 0.95)' : 'transparent',
borderBottom: scrolled ? `1px solid ${nordColors.bgLight}` : 'none',
backdropFilter: scrolled ? 'blur(10px)' : 'none'
}}
>
<div className="max-w-6xl mx-auto px-6 py-4">
<div className="flex justify-between items-center">
<div className="text-xl font-bold" style={{ color: nordColors.accent }}>
Pietro Quintavalle
</div>
<div className="hidden md:flex space-x-8">
{['Home', 'About', 'Projects', 'Education', 'Contact'].map((item: string) => (
<button
key={item}
onClick={() => scrollToSection(item.toLowerCase())}
className="transition-colors hover:opacity-80"
style={{
color: activeSection === item.toLowerCase() ? nordColors.accent : nordColors.text
}}
>
{item}
</button>
))}
</div>
</div>
</div>
</nav>
{/* Hero Section */}
<section id="home" className="min-h-screen flex items-center justify-center relative">
<div className="text-center max-w-4xl mx-auto px-6">
<div className="mb-8">
<h1 className="text-5xl md:text-7xl font-bold mb-4">
<span style={{ color: nordColors.text }}>Pietro</span>
<span className="ml-4" style={{ color: nordColors.accent }}>Quintavalle</span>
</h1>
<div className="text-xl md:text-2xl mb-6" style={{ color: nordColors.blue }}>
Economics Student • Data Analytics • Web Development
</div>
<p className="text-lg max-w-2xl mx-auto leading-relaxed" style={{ color: nordColors.textMuted }}>
Passionate about the intersection of economics and technology, exploring how data and code can solve real-world problems.
</p>
</div>
<div className="flex justify-center space-x-6 mb-12">
<a
href="https://github.com/Quinta0"
className="p-3 rounded-full transition-colors hover:opacity-80"
style={{ backgroundColor: nordColors.bgLight }}
target="_blank"
rel="noopener noreferrer"
>
<Github className="w-6 h-6" style={{ color: nordColors.text }} />
</a>
<a
href="https://www.linkedin.com/in/pietro-quintavalle-996b96267/"
className="p-3 rounded-full transition-colors hover:opacity-80"
style={{ backgroundColor: nordColors.bgLight }}
target="_blank"
rel="noopener noreferrer"
>
<Linkedin className="w-6 h-6" style={{ color: nordColors.text }} />
</a>
<a
href="mailto:0pietroquintavalle0@gmail.com"
className="p-3 rounded-full transition-colors hover:opacity-80"
style={{ backgroundColor: nordColors.bgLight }}
>
<Mail className="w-6 h-6" style={{ color: nordColors.text }} />
</a>
<a
href="https://quinta0.github.io/whoami/"
className="p-3 rounded-full transition-colors hover:opacity-80"
style={{ backgroundColor: nordColors.bgLight }}
target="_blank"
rel="noopener noreferrer"
>
<Globe className="w-6 h-6" style={{ color: nordColors.text }} />
</a>
</div>
</div>
<div className="absolute bottom-8 left-1/2 transform -translate-x-1/2 animate-bounce">
<ChevronDown className="w-6 h-6" style={{ color: nordColors.blue }} />
</div>
</section>
{/* About Section */}
<section id="about" className="py-20" style={{ backgroundColor: 'rgba(59, 66, 82, 0.3)' }}>
<div className="max-w-6xl mx-auto px-6">
<h2 className="text-4xl font-bold text-center mb-16" style={{ color: nordColors.accent }}>
About Me
</h2>
<div className="grid md:grid-cols-2 gap-12 items-center">
<div>
<p className="text-lg leading-relaxed mb-6" style={{ color: nordColors.text }}>
I'm an Economics student at USI with extensive experience in data analytics and web development.
My journey combines analytical thinking with technical skills to create meaningful solutions.
</p>
<p className="text-lg leading-relaxed mb-6" style={{ color: nordColors.text }}>
Google-certified in Data Analytics and IT Support, I bring proven expertise in Python, R, SQL,
and modern web technologies like Next.js and React.
</p>
<div className="flex flex-wrap gap-3">
<span
className="px-3 py-1 rounded-full text-sm"
style={{ backgroundColor: nordColors.darkBlue, color: nordColors.text }}
>
Italian (Native)
</span>
<span
className="px-3 py-1 rounded-full text-sm"
style={{ backgroundColor: nordColors.darkBlue, color: nordColors.text }}
>
English (C2)
</span>
<span
className="px-3 py-1 rounded-full text-sm"
style={{ backgroundColor: nordColors.darkBlue, color: nordColors.text }}
>
Switzerland 🇨🇭
</span>
</div>
</div>
<div className="space-y-6">
{Object.entries(skills).map(([category, skillList]: [string, string[]]) => (
<div
key={category}
className="p-6 rounded-lg border"
style={{
backgroundColor: nordColors.bg,
borderColor: nordColors.bgLight
}}
>
<h3 className="text-xl font-semibold mb-3" style={{ color: nordColors.blue }}>
{category}
</h3>
<div className="flex flex-wrap gap-2">
{skillList.map((skill: string) => (
<span
key={skill}
className="px-3 py-1 rounded text-sm"
style={{
backgroundColor: nordColors.bgLighter,
color: nordColors.text
}}
>
{skill}
</span>
))}
</div>
</div>
))}
</div>
</div>
</div>
</section>
{/* Projects Section */}
<section id="projects" className="py-20">
<div className="max-w-6xl mx-auto px-6">
<h2 className="text-4xl font-bold text-center mb-16" style={{ color: nordColors.accent }}>
Featured Projects
</h2>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
{projects.map((project: Project, index: number) => (
<div
key={index}
className="p-6 rounded-lg border transition-colors hover:opacity-90 cursor-pointer"
style={{
backgroundColor: nordColors.bgLight,
borderColor: nordColors.bgLighter
}}
onClick={() => setShowProjectGallery(project)}
>
<div className="flex items-center mb-4">
<div
className="p-2 rounded-lg mr-3"
style={{ backgroundColor: nordColors.darkBlue }}
>
{project.icon}
</div>
<div>
<h3 className="text-xl font-semibold" style={{ color: nordColors.text }}>
{project.title}
</h3>
<p className="text-sm" style={{ color: nordColors.blue }}>
{project.period}
</p>
</div>
</div>
<p className="leading-relaxed mb-4" style={{ color: nordColors.textMuted }}>
{project.description}
</p>
<div className="flex flex-wrap gap-2 mb-4">
{project.tech.map((tech: string) => (
<span
key={tech}
className="px-2 py-1 rounded text-xs"
style={{
backgroundColor: nordColors.bg,
color: nordColors.accent
}}
>
{tech}
</span>
))}
</div>
<div className="flex items-center justify-between">
<span
className="text-sm flex items-center gap-2"
style={{ color: nordColors.blue }}
>
<Image className="w-4 h-4" />
View Gallery
</span>
<span
className="px-2 py-1 rounded text-xs"
style={{
backgroundColor: nordColors.darkBlue,
color: nordColors.text
}}
>
{project.status}
</span>
</div>
</div>
))}
</div>
</div>
</section>
{/* Education & Certificates Section */}
<section id="education" className="py-20" style={{ backgroundColor: 'rgba(59, 66, 82, 0.3)' }}>
<div className="max-w-6xl mx-auto px-6">
<h2 className="text-4xl font-bold text-center mb-16" style={{ color: nordColors.accent }}>
Education & Certifications
</h2>
<div className="grid md:grid-cols-2 gap-12">
{/* Education */}
<div>
<h3 className="text-2xl font-semibold mb-8 flex items-center" style={{ color: nordColors.blue }}>
<GraduationCap className="w-6 h-6 mr-2" />
Education
</h3>
<div className="space-y-6">
{education.map((edu: Education, index: number) => (
<div
key={index}
className="p-6 rounded-lg border"
style={{
backgroundColor: nordColors.bg,
borderColor: nordColors.bgLight
}}
>
<h4 className="text-lg font-semibold mb-2" style={{ color: nordColors.text }}>
{edu.degree}
</h4>
<p className="mb-2" style={{ color: nordColors.blue }}>
{edu.institution}
</p>
<div className="flex justify-between items-center">
<span className="text-sm" style={{ color: nordColors.textMuted }}>
{edu.period}
</span>
<span
className="px-2 py-1 rounded text-xs"
style={{ backgroundColor: nordColors.darkBlue, color: nordColors.text }}
>
{edu.status}
</span>
</div>
</div>
))}
</div>
</div>
{/* Certificates */}
<div>
<h3 className="text-2xl font-semibold mb-8 flex items-center" style={{ color: nordColors.blue }}>
<Award className="w-6 h-6 mr-2" />
Certifications
</h3>
<div className="space-y-4">
{certificates.map((cert: string, index: number) => (
<div
key={index}
className="p-4 rounded-lg border flex items-center"
style={{
backgroundColor: nordColors.bg,
borderColor: nordColors.bgLight
}}
>
<div
className="w-2 h-2 rounded-full mr-4"
style={{ backgroundColor: nordColors.accent }}
></div>
<span style={{ color: nordColors.text }}>{cert}</span>
</div>
))}
</div>
<div
className="mt-8 p-6 rounded-lg border"
style={{
backgroundColor: nordColors.bg,
borderColor: nordColors.bgLight
}}
>
<h4 className="text-lg font-semibold mb-3" style={{ color: nordColors.blue }}>
Interests
</h4>
<div className="flex flex-wrap gap-2">
{['Computer Hardware', 'Web Development', 'Finance', 'Economics', 'Literature'].map((interest: string) => (
<span
key={interest}
className="px-3 py-1 rounded text-sm"
style={{
backgroundColor: nordColors.bgLighter,
color: nordColors.text
}}
>
{interest}
</span>
))}
</div>
</div>
</div>
</div>
</div>
</section>
{/* Contact Section */}
<section id="contact" className="py-20">
<div className="max-w-4xl mx-auto px-6 text-center">
<h2 className="text-4xl font-bold mb-8" style={{ color: nordColors.accent }}>
Let's Connect
</h2>
<p className="text-lg mb-12 max-w-2xl mx-auto" style={{ color: nordColors.textMuted }}>
I'm always interested in discussing new opportunities, collaborations, or just having a chat about technology and economics.
</p>
<div className="grid md:grid-cols-3 gap-8 mb-12">
<a
href="mailto:0pietroquintavalle0@gmail.com"
className="p-6 rounded-lg transition-colors hover:opacity-80 group"
style={{ backgroundColor: nordColors.bgLight }}
>
<Mail className="w-8 h-8 mx-auto mb-4" style={{ color: nordColors.blue }} />
<h3 className="text-lg font-semibold mb-2" style={{ color: nordColors.text }}>Email</h3>
<p className="text-sm" style={{ color: nordColors.textMuted }}>Drop me a line</p>
</a>
<a
href="https://www.linkedin.com/in/pietro-quintavalle-996b96267/"
className="p-6 rounded-lg transition-colors hover:opacity-80 group"
style={{ backgroundColor: nordColors.bgLight }}
target="_blank"
rel="noopener noreferrer"
>
<Linkedin className="w-8 h-8 mx-auto mb-4" style={{ color: nordColors.blue }} />
<h3 className="text-lg font-semibold mb-2" style={{ color: nordColors.text }}>LinkedIn</h3>
<p className="text-sm" style={{ color: nordColors.textMuted }}>Let's connect professionally</p>
</a>
<a
href="https://github.com/Quinta0"
className="p-6 rounded-lg transition-colors hover:opacity-80 group"
style={{ backgroundColor: nordColors.bgLight }}
target="_blank"
rel="noopener noreferrer"
>
<Github className="w-8 h-8 mx-auto mb-4" style={{ color: nordColors.blue }} />
<h3 className="text-lg font-semibold mb-2" style={{ color: nordColors.text }}>GitHub</h3>
<p className="text-sm" style={{ color: nordColors.textMuted }}>Check out my code</p>
</a>
</div>
</div>
</section>
{/* Footer */}
<footer className="py-8 border-t" style={{ borderColor: nordColors.bgLight }}>
<div className="max-w-6xl mx-auto px-6 text-center">
<p style={{ color: nordColors.textMuted }}>
Built with ❄️ using Next.js & Nord theme • Pietro Quintavalle © 2025
</p>
</div>
</footer>
{/* Project Gallery Modal */}
{showProjectGallery && (
<ProjectGallery
project={showProjectGallery}
onClose={() => setShowProjectGallery(false)}
/>
)}
</div>
);
};
export default Portfolio;
+31
View File
@@ -0,0 +1,31 @@
export const NORD_COLORS: NordColors = {
bg: '#2E3440',
bgLight: '#3B4252',
bgLighter: '#434C5E',
bgLightest: '#4C566A',
text: '#D8DEE9',
textMuted: 'rgba(216, 222, 233, 0.6)',
accent: '#88C0D0',
blue: '#81A1C1',
darkBlue: '#5E81AC',
cyan: '#8FBCBB',
green: '#A3BE8C',
yellow: '#EBCB8B',
orange: '#D08770',
red: '#BF616A',
purple: '#B48EAD'
};
export const SKILLS: Record<string, string[]> = {
'Data & Analytics': ['Python', 'R', 'SQL', 'Statistical Analysis', 'Data Visualization', 'Business Intelligence'],
'Web Development': ['JavaScript', 'TypeScript', 'React', 'Next.js', 'HTML5', 'CSS3', 'Tailwind CSS'],
'Backend & Tools': ['Flask', 'Express', 'MongoDB', 'SQLite', 'Git', 'Linux'],
'Other': ['Java', 'LaTeX', 'Project Planning', 'Financial Analysis']
};
export const CERTIFICATES: string[] = [
'Google Data Analytics Professional Certificate',
'Google IT Support Professional Certificate',
'IT Security: Defense against the digital dark arts',
'Python for Data Science, AI & Development'
];
+9 -2
View File
@@ -1,4 +1,11 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = {}; const nextConfig = {
experimental: {
appDir: true,
},
images: {
domains: ['via.placeholder.com'],
},
}
export default nextConfig; module.exports = nextConfig
+15 -19
View File
@@ -1,32 +1,28 @@
{ {
"name": "personalwebsite", "name": "pietro-portfolio",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint" "lint": "next lint",
"type-check": "tsc --noEmit"
}, },
"dependencies": { "dependencies": {
"@radix-ui/react-slot": "^1.1.0", "next": "14.2.4",
"class-variance-authority": "^0.7.0", "react": "^18.3.1",
"clsx": "^2.1.1", "react-dom": "^18.3.1",
"lucide-react": "^0.441.0", "lucide-react": "^0.263.1"
"next": "14.2.13",
"react": "^18",
"react-dom": "^18",
"tailwind-merge": "^2.5.2",
"tailwindcss-animate": "^1.0.7"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20", "@types/node": "^20.14.9",
"@types/react": "^18", "@types/react": "^18.3.3",
"@types/react-dom": "^18", "@types/react-dom": "^18.3.0",
"eslint": "^8", "eslint": "^8.57.0",
"eslint-config-next": "14.2.13", "eslint-config-next": "14.2.4",
"postcss": "^8", "postcss": "^8.4.39",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.4",
"typescript": "^5" "typescript": "^5.5.3"
} }
} }
+23 -43
View File
@@ -8,49 +8,29 @@ const config: Config = {
"./app/**/*.{js,ts,jsx,tsx,mdx}", "./app/**/*.{js,ts,jsx,tsx,mdx}",
], ],
theme: { theme: {
extend: { extend: {
colors: { colors: {
background: 'hsl(var(--background))', nord: {
foreground: 'hsl(var(--foreground))', 0: '#2E3440',
card: { 1: '#3B4252',
DEFAULT: 'hsl(var(--card))', 2: '#434C5E',
foreground: 'hsl(var(--card-foreground))' 3: '#4C566A',
}, 4: '#D8DEE9',
popover: { 5: '#E5E9F0',
DEFAULT: 'hsl(var(--popover))', 6: '#ECEFF4',
foreground: 'hsl(var(--popover-foreground))' 7: '#8FBCBB',
}, 8: '#88C0D0',
primary: { 9: '#81A1C1',
DEFAULT: 'hsl(var(--primary))', 10: '#5E81AC',
foreground: 'hsl(var(--primary-foreground))' 11: '#BF616A',
}, 12: '#D08770',
secondary: { 13: '#EBCB8B',
DEFAULT: 'hsl(var(--secondary))', 14: '#A3BE8C',
foreground: 'hsl(var(--secondary-foreground))' 15: '#B48EAD',
}, },
muted: { },
DEFAULT: 'hsl(var(--muted))', },
foreground: 'hsl(var(--muted-foreground))' },
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))'
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
foreground: 'hsl(var(--destructive-foreground))'
},
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
chart: {
'1': 'hsl(var(--chart-1))',
'2': 'hsl(var(--chart-2))',
'3': 'hsl(var(--chart-3))',
'4': 'hsl(var(--chart-4))',
'5': 'hsl(var(--chart-5))'
}
},
borderRadius: { borderRadius: {
lg: 'var(--radius)', lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)', md: 'calc(var(--radius) - 2px)',
+6 -2
View File
@@ -1,6 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"], "lib": ["dom", "dom.iterable", "es6"],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
@@ -17,8 +17,12 @@
"name": "next" "name": "next"
} }
], ],
"baseUrl": ".",
"paths": { "paths": {
"@/*": ["./*"] "@/*": ["./src/*"],
"@/components/*": ["./src/components/*"],
"@/lib/*": ["./src/lib/*"],
"@/types/*": ["./src/types/*"]
} }
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],