commit 31aa9c6015c15bb033c7644376edba7f7436f146 Author: Joe Wee Date: Thu May 21 12:05:48 2026 +0100 Initial: portfolio template via tAI diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..dba91da --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,13 @@ +{ + "permissions": { + "allow": [ + "Read", + "Write", + "Edit", + "Bash", + "Glob", + "Grep" + ] + }, + "model": "claude-sonnet-4-20250514" +} \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..b25496f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,28 @@ +# Alex Rivera +Designer portfolio with project showcase, case studies, about, and contact +Stack: React 18 / TypeScript / Vite / Tailwind CSS / shadcn/ui +Pages: Index, Work, ProjectDetail, About, Contact +Palette: violet/purple dark theme + +## Files +- src/components/Header.tsx (2KB) +- src/components/Footer.tsx (1KB) +- src/pages/Index.tsx (11KB) +- src/pages/Work.tsx (4KB) +- src/pages/ProjectDetail.tsx (11KB) +- src/pages/About.tsx (8KB) +- src/pages/Contact.tsx (6KB) +- src/App.tsx (1KB) + +## Imports +UI: @/components/ui/{button,card,badge,input,textarea,tabs,accordion,dialog,sheet} +Icons: lucide-react +Toast: import { toast } from "sonner" +Theme: ThemeToggle in headers (next-themes) +Router: react-router-dom BrowserRouter + +## Rules +- MODIFY existing files — never rebuild from scratch +- Pages import Header + Footer from @/components/ +- Tailwind only — no inline styles +- Use existing shadcn components — don't create custom ones diff --git a/README.md b/README.md new file mode 100644 index 0000000..b8ffd1d --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# template-portfolio + +Template: portfolio \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..2e80739 --- /dev/null +++ b/index.html @@ -0,0 +1,12 @@ + + + + + + Portfolio + + +
+ + + diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..ab5aac5 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,22 @@ +import { BrowserRouter, Routes, Route } from "react-router-dom"; +import IndexPage from "@/pages/Index"; +import WorkPage from "@/pages/Work"; +import ProjectDetailPage from "@/pages/ProjectDetail"; +import AboutPage from "@/pages/About"; +import ContactPage from "@/pages/Contact"; + +function App() { + return ( + + + } /> + } /> + } /> + } /> + } /> + + + ); +} + +export default App; diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx new file mode 100644 index 0000000..c0b4eb7 --- /dev/null +++ b/src/components/Footer.tsx @@ -0,0 +1,16 @@ +import { Github, Linkedin, Twitter, Mail } from "lucide-react"; + +export default function Footer() { + return ( + + ); +} \ No newline at end of file diff --git a/src/components/Header.tsx b/src/components/Header.tsx new file mode 100644 index 0000000..2b0dfd7 --- /dev/null +++ b/src/components/Header.tsx @@ -0,0 +1,52 @@ +import { useState, useEffect } from "react"; +import { Link } from "react-router-dom"; +import { Button } from "@/components/ui/button"; +import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"; +import { Menu } from "lucide-react"; +import { ThemeToggle } from "@/components/ThemeToggle"; + +export default function Header() { + const [open, setOpen] = useState(false); + const [scrolled, setScrolled] = useState(false); + + useEffect(() => { + const fn = () => setScrolled(window.scrollY > 20); + window.addEventListener("scroll", fn); + return () => window.removeEventListener("scroll", fn); + }, []); + + const links = [ + { label: "Work", to: "/work" }, + { label: "About", to: "/about" }, + { label: "Contact", to: "/contact" }, + ]; + + return ( +
+
+ Alex Rivera + + + + + + + + + +
+
+ ); +} \ No newline at end of file diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/src/index.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/src/main.tsx b/src/main.tsx new file mode 100644 index 0000000..9b67590 --- /dev/null +++ b/src/main.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; +import "./index.css"; + +ReactDOM.createRoot(document.getElementById("root")!).render( + + + +); diff --git a/src/pages/About.tsx b/src/pages/About.tsx new file mode 100644 index 0000000..bd5551e --- /dev/null +++ b/src/pages/About.tsx @@ -0,0 +1,146 @@ +import { Link } from "react-router-dom"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Separator } from "@/components/ui/separator"; +import { + Download, Award, Briefcase, GraduationCap, ArrowRight +} from "lucide-react"; +import Header from "@/components/Header"; +import Footer from "@/components/Footer"; + +const stats = [ + { value: "8+", label: "Years Experience" }, + { value: "50+", label: "Projects Completed" }, + { value: "30+", label: "Happy Clients" }, +]; + +const experience = [ + { company: "TechVentures Inc.", role: "Senior Product Designer", years: "2022 — Present", desc: "Leading design for the core product suite, managing a team of 4 designers, and establishing the company design system." }, + { company: "DesignLab Studio", role: "UI/UX Designer & Developer", years: "2020 — 2022", desc: "Designed and built web applications for Fortune 500 clients. Led the frontend development of 12+ projects." }, + { company: "Pixel Perfect Agency", role: "Junior Designer", years: "2018 — 2020", desc: "Crafted visual identities, marketing materials, and responsive websites for startups and SMBs." }, + { company: "Freelance", role: "Web Designer", years: "2016 — 2018", desc: "Built custom WordPress and React sites for local businesses while completing university studies." }, +]; + +const awards = [ + { title: "Best Portfolio Design", org: "Awwwards", year: "2024" }, + { title: "Design Excellence", org: "CSS Design Awards", year: "2023" }, + { title: "Top 10 Designers", org: "Dribbble", year: "2023" }, +]; + +export default function AboutPage() { + return ( +
+
+ + {/* ── HERO ── */} +
+
+
+

About Me

+

I am a multidisciplinary designer and developer with 8+ years of experience crafting digital products that people love. I specialize in bridging the gap between design and engineering.

+

When I am not pushing pixels or writing code, you will find me exploring national parks, experimenting with film photography, or contributing to open-source projects.

+
+ {stats.map((s, i) => ( +
+
{s.value}
+
{s.label}
+
+ ))} +
+ +
+
+
+
+
+
+
+ {("Alex Rivera").split(" ").map((n: string) => n[0]).join("")} +
+
+
+
+
+ + {/* ── EXPERIENCE ── */} +
+
+

+ Experience +

+
+ {experience.map((e, i) => ( +
+
+
+

{e.role}

+ {e.years} +
+
{e.company}
+

{e.desc}

+
+ ))} +
+
+
+ + {/* ── AWARDS ── */} +
+
+

+ Recognition +

+
+ {awards.map((a, i) => ( + + + {a.year} +

{a.title}

+

{a.org}

+
+
+ ))} +
+
+
+ + {/* ── EDUCATION ── */} +
+
+

+ Education +

+
+
+

B.S. Computer Science

+
Stanford University
+
2012 — 2016
+
+ +
+

UX Design Certificate

+
Google / Coursera
+
2018
+
+
+
+
+ + {/* ── CTA ── */} +
+
+

Interested in working together?

+

I'm always open to new opportunities and collaborations.

+ +
+
+ +
+
+ ); +} \ No newline at end of file diff --git a/src/pages/Contact.tsx b/src/pages/Contact.tsx new file mode 100644 index 0000000..82655f0 --- /dev/null +++ b/src/pages/Contact.tsx @@ -0,0 +1,114 @@ +import { useState } from "react"; +import { toast } from "sonner"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"; +import { + ArrowRight, Mail, MapPin, Linkedin, Github, Twitter, CheckCircle2 +} from "lucide-react"; +import Header from "@/components/Header"; +import Footer from "@/components/Footer"; + +const faqs = [ + { q: "What is your typical project timeline?", a: "Most projects take 4-8 weeks depending on scope. I will provide a detailed timeline during our initial consultation." }, + { q: "What are your rates?", a: "I offer both project-based and retainer pricing. Rates depend on project scope and complexity. Let us chat to find the right fit." }, + { q: "Do you work with international clients?", a: "Absolutely! I work with clients worldwide and am comfortable with asynchronous communication across time zones." }, + { q: "What tools do you use?", a: "Figma for design, React/Next.js for development, and tools like Framer Motion, Tailwind CSS, and TypeScript for building modern interfaces." }, +]; + +export default function ContactPage() { + return ( +
+
+ +
+
+

Let's Work Together

+

Have a project in mind? I would love to hear about it. Send me a message and I will get back to you within 24 hours.

+ +
+ {/* ── LEFT: Contact info ── */} +
+
+ {[ + { icon: Mail, label: "Email", value: "hello@alexrivera.dev" }, + { icon: MapPin, label: "Location", value: "San Francisco, CA" }, + { icon: Linkedin, label: "LinkedIn", value: "linkedin.com/in/alexrivera" }, + ].map((item, i) => ( +
+
+ +
+
+
{item.label}
+
{item.value}
+
+
+ ))} +
+
+ {[Github, Linkedin, Twitter].map((Icon, i) => ( + + + + ))} +
+
+ + {/* ── RIGHT: Form ── */} + + +
{ e.preventDefault(); toast.success("Message sent! I'll get back to you within 24 hours."); (e.target as HTMLFormElement).reset(); }} className="space-y-4"> +
+
+ + +
+
+ + +
+
+
+ + +
+
+ +