OpenClaw + ClawTeam + Superpowers Git Initialization

This commit is contained in:
2026-04-01 10:15:43 +07:00
parent 356c18ac75
commit b49ba1a719
258 changed files with 50192 additions and 0 deletions
@@ -0,0 +1,174 @@
'use client';
import { GraduationCapIcon, AwardIcon, LanguagesIcon, MapPinIcon, MailIcon, PhoneIcon } from '@/components/icons/TetIcons';
import ScrollReveal from '@/components/animations/ScrollReveal';
export default function AboutPage() {
return (
<main className="min-h-screen py-20 px-4 sm:px-6 lg:px-8 bg-[var(--tet-cream)]">
<div className="max-w-6xl mx-auto">
{/* Page Header */}
<ScrollReveal variant="fadeInUp">
<div className="text-center mb-16">
<h1 className="text-5xl font-bold text-[var(--tet-red)] mb-4">About Me</h1>
<div className="h-1 w-32 bg-[var(--tet-gold)] mx-auto rounded-full" />
</div>
</ScrollReveal>
<div className="grid md:grid-cols-2 gap-12 items-start">
{/* Avatar Section */}
<ScrollReveal variant="fadeInUp" delay={0.1}>
<div className="flex flex-col items-center">
<div className="relative w-80 h-80 rounded-full overflow-hidden border-8 border-[var(--tet-gold)] shadow-2xl mb-6 bg-gradient-to-br from-[var(--tet-red)] to-[var(--tet-gold)] flex items-center justify-center">
<span className="text-6xl font-bold text-white">TV</span>
</div>
{/* Quick contact */}
<div className="space-y-3 w-full max-w-md">
<div className="flex items-center space-x-3 text-gray-700">
<MapPinIcon className="w-5 h-5 text-[var(--tet-red)]" />
<span>Ho Chi Minh City, Vietnam</span>
</div>
<div className="flex items-center space-x-3 text-gray-700">
<MailIcon className="w-5 h-5 text-[var(--tet-red)]" />
<a href="mailto:nntrivi2001@gmail.com" className="hover:text-[var(--tet-red)] transition">
nntrivi2001@gmail.com
</a>
</div>
<div className="flex items-center space-x-3 text-gray-700">
<PhoneIcon className="w-5 h-5 text-[var(--tet-red)]" />
<span>090 321 5095</span>
</div>
</div>
</ScrollReveal>
{/* Bio Content */}
<ScrollReveal variant="fadeInUp" delay={0.2}>
<div className="space-y-8">
{/* Introduction */}
<section className="bg-white p-8 rounded-2xl border-2 border-[var(--tet-red)]/20 shadow-lg">
<h2 className="text-2xl font-bold text-[var(--tet-red)] mb-4">Who I Am</h2>
<p className="text-gray-700 leading-relaxed mb-4">
I&apos;m <strong>Nguyễn Ngọc Trí </strong> (Thomas), an AI Engineer with a passion for building intelligent systems
that solve real-world problems. I graduated as <span className="text-[var(--tet-gold)] font-semibold">Valedictorian</span> with a GPA of 3.74/4.0
from Ho Chi Minh City University of Industry and Trade, majoring in Data Analytics & AI.
</p>
<p className="text-gray-700 leading-relaxed">
My journey spans from computer vision in manufacturing to applied AI research and workflow automation.
I believe in the power of AI to transform businesses and improve lives, and I&apos;m committed to pushing
the boundaries of what&apos;s possible with technology.
</p>
</section>
{/* Education */}
<section className="bg-white p-8 rounded-2xl border-2 border-[var(--tet-red)]/20 shadow-lg">
<div className="flex items-center space-x-3 mb-4">
<GraduationCapIcon className="w-8 h-8 text-[var(--tet-red)]" />
<h2 className="text-2xl font-bold text-[var(--tet-red)]">Education</h2>
</div>
<div className="border-l-4 border-[var(--tet-gold)] pl-6 py-2">
<h3 className="text-xl font-semibold text-gray-800">
Engineer in Data Analytics & AI
</h3>
<p className="text-[var(--tet-red)] font-medium">Ho Chi Minh City University of Industry and Trade</p>
<p className="text-gray-600">Oct 2020 Oct 2024</p>
<div className="mt-3 flex flex-wrap gap-2">
<span className="px-3 py-1 bg-[var(--tet-red)]/10 text-[var(--tet-red)] rounded-full text-sm font-medium">
Valedictorian 🎓
</span>
<span className="px-3 py-1 bg-[var(--tet-gold)]/20 text-amber-700 rounded-full text-sm font-medium">
GPA: 3.74 / 4.0
</span>
</div>
</div>
{/* Awards */}
<div className="mt-6">
<h4 className="font-semibold text-gray-800 mb-3">Awards & Achievements</h4>
<ul className="space-y-2">
{[
"🥈 2nd Place Essential IT Products Competition (2024)",
"🥉 Consolation Prize TOFAS (2023)",
"🏆 Clean Code Award Finding Talents & Innovative IT (2022)",
"📜 Multiple scholarships (20202024)",
].map((award, idx) => (
<li key={idx} className="flex items-start space-x-2 text-gray-700">
<span className="text-[var(--tet-gold)]">{award}</span>
</li>
))}
</ul>
</div>
</section>
{/* Skills & Languages */}
<div className="grid md:grid-cols-2 gap-6">
<section className="bg-white p-6 rounded-2xl border-2 border-[var(--tet-red)]/20 shadow-lg">
<h3 className="text-xl font-bold text-[var(--tet-red)] mb-4">Skills</h3>
<div className="space-y-3">
<div>
<p className="font-semibold text-gray-800 mb-2">Programming & Tools</p>
<div className="flex flex-wrap gap-2">
{['Python', 'C++', 'HTML/CSS', 'JavaScript', 'PineScript', 'n8n', 'Telegram Bots'].map(skill => (
<span key={skill} className="px-3 py-1 bg-gray-100 text-gray-700 rounded-full text-sm">
{skill}
</span>
))}
</div>
</div>
<div>
<p className="font-semibold text-gray-800 mb-2">AI / ML</p>
<div className="flex flex-wrap gap-2">
{['TensorFlow', 'PyTorch', 'Scikit-learn', 'OpenCV'].map(skill => (
<span key={skill} className="px-3 py-1 bg-gray-100 text-gray-700 rounded-full text-sm">
{skill}
</span>
))}
</div>
</div>
<div>
<p className="font-semibold text-gray-800 mb-2">Data & Cloud</p>
<div className="flex flex-wrap gap-2">
{['SQL Server', 'Supabase', 'Firebase', 'MongoDB'].map(skill => (
<span key={skill} className="px-3 py-1 bg-gray-100 text-gray-700 rounded-full text-sm">
{skill}
</span>
))}
</div>
</div>
</div>
</section>
<section className="bg-white p-6 rounded-2xl border-2 border-[var(--tet-red)]/20 shadow-lg">
<div className="flex items-center space-x-3 mb-4">
<LanguagesIcon className="w-6 h-6 text-[var(--tet-red)]" />
<h3 className="text-xl font-bold text-[var(--tet-red)]">Languages</h3>
</div>
<div className="space-y-4">
<div>
<div className="flex justify-between mb-1">
<span className="font-medium text-gray-800">Vietnamese</span>
<span className="text-sm text-gray-600">Native</span>
</div>
<div className="h-2 bg-gray-200 rounded-full">
<div className="h-2 bg-[var(--tet-red)] rounded-full" style={{ width: '100%' }} />
</div>
</div>
<div>
<div className="flex justify-between mb-1">
<span className="font-medium text-gray-800">English</span>
<span className="text-sm text-gray-600">Professional</span>
</div>
<div className="h-2 bg-gray-200 rounded-full">
<div className="h-2 bg-[var(--tet-gold)] rounded-full" style={{ width: '85%' }} />
</div>
</div>
</div>
</section>
</div>
</ScrollReveal>
</div>
</div>
</main>
);
}
@@ -0,0 +1,248 @@
'use client';
import { motion } from 'framer-motion';
import { MailIcon, PhoneIcon, MapPinIcon, SendIcon, LinkedInIcon, GithubIcon, ArrowRightIcon } from '@/components/icons/TetIcons';
import { useState } from 'react';
import ScrollReveal from '@/components/animations/ScrollReveal';
export default function ContactPage() {
const [formData, setFormData] = useState({
name: '',
email: '',
subject: '',
message: '',
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitStatus, setSubmitStatus] = useState<'idle' | 'success' | 'error'>('idle');
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setIsSubmitting(true);
// Simulate form submission (in production, connect to backend)
await new Promise(resolve => setTimeout(resolve, 1500));
setSubmitStatus('success');
setIsSubmitting(false);
setFormData({ name: '', email: '', subject: '', message: '' });
setTimeout(() => setSubmitStatus('idle'), 5000);
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
setFormData(prev => ({
...prev,
[e.target.name]: e.target.value
}));
};
return (
<main className="min-h-screen py-20 px-4 sm:px-6 lg:px-8 bg-[var(--tet-cream)]">
<div className="max-w-6xl mx-auto">
{/* Page Header */}
<ScrollReveal variant="fadeInUp">
<div className="text-center mb-16">
<h1 className="text-5xl font-bold text-[var(--tet-red)] mb-4">Get in Touch</h1>
<div className="h-1 w-32 bg-[var(--tet-gold)] mx-auto rounded-full mb-4" />
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
Have a project in mind or want to collaborate? I&apos;d love to hear from you.
Don&apos;t hesitate to reach out!
</p>
</div>
</ScrollReveal>
<div className="grid lg:grid-cols-3 gap-12">
{/* Contact Information */}
<ScrollReveal variant="fadeInUp" delay={0.1} className="lg:col-span-1 space-y-6">
<div className="bg-white p-8 rounded-2xl border-2 border-[var(--tet-red)]/20 shadow-lg">
<h2 className="text-2xl font-bold text-[var(--tet-red)] mb-6">Contact Info</h2>
<div className="space-y-6">
<div className="flex items-start space-x-4">
<div className="p-3 bg-[var(--tet-red)]/10 rounded-xl">
<MailIcon className="w-6 h-6 text-[var(--tet-red)]" />
</div>
<div>
<p className="font-semibold text-gray-800">Email</p>
<a
href="mailto:nntrivi2001@gmail.com"
className="text-gray-600 hover:text-[var(--tet-red)] transition-colors"
>
nntrivi2001@gmail.com
</a>
</div>
</div>
<div className="flex items-start space-x-4">
<div className="p-3 bg-[var(--tet-red)]/10 rounded-xl">
<PhoneIcon className="w-6 h-6 text-[var(--tet-red)]" />
</div>
<div>
<p className="font-semibold text-gray-800">Phone</p>
<a
href="tel:+84903215095"
className="text-gray-600 hover:text-[var(--tet-red)] transition-colors"
>
090 321 5095
</a>
</div>
</div>
<div className="flex items-start space-x-4">
<div className="p-3 bg-[var(--tet-red)]/10 rounded-xl">
<MapPinIcon className="w-6 h-6 text-[var(--tet-red)]" />
</div>
<div>
<p className="font-semibold text-gray-800">Location</p>
<p className="text-gray-600">Ho Chi Minh City, Vietnam</p>
</div>
</div>
</div>
{/* Social Links */}
<div className="mt-8 pt-8 border-t border-gray-200">
<h3 className="font-semibold text-gray-800 mb-4">Connect with me</h3>
<div className="flex space-x-4">
<a
href="https://linkedin.com/in/nguyen-ngoc-tri-vi"
target="_blank"
rel="noopener noreferrer"
className="p-3 bg-[var(--tet-red)]/10 rounded-xl hover:bg-[var(--tet-red)]/20 transition-colors group"
aria-label="LinkedIn"
>
<LinkedInIcon className="w-6 h-6 text-[var(--tet-red)] group-hover:scale-110 transition-transform" />
</a>
<a
href="https://nguyenngoctrivi.vercel.app/"
target="_blank"
rel="noopener noreferrer"
className="p-3 bg-[var(--tet-gold)]/20 rounded-xl hover:bg-[var(--tet-gold)]/30 transition-colors group"
aria-label="Portfolio"
>
<ArrowRightIcon className="w-6 h-6 text-amber-600 group-hover:scale-110 transition-transform" />
</a>
</div>
</div>
</div>
{/* Decorative element */}
<div className="text-center text-6xl hidden lg:block">🧧</div>
</ScrollReveal>
{/* Contact Form */}
<ScrollReveal variant="fadeInUp" delay={0.2} className="lg:col-span-2">
<div className="bg-white p-8 rounded-2xl border-2 border-[var(--tet-red)]/20 shadow-lg">
<h2 className="text-2xl font-bold text-[var(--tet-red)] mb-6">Send a Message</h2>
<form onSubmit={handleSubmit} className="space-y-6">
<div className="grid md:grid-cols-2 gap-6">
<div>
<label htmlFor="name" className="block text-sm font-medium text-gray-700 mb-2">
Your Name *
</label>
<input
type="text"
id="name"
name="name"
required
value={formData.name}
onChange={handleChange}
className="w-full px-4 py-3 rounded-xl border-2 border-gray-200 focus:border-[var(--tet-red)] focus:outline-none transition-colors"
placeholder="Nguyễn Văn A"
/>
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700 mb-2">
Email Address *
</label>
<input
type="email"
id="email"
name="email"
required
value={formData.email}
onChange={handleChange}
className="w-full px-4 py-3 rounded-xl border-2 border-gray-200 focus:border-[var(--tet-red)] focus:outline-none transition-colors"
placeholder="example@email.com"
/>
</div>
</div>
<div>
<label htmlFor="subject" className="block text-sm font-medium text-gray-700 mb-2">
Subject
</label>
<input
type="text"
id="subject"
name="subject"
value={formData.subject}
onChange={handleChange}
className="w-full px-4 py-3 rounded-xl border-2 border-gray-200 focus:border-[var(--tet-red)] focus:outline-none transition-colors"
placeholder="What's this about?"
/>
</div>
<div>
<label htmlFor="message" className="block text-sm font-medium text-gray-700 mb-2">
Message *
</label>
<textarea
id="message"
name="message"
required
rows={6}
value={formData.message}
onChange={handleChange}
className="w-full px-4 py-3 rounded-xl border-2 border-gray-200 focus:border-[var(--tet-red)] focus:outline-none transition-colors resize-none"
placeholder="Tell me about your project or opportunity..."
/>
</div>
<div className="flex items-center justify-between">
<p className="text-sm text-gray-500">
* Required fields
</p>
<button
type="submit"
disabled={isSubmitting}
className="inline-flex items-center gap-2 px-8 py-4 bg-[var(--tet-red)] text-white rounded-full font-semibold hover:bg-[var(--tet-red-dark)] transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed shadow-lg hover:shadow-xl"
>
{isSubmitting ? (
'Sending...'
) : (
<>
Send Message
<SendIcon className="w-5 h-5" />
</>
)}
</button>
</div>
{/* Success/Error messages */}
{submitStatus === 'success' && (
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
className="p-4 bg-green-50 border-2 border-green-200 rounded-xl text-green-800"
>
Your message has been sent successfully! I&apos;ll get back to you soon.
</motion.div>
)}
{submitStatus === 'error' && (
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
className="p-4 bg-red-50 border-2 border-red-200 rounded-xl text-red-800"
>
Something went wrong. Please try again or email me directly.
</motion.div>
)}
</form>
</div>
</ScrollReveal>
</div>
</div>
</main>
);
}
@@ -0,0 +1,137 @@
'use client';
import { motion } from 'framer-motion';
import { BriefcaseIcon, CalendarIcon, MapPinIcon } from '@/components/icons/TetIcons';
import ScrollReveal from '@/components/animations/ScrollReveal';
const experiences = [
{
company: 'SmartGift Solution',
role: 'AI Engineer',
period: 'Mar 2026 Present',
location: 'Ho Chi Minh City, Vietnam',
description: [
'Researched and implemented AI-assisted solutions to improve developer team performance',
'Explored technologies for business use cases, built POCs, and documented recommendations',
],
color: 'tet-red',
},
{
company: 'Learning Chain Vietnam',
role: 'Applied AI Researcher & Operations Associate',
period: 'Jul 2025 Mar 2026',
location: 'Ho Chi Minh City, Vietnam',
description: [
'Built AI-assisted trading and operations automation systems',
'Developed POCs and recommended technologies for business use',
'Designed applied AI curricula, workshops, and n8n learning assets',
'Supported COO in workflow optimization and process standardization',
],
color: 'tet-gold',
},
{
company: 'Vườn Đậu Herbal Soy Milk Brand',
role: 'Founder',
period: 'Oct 2024 Apr 2025',
location: 'Ho Chi Minh City, Vietnam',
description: [
'Managed full production and business operations',
'Optimized sourcing, production, and inventory systems',
'Built pricing strategy and launched direct sales channels',
'Achieved strong customer retention (2.51 repeat purchases/customer)',
],
color: 'tet-red',
},
{
company: 'VSTECH Company Limited',
role: 'Computer Vision Engineer',
period: 'Aug 2023 Feb 2025',
location: 'Ho Chi Minh City, Vietnam',
description: [
'Developed nozzle quality inspection system for Japanese factory',
'Integrated 3D vision system for Samsung LED measurement (±7% accuracy)',
'Built OCR system for package code recognition in industrial environments',
],
color: 'tet-gold',
},
];
export default function ExperiencePage() {
return (
<main className="min-h-screen py-20 px-4 sm:px-6 lg:px-8 bg-[var(--tet-cream)]">
<div className="max-w-5xl mx-auto">
{/* Page Header */}
<ScrollReveal variant="fadeInUp">
<div className="text-center mb-16">
<h1 className="text-5xl font-bold text-[var(--tet-red)] mb-4">Experience</h1>
<div className="h-1 w-32 bg-[var(--tet-gold)] mx-auto rounded-full" />
</div>
</ScrollReveal>
{/* Timeline */}
<div className="relative">
{/* Central line */}
<div className="absolute left-8 md:left-1/2 top-0 bottom-0 w-0.5 bg-gradient-to-b from-[var(--tet-red)] to-[var(--tet-gold)] transform md:-translate-x-1/2" />
{experiences.map((exp, index) => {
const isEven = index % 2 === 0;
const Icon = BriefcaseIcon;
return (
<ScrollReveal key={index} variant={isEven ? "slideInLeft" : "slideInRight"} delay={index * 0.15}>
<div className={`relative flex items-center mb-16 ${isEven ? 'md:flex-row' : 'md:flex-row-reverse'}`}>
{/* Content Card */}
<div className={`ml-20 md:ml-0 md:w-5/12 ${isEven ? 'md:pr-12 md:text-right' : 'md:pl-12'} z-10`}>
<div className="bg-white p-6 rounded-2xl border-2 border-[var(--tet-red)]/20 shadow-lg hover:shadow-xl transition-shadow duration-300 card-hover">
<div className="flex items-center gap-2 mb-2 justify-center md:justify-start">
<CalendarIcon className="w-4 h-4 text-[var(--tet-red)]" />
<span className="text-sm font-medium text-[var(--tet-red)]">{exp.period}</span>
</div>
<h3 className="text-2xl font-bold text-gray-800 mb-1">{exp.role}</h3>
<div className="flex items-center gap-2 mb-3 justify-center md:justify-start">
<span className="text-lg font-semibold text-[var(--tet-red)]">{exp.company}</span>
</div>
<div className="flex items-center gap-2 mb-4 text-gray-600 text-sm justify-center md:justify-start">
<MapPinIcon className="w-4 h-4" />
<span>{exp.location}</span>
</div>
<ul className="space-y-2 mb-4">
{exp.description.map((item, idx) => (
<li key={idx} className={`text-gray-700 ${isEven ? 'md:text-right' : 'md:text-left'}`}>
{item}
</li>
))}
</ul>
<div className="flex justify-center md:justify-start">
<span className={`px-3 py-1 rounded-full text-xs font-medium bg-${exp.color === 'tet-red' ? '[var(--tet-red)]/10' : '[var(--tet-gold)]/20'} text-${exp.color === 'tet-red' ? '[var(--tet-red)]' : 'amber-700'}`}>
{exp.color === 'tet-red' ? '🔴' : '🟡'} {exp.period.split(' ')[0]}
</span>
</div>
</div>
</div>
{/* Timeline dot */}
<div className="absolute left-8 md:left-1/2 transform -translate-x-1/2">
<motion.div
whileHover={{ scale: 1.3 }}
className="w-8 h-8 rounded-full bg-[var(--tet-gold)] border-4 border-[var(--tet-cream)] shadow-lg flex items-center justify-center z-20"
>
<Icon className="w-4 h-4 text-[var(--tet-dark)]" />
</motion.div>
</div>
{/* Empty spacer for opposite side */}
<div className="hidden md:block md:w-5/12" />
</div>
</ScrollReveal>
);
})}
</div>
</div>
</main>
);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

@@ -0,0 +1,66 @@
:root {
/* Tet Theme Colors */
--tet-red: #C41E3A;
--tet-red-dark: #8B0000;
--tet-gold: #FFD700;
--tet-gold-light: #FFC107;
--tet-cream: #FFF8E7;
--tet-dark: #1A1A1A;
--tet-red-gradient: linear-gradient(135deg, #C41E3A 0%, #8B0000 100%);
--tet-gold-gradient: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
--background: var(--tet-cream);
--foreground: var(--tet-dark);
}
/* Custom utility classes */
.bg-tet-red { background-color: var(--tet-red); }
.bg-tet-gold { background-color: var(--tet-gold); }
.text-tet-red { color: var(--tet-red); }
.text-tet-gold { color: var(--tet-gold); }
.border-tet-red { border-color: var(--tet-red); }
body {
background: var(--background);
color: var(--foreground);
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
overflow-x: hidden;
}
/* Smooth scrolling */
html {
scroll-behavior: smooth;
}
/* Custom scrollbar with Tet colors */
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar-track {
background: var(--tet-cream);
}
::-webkit-scrollbar-thumb {
background: var(--tet-red);
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--tet-red-dark);
}
/* Golden glow effect */
.text-glow {
text-shadow: 0 0 20px rgba(255, 215, 0, 0.5);
}
/* Red card hover effect */
.card-hover {
transition: all 0.3s ease;
}
.card-hover:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px rgba(196, 30, 58, 0.2);
}
@@ -0,0 +1,101 @@
'use client';
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import Navigation from "@/components/layout/Navigation";
import Footer from "@/components/layout/Footer";
import Script from "next/script";
import { AnimatePresence, motion } from 'framer-motion';
import { usePathname } from 'next/navigation';
import FallingPetals from '@/components/animations/FallingPetals';
import { useEffect, useState } from 'react';
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Trí Vĩ - AI Engineer Portfolio",
description: "Portfolio of Nguyễn Ngọc Trí Vĩ - AI Engineer specializing in Computer Vision, Machine Learning, and Applied AI solutions",
keywords: ["AI Engineer", "Machine Learning", "Computer Vision", "Portfolio", "Vietnam"],
authors: [{ name: "Nguyễn Ngọc Trí Vĩ" }],
openGraph: {
title: "Trí Vĩ - AI Engineer",
description: "Portfolio of an AI Engineer building intelligent systems",
type: "website",
},
};
// Page transition variants
const pageVariants = {
hidden: { opacity: 0, x: 20 },
visible: {
opacity: 1,
x: 0,
transition: {
duration: 0.4,
ease: [0.25, 0.1, 0.25, 1]
}
},
exit: {
opacity: 0,
x: -20,
transition: {
duration: 0.3,
ease: [0.25, 0.1, 0.25, 1]
}
},
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const pathname = usePathname();
const [isClient, setIsClient] = useState(false);
useEffect(() => {
setIsClient(true);
}, []);
return (
<html lang="en" className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}>
<body className="min-h-full flex flex-col">
{/* Tailwind CSS CDN */}
<Script
src="https://cdn.tailwindcss.com"
strategy="beforeInteractive"
/>
<Navigation />
<div className="flex-1 pt-16 relative"> {/* Added relative for positioning */}
<AnimatePresence mode="wait" initial={false}>
{isClient && (
<motion.div
key={pathname}
initial="hidden"
animate="visible"
exit="exit"
variants={pageVariants}
className="min-h-screen"
>
{children}
</motion.div>
)}
</AnimatePresence>
{/* Falling petals overlay - appears on all pages */}
<FallingPetals count={40} />
</div>
<Footer />
</body>
</html>
);
}
@@ -0,0 +1,164 @@
'use client';
import { motion } from 'framer-motion';
import { ArrowRightIcon, SparklesIcon, Code2Icon, BrainIcon } from '@/components/icons/TetIcons';
import Link from 'next/link';
import ScrollReveal from '@/components/animations/ScrollReveal';
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.2,
delayChildren: 0.3,
},
},
};
const itemVariants = {
hidden: { opacity: 0, y: 30 },
visible: {
opacity: 1,
y: 0,
transition: { duration: 0.6 },
},
};
export default function HomePage() {
return (
<main className="relative min-h-screen flex items-center justify-center overflow-hidden">
{/* Decorative border patterns */}
<div className="absolute inset-0 pointer-events-none">
{/* Top border - traditional cloud pattern */}
<div className="absolute top-0 left-0 right-0 h-4 bg-gradient-to-r from-[var(--tet-red)] via-[var(--tet-gold)] to-[var(--tet-red)]" />
{/* Corner decorations */}
<div className="absolute top-4 left-4 w-16 h-16 border-t-4 border-l-4 border-[var(--tet-red)]" />
<div className="absolute top-4 right-4 w-16 h-16 border-t-4 border-r-4 border-[var(--tet-red)]" />
<div className="absolute bottom-4 left-4 w-16 h-16 border-b-4 border-l-4 border-[var(--tet-red)]" />
<div className="absolute bottom-4 right-4 w-16 h-16 border-b-4 border-r-4 border-[var(--tet-red)]" />
</div>
{/* Main content */}
<motion.div
variants={containerVariants}
initial="hidden"
animate="visible"
className="relative z-10 max-w-6xl mx-auto px-6 py-24 text-center"
>
{/* Greeting in Traditional Vietnamese style */}
<motion.div variants={itemVariants} className="mb-6">
<span className="inline-block px-6 py-2 bg-[var(--tet-red)] text-white rounded-full text-sm font-semibold tracking-wider uppercase">
🎊 Chúc Mừng Năm Mới 🎊
</span>
</motion.div>
{/* Test agent completion badge */}
<motion.div variants={itemVariants} className="mb-4">
<span className="inline-flex items-center gap-2 px-4 py-1.5 bg-green-100 text-green-800 rounded-full text-xs font-medium border border-green-200">
<svg className="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
</svg>
Test Agent Task Completed
</span>
</motion.div>
{/* Name with golden glow */}
<motion.h1
variants={itemVariants}
className="text-5xl md:text-8xl font-bold mb-4 bg-[var(--tet-gold-gradient)] bg-clip-text text-transparent text-glow"
>
Nguyễn Ngọc Trí
</motion.h1>
{/* Role with red accent */}
<motion.h2
variants={itemVariants}
className="text-2xl md:text-4xl font-semibold mb-8 text-[var(--tet-red)]"
>
AI Engineer
</motion.h2>
{/* Bio */}
<motion.p
variants={itemVariants}
className="text-lg md:text-xl max-w-3xl mx-auto mb-12 leading-relaxed text-gray-700"
>
Passionate about building intelligent systems that bridge the gap between AI and real-world business problems.
Currently researching AI-assisted solutions at <span className="font-bold text-[var(--tet-red)]">SmartGift Solution</span>.
</motion.p>
{/* Quick stats */}
<motion.div
variants={itemVariants}
className="grid grid-cols-2 md:grid-cols-4 gap-6 mb-12 max-w-4xl mx-auto"
>
{[
{ icon: BrainIcon, label: 'AI/ML', value: 'Expert' },
{ icon: Code2Icon, label: 'Experience', value: '3+ Years' },
{ icon: SparklesIcon, label: 'Projects', value: '20+' },
{ icon: () => (
<span className="text-2xl">🎓</span>
), label: 'Education', value: 'Valedictorian' },
].map((stat, index) => (
<motion.div
key={index}
whileHover={{ scale: 1.05 }}
className="flex flex-col items-center p-6 bg-white/80 backdrop-blur-sm rounded-2xl border-2 border-[var(--tet-red)]/20 shadow-lg card-hover"
>
<stat.icon className="w-8 h-8 text-[var(--tet-red)] mb-2" />
<span className="text-3xl font-bold text-[var(--tet-gold)]">{stat.value}</span>
<span className="text-sm text-gray-600 mt-1">{stat.label}</span>
</motion.div>
))}
</motion.div>
{/* CTA buttons */}
<motion.div
variants={itemVariants}
className="flex flex-col sm:flex-row gap-4 justify-center"
>
<Link
href="/about"
className="group inline-flex items-center justify-center px-8 py-4 bg-[var(--tet-red)] text-white rounded-full font-semibold text-lg hover:bg-[var(--tet-red-dark)] transition-all duration-300 shadow-lg hover:shadow-xl hover:scale-105"
>
Learn More
<ArrowRightIcon className="ml-2 w-5 h-5 group-hover:translate-x-1 transition-transform" />
</Link>
<Link
href="/projects"
className="inline-flex items-center justify-center px-8 py-4 border-2 border-[var(--tet-red)] text-[var(--tet-red)] rounded-full font-semibold text-lg hover:bg-[var(--tet-red)] hover:text-white transition-all duration-300"
>
View Projects
</Link>
<Link
href="/contact"
className="inline-flex items-center justify-center px-8 py-4 bg-[var(--tet-gold)] text-[var(--tet-dark)] rounded-full font-semibold text-lg hover:bg-[var(--tet-gold-light)] transition-all duration-300"
>
Get in Touch
</Link>
</motion.div>
</motion.div>
{/* Floating lantern decoration */}
<motion.div
animate={{ y: [0, -20, 0] }}
transition={{ duration: 3, repeat: Infinity, ease: 'easeInOut' }}
className="absolute bottom-10 left-10 text-4xl hidden lg:block"
>
🏮
</motion.div>
<motion.div
animate={{ y: [0, -15, 0] }}
transition={{ duration: 2.5, repeat: Infinity, ease: 'easeInOut', delay: 0.5 }}
className="absolute bottom-10 right-10 text-4xl hidden lg:block"
>
🧧
</motion.div>
</main>
);
}
@@ -0,0 +1,105 @@
'use client';
import { motion } from 'framer-motion';
import { ExternalLinkIcon, GithubIcon, FolderOpenIcon, TagIcon } from '@/components/icons/TetIcons';
import ScrollReveal from '@/components/animations/ScrollReveal';
const projects = [
return (
<main className="min-h-screen py-20 px-4 sm:px-6 lg:px-8 bg-[var(--tet-cream)]">
<div className="max-w-7xl mx-auto">
{/* Page Header */}
<ScrollReveal variant="fadeInUp">
<div className="text-center mb-16">
<h1 className="text-5xl font-bold text-[var(--tet-red)] mb-4">Projects</h1>
<div className="h-1 w-32 bg-[var(--tet-gold)] mx-auto rounded-full mb-4" />
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
A showcase of AI, computer vision, and automation projects that demonstrate my expertise in applied AI and full-stack development.
</p>
</div>
</ScrollReveal>
{/* Projects Grid */}
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
{projects.map((project, index) => (
<ScrollReveal key={project.id} variant="fadeInUp" delay={index * 0.1}>
<motion.div
whileHover={{ y: -8 }}
className="bg-white rounded-2xl border-2 border-[var(--tet-red)]/20 shadow-lg overflow-hidden card-hover group"
>
{/* Card Header with decorative pattern */}
<div className={`h-3 bg-gradient-to-r from-${project.color === 'tet-red' ? '[var(--tet-red)]' : '[var(--tet-gold)]'} to-${project.color === 'tet-red' ? '[var(--tet-red-dark)]' : '[#FFA500]'}`} />
<div className="p-6">
{/* Icon and year */}
<div className="flex justify-between items-start mb-4">
<div className={`p-3 rounded-xl bg-${project.color}/10`}>
<FolderOpenIcon className={`w-8 h-8 text-${project.color === 'tet-red' ? '[var(--tet-red)]' : '[var(--tet-gold)]'}`} />
</div>
<span className="text-sm font-medium text-gray-500">{project.year}</span>
</div>
{/* Title */}
<h3 className="text-xl font-bold text-gray-800 mb-3 line-clamp-2 min-h-[3.5rem]">
{project.title}
</h3>
{/* Description */}
<p className="text-gray-600 mb-6 text-sm leading-relaxed line-clamp-3">
{project.description}
</p>
{/* Tags */}
<div className="flex flex-wrap gap-2 mb-6">
{project.tags.map(tag => (
<span
key={tag}
className="inline-flex items-center gap-1 px-3 py-1 bg-gray-100 text-gray-700 rounded-full text-xs"
>
<TagIcon className="w-3 h-3" />
{tag}
</span>
))}
</div>
{/* Links */}
<div className="flex gap-3">
<a
href={project.link}
className="flex-1 inline-flex items-center justify-center gap-2 px-4 py-2 bg-[var(--tet-red)] text-white rounded-lg text-sm font-medium hover:bg-[var(--tet-red-dark)] transition-colors"
>
<ExternalLinkIcon className="w-4 h-4" />
View
</a>
<a
href={project.github}
className="inline-flex items-center justify-center gap-2 px-4 py-2 border border-gray-300 text-gray-700 rounded-lg text-sm hover:bg-gray-50 transition-colors"
>
<GithubIcon className="w-4 h-4" />
Code
</a>
</div>
</div>
</motion.div>
</ScrollReveal>
))}
</div>
{/* More projects placeholder */}
<ScrollReveal variant="fadeInUp" delay={0.6}>
<div className="mt-16 text-center">
<p className="text-gray-600 mb-4">
Want to see more of my work or discuss a collaboration?
</p>
<a
href="/contact"
className="inline-flex items-center gap-2 px-8 py-4 bg-[var(--tet-gold)] text-[var(--tet-dark)] rounded-full font-semibold hover:bg-[var(--tet-gold-light)] transition-all duration-300"
>
Get in Touch
</a>
</div>
</ScrollReveal>
</div>
</main>
);
}