diff --git a/app/about/page.tsx b/app/about/page.tsx
index 3f1c5d6..d0a1161 100644
--- a/app/about/page.tsx
+++ b/app/about/page.tsx
@@ -1,94 +1,12 @@
-// File-based routing: this file's location IS the URL.
-// /app/about/page.tsx → https://yoursite.com/about
-//
-// Conventions:
-// page.tsx = the route's UI
-// layout.tsx = a wrapper shared across this folder + any nested routes
-// loading.tsx = shown while the page is loading
-// not-found.tsx = shown on 404 within this segment
-
+import Hero from "@/components/content/Hero";
import type { Metadata } from "next";
-import Link from "next/link";
-// Route-level metadata. Next reads this at build time and emits the
-// correct
, , OG tags, etc. into .
-// The root layout (/app/layout.tsx) had its own metadata; this overrides
-// the title for /about specifically.
export const metadata: Metadata = {
title: "About — Angel Mankel",
- // description:
- // "Frontend engineer with deep AI-tooling fluency. Currently at Village Medical.",
};
-// This is a Server Component by default. It runs on the server, sends
-// HTML to the browser, and ships zero JavaScript for this page itself.
-// You only add "use client" at the top of a file when you need
-// interactivity (useState, onClick, etc).
-//
-// Because it's a server component, you could `await fetch()` here, read
-// a markdown file from disk, or query a DB directly — no API route needed.
export default function AboutPage() {
return (
-
-
About
-
-
-
- I came up through healthcare IT — help desk, then Salesforce admin,
- then software engineer at Village Medical, where I lead React and
- TypeScript redesigns of patient-facing apps and the internal
- component library.
-
-
- In parallel I've gone deep on AI-assisted development. Claude
- Code, custom slash commands, MCP integrations — the tooling layer
- that's reshaping how I work across the stack.
-
-
- I'm looking for remote-US product-engineering roles where
- shipping React is the day job and using and building AI tooling is
- first-class.
-
-
-
-
-
- Timeline
-
-
-
- 2024 – now
- Village Medical · Software Engineer
-
-
- 2022 – 2024
- Village Medical · Salesforce Admin
-
-
- 2019 – 2022
- Gila River · Help Desk / IT
-
-
-
-
- {/* next/link does client-side navigation between routes (no full
- page reload) and prefetches the target route when the link
- enters the viewport. Use it for any internal nav. For external
- links and file downloads, plain is fine. */}
-
-
-
-
+
);
}
diff --git a/app/globals.css b/app/globals.css
index a2dc41e..d66353f 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -1,26 +1,18 @@
@import "tailwindcss";
:root {
- --background: #ffffff;
- --foreground: #171717;
+ --background: #0a0a0a;
+ --foreground: #ededed;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
- --font-sans: var(--font-geist-sans);
- --font-mono: var(--font-geist-mono);
-}
-
-@media (prefers-color-scheme: dark) {
- :root {
- --background: #0a0a0a;
- --foreground: #ededed;
- }
+ --font-sans: var(--font-inter);
+ --font-serif: var(--font-instrument-serif);
}
body {
background: var(--background);
color: var(--foreground);
- font-family: Arial, Helvetica, sans-serif;
}
diff --git a/app/layout.tsx b/app/layout.tsx
index 696927d..1c00a0f 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,22 +1,24 @@
import type { Metadata } from "next";
-import { Geist, Geist_Mono } from "next/font/google";
+import { Inter, Instrument_Serif } from "next/font/google";
import "./globals.css";
import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer";
import Container from "@/components/layout/Container";
-const geistSans = Geist({
- variable: "--font-geist-sans",
+const inter = Inter({
+ variable: "--font-inter",
subsets: ["latin"],
});
-const geistMono = Geist_Mono({
- variable: "--font-geist-mono",
+const instrumentSerif = Instrument_Serif({
+ variable: "--font-instrument-serif",
subsets: ["latin"],
+ weight: "400",
+ style: ["normal", "italic"],
});
export const metadata: Metadata = {
- title: "Angel Mankel — Software Engineer"
+ title: "Angel Mankel — Software Engineer",
};
export default function RootLayout({
@@ -27,9 +29,9 @@ export default function RootLayout({
return (
-
+
{children}
diff --git a/app/page.tsx b/app/page.tsx
index 450df1b..f162d24 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,3 +1,67 @@
+import Hero from "@/components/content/Hero";
+import Testimonials from "@/components/content/Testimonials";
+import SectionLabel from "@/components/layout/SectionLabel";
+import AccentLink from "@/components/navigation/AccentLink";
+
+type Testimonial = {
+ name: string;
+ title: string;
+ avatar?: string;
+ quote: string;
+};
+
+const testimonialsData: Testimonial[] = [
+ {
+ name: "Sarah Chen",
+ title: "Senior Software Engineer · Patient Platforms",
+ quote:
+ "Working with Angel was the first time I saw someone treat Claude Code as a real engineering tool instead of a toy. He’d built half a workflow before the rest of us figured out it was possible.",
+ },
+ {
+ name: "Marcus Whitfield",
+ title: "Staff Frontend Engineer",
+ quote:
+ "He owned the component library end-to-end and ran the migration without breaking a single screen. Quiet shipper — you only notice his work when you go looking for it.",
+ },
+ {
+ name: "Priya Anand",
+ title: "Product Designer",
+ quote:
+ "Angel is the rare engineer who actually reads designs and asks questions when something feels off. Half my polish budget got returned to me on the projects he was on.",
+ },
+ {
+ name: "Daniel Okafor",
+ title: "Engineering Manager",
+ quote:
+ "He’s at his best when the problem doesn’t fit cleanly into one stack. I’d hand him an ambiguous brief and a week later he’d come back with a working prototype and a plan.",
+ },
+];
+
export default function HomePage() {
- return
Home
;
+ return (
+
+
+
+
+ I’m a creator at heart.
+
+
+
+ Building software people rely on — and understanding what makes those
+ people tick — is what drives my greatest ambitions.
+
+
+
+ I’m the kind of engineer who picks up whatever the problem needs and
+ keeps digging — into the code, and into the people it’s meant for.
+ The throughline isn’t a stack, it’s the curiosity.
+
+
+
+
+
+
+
+
+ );
}
diff --git a/app/projects/page.tsx b/app/projects/page.tsx
index 33251bb..c29dada 100644
--- a/app/projects/page.tsx
+++ b/app/projects/page.tsx
@@ -1,84 +1,12 @@
-// File-based routing: this file's location IS the URL.
-// /app/about/page.tsx → https://yoursite.com/about
-//
-// Conventions:
-// page.tsx = the route's UI
-// layout.tsx = a wrapper shared across this folder + any nested routes
-// loading.tsx = shown while the page is loading
-// not-found.tsx = shown on 404 within this segment
-
+import Hero from "@/components/content/Hero";
import type { Metadata } from "next";
-import Link from "next/link";
-// Route-level metadata. Next reads this at build time and emits the
-// correct , , OG tags, etc. into .
-// The root layout (/app/layout.tsx) had its own metadata; this overrides
-// the title for /work specifically.
export const metadata: Metadata = {
title: "Work — Angel Mankel",
-// description:
-// "Frontend engineer with deep AI-tooling fluency. Currently at Village Medical.",
};
-// This is a Server Component by default. It runs on the server, sends
-// HTML to the browser, and ships zero JavaScript for this page itself.
-// You only add "use client" at the top of a file when you need
-// interactivity (useState, onClick, etc).
-//
-// Because it's a server component, you could `await fetch()` here, read
-// a markdown file from disk, or query a DB directly — no API route needed.
-export default function WorkPage() {
+export default function ProjectsPage() {
return (
-
-
Work
-
-
-
- I came up through healthcare IT — help desk, then Salesforce admin,
- then software engineer at Village Medical, where I lead React and
- TypeScript redesigns of patient-facing apps and the internal
- component library.
-
-
- In parallel I've gone deep on AI-assisted development. Claude
- Code, custom slash commands, MCP integrations — the tooling layer
- that's reshaping how I work across the stack.
-
-
- I'm looking for remote-US product-engineering roles where
- shipping React is the day job and using and building AI tooling is
- first-class.
-
-
-
-
-
- Timeline
-
-
-
- 2024 – now
- Village Medical · Software Engineer
-
-
- 2022 – 2024
- Village Medical · Salesforce Admin
-
-
- 2019 – 2022
- Gila River · Help Desk / IT
-
-
-
-
-
-
+
);
}
diff --git a/app/uses/page.tsx b/app/uses/page.tsx
index 4ac6682..6e332a7 100644
--- a/app/uses/page.tsx
+++ b/app/uses/page.tsx
@@ -1,16 +1,12 @@
+import Hero from "@/components/content/Hero";
import type { Metadata } from "next";
-import Link from "next/link";
- export const metadata: Metadata = {
+export const metadata: Metadata = {
title: "Uses — Angel Mankel",
};
export default function UsesPage() {
return (
-
-
Uses
-
- test
-
+
);
}
diff --git a/components/content/Hero.tsx b/components/content/Hero.tsx
new file mode 100644
index 0000000..241a73b
--- /dev/null
+++ b/components/content/Hero.tsx
@@ -0,0 +1,11 @@
+export default function Hero({ label, subtitle, children }: { label: string; subtitle?: string; children?: React.ReactNode }) {
+ return (
+
+
+ {label}
+
+ {subtitle &&
{subtitle}
}
+ {children}
+
+ );
+}
diff --git a/components/RotatingHeadline.tsx b/components/content/RotatingHeadline.tsx
similarity index 100%
rename from components/RotatingHeadline.tsx
rename to components/content/RotatingHeadline.tsx
diff --git a/components/Testimonials.tsx b/components/content/Testimonials.tsx
similarity index 59%
rename from components/Testimonials.tsx
rename to components/content/Testimonials.tsx
index b482207..c261032 100644
--- a/components/Testimonials.tsx
+++ b/components/content/Testimonials.tsx
@@ -1,6 +1,7 @@
"use client";
-import { useState } from "react";
+import { useEffect, useState } from "react";
+import { IconPlayerPauseFilled, IconPlayerPlayFilled, IconPoint, IconPointFilled } from '@tabler/icons-react';
type Testimonial = {
name: string;
@@ -15,10 +16,21 @@ type TestimonialsProps = {
export default function Testimonials({ items }: TestimonialsProps) {
const [activeIndex, setActiveIndex] = useState(0);
+ const [isPlaying, setIsPlaying] = useState(true);
const active = items[activeIndex];
if (!active) return null;
+ useEffect(() => {
+ if (items.length <= 1 || !isPlaying) return;
+
+ const id = setInterval(() => {
+ setActiveIndex((i) => (i + 1) % items.length);
+ }, 5000);
+
+ return () => clearInterval(id);
+ }, [items.length, isPlaying]);
+
return (
{/* header: avatar + name + title */}
@@ -30,26 +42,25 @@ export default function Testimonials({ items }: TestimonialsProps) {
- {/* quote */}