Initial commit

This commit is contained in:
2024-10-27 11:04:40 -07:00
commit 15047541f4
39 changed files with 8203 additions and 0 deletions

14
src/app/api/cv/route.ts Normal file
View File

@@ -0,0 +1,14 @@
import { NextResponse } from 'next/server';
import { promises as fs } from 'fs';
import path from 'path';
export async function GET() {
try {
const cvPath = path.join(process.cwd(), 'cv.tex');
const cvContent = await fs.readFile(cvPath, 'utf8');
return NextResponse.json({ content: cvContent });
} catch (error) {
return NextResponse.json({ error: 'Failed to load CV' }, { status: 500 });
}
}

26
src/app/cv/page.tsx Normal file
View File

@@ -0,0 +1,26 @@
'use client';
export default function CVPage() {
return (
<div className="bg-white shadow-sm rounded-lg overflow-hidden">
<object
data="/cv.pdf"
type="application/pdf"
className="w-full h-[calc(100vh-8rem)]"
>
<div className="flex flex-col items-center justify-center p-8">
<p className="text-lg text-muted-foreground">
Your browser doesn't support PDF preview.
</p>
<a
href="/cv.pdf"
download
className="mt-4 inline-flex items-center justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-primary hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary"
>
Download PDF
</a>
</div>
</object>
</div>
);
}

28
src/app/layout.tsx Normal file
View File

@@ -0,0 +1,28 @@
import { inter } from "~/lib/fonts"
import "~/styles/globals.css"
import { Navigation } from "~/components/Navigation"
import { Sidebar } from "~/components/Sidebar"
export const metadata = {
title: "Sean O'Connor",
description: "Personal website and portfolio",
icons: [{ rel: "icon", url: "/favicon.ico" }],
}
export default function RootLayout({ children }: React.PropsWithChildren) {
return (
<html lang="en" className={inter.className}>
<body className="font-sans bg-background text-foreground min-h-screen">
<Navigation />
<div className="max-w-screen-xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex flex-col lg:flex-row lg:gap-12 py-8">
<Sidebar />
<main className="flex-1">
{children}
</main>
</div>
</div>
</body>
</html>
)
}

114
src/app/page.tsx Normal file
View File

@@ -0,0 +1,114 @@
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "~/components/ui/card";
import { Badge } from "~/components/ui/badge";
import Link from "next/link";
import { ArrowUpRight, Code, FlaskConical, Users } from 'lucide-react';
import { projects } from "~/lib/data";
export default function HomePage() {
return (
<div className="space-y-12">
{/* About Section */}
<section className="space-y-6">
<div>
<h1 className="text-2xl font-bold">About Me</h1>
<p className="text-lg text-muted-foreground mt-2">
I'm a Computer Science and Engineering student at Bucknell University, passionate about robotics,
software development, and human-computer interaction. With a strong foundation in both academic
research and practical development, I bridge the gap between theoretical concepts and real-world applications.
</p>
</div>
<Card>
<CardHeader>
<div className="flex items-center gap-2">
<Code className="h-5 w-5" />
<CardTitle>Technical Expertise</CardTitle>
</div>
</CardHeader>
<CardContent className="space-y-2">
<ul className="list-disc pl-5 space-y-2">
<li>Full-stack development with modern frameworks (React, Next.js, Node.js)</li>
<li>Robotics development using ROS2 and C++</li>
<li>Systems programming and architecture design</li>
<li>Database design and optimization (SQL, PostgreSQL)</li>
<li>Cloud infrastructure and DevOps (AWS, Docker)</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<div className="flex items-center gap-2">
<FlaskConical className="h-5 w-5" />
<CardTitle>Research Focus</CardTitle>
</div>
</CardHeader>
<CardContent className="space-y-2">
<ul className="list-disc pl-5 space-y-2">
<li>Human-Robot Interaction studies and experimental design</li>
<li>Published researcher at IEEE RO-MAN 2024</li>
<li>Development of experimental platforms for HRI research</li>
<li>Integration of robotics in chemical engineering research</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<div className="flex items-center gap-2">
<Users className="h-5 w-5" />
<CardTitle>Leadership</CardTitle>
</div>
</CardHeader>
<CardContent className="space-y-2">
<ul className="list-disc pl-5 space-y-2">
<li>President of AIChE Chem-E-Car Competition Team</li>
<li>Treasurer of Bucknell Coffee Society</li>
<li>Teaching Assistant for Computer Science courses</li>
<li>Founding member of RoboLab@Bucknell</li>
</ul>
</CardContent>
</Card>
</section>
{/* Featured Projects Section */}
<section className="space-y-4">
<div className="flex items-center justify-between">
<h2 className="text-2xl font-bold">Featured Projects</h2>
<Link
href="/projects"
className="text-sm text-muted-foreground hover:text-primary flex items-center gap-1"
>
View all projects
<ArrowUpRight className="h-4 w-4" />
</Link>
</div>
<div className="space-y-6">
{projects
.filter(project => project.featured)
.slice(0, 2)
.map((project, index) => (
<Card key={index}>
<CardHeader>
<div className="flex items-center justify-between">
<CardTitle>{project.title}</CardTitle>
{project.link && (
<Link
href={project.link}
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-primary"
>
<ArrowUpRight className="h-5 w-5" />
</Link>
)}
</div>
<CardDescription className="text-base">{project.description}</CardDescription>
</CardHeader>
</Card>
))}
</div>
</section>
</div>
);
}

72
src/app/projects/page.tsx Normal file
View File

@@ -0,0 +1,72 @@
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "~/components/ui/card";
import { Badge } from "~/components/ui/badge";
import Link from "next/link";
import { ArrowUpRight } from "lucide-react";
import { projects } from "~/lib/data";
import Image from "next/image";
export default function ProjectsPage() {
return (
<div className="space-y-8">
<section className="prose prose-zinc dark:prose-invert max-w-none">
<h1 className="text-2xl font-bold">Featured Projects</h1>
<p className="text-lg text-muted-foreground">
A selection of my academic and professional projects, focusing on robotics,
web development, and embedded systems.
</p>
</section>
<div className="space-y-6">
{projects.map((project, index) => (
<Card key={index}>
<div className="flex flex-col lg:flex-row lg:items-center">
<div className="flex-1">
<CardHeader>
<div className="flex items-center justify-between">
<CardTitle>{project.title}</CardTitle>
{project.link && (
<Link
href={project.link}
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-primary"
>
<ArrowUpRight className="h-5 w-5" />
</Link>
)}
</div>
<CardDescription className="text-base">{project.description}</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<p className="text-sm text-muted-foreground">
{project.longDescription}
</p>
<div className="flex flex-wrap gap-2">
{project.tags.map((tag) => (
<Badge key={tag} variant="secondary">
{tag}
</Badge>
))}
</div>
</CardContent>
</div>
{project.image && (
<div className="px-6 pb-6 lg:py-6 lg:w-1/3">
<div className="relative aspect-[4/3] w-full overflow-hidden rounded-lg">
<Image
src={project.image}
alt={project.title}
fill
className="object-contain"
/>
</div>
</div>
)}
</div>
</Card>
))}
</div>
</div>
);
}