feat: update app pages and layout
This commit is contained in:
+93
-2
@@ -1,5 +1,11 @@
|
||||
import Hero from "@/components/content/Hero";
|
||||
import type { Metadata } from "next";
|
||||
import { IconBrandLinkedinFilled, IconMailFilled } from "@tabler/icons-react";
|
||||
import Hero from "@/components/content/Hero";
|
||||
import SectionLabel from "@/components/layout/SectionLabel";
|
||||
import AccentLink from "@/components/navigation/AccentLink";
|
||||
import GiteaIcon from "@/components/icons/GiteaIcon";
|
||||
import Tooltip from "@/components/ui/Tooltip";
|
||||
import { colors, education, timeline } from "@/constants";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "About — Angel Mankel",
|
||||
@@ -7,6 +13,91 @@ export const metadata: Metadata = {
|
||||
|
||||
export default function AboutPage() {
|
||||
return (
|
||||
<Hero label="About"/>
|
||||
<div className="space-y-14">
|
||||
<Hero label="About">
|
||||
<div className="space-y-5 text-[19px] leading-[1.65]">
|
||||
<p>
|
||||
I came up through healthcare IT — help desk, then Salesforce
|
||||
administration, then software engineering. A path that taught me
|
||||
to translate between operations, design, and engineering without
|
||||
losing the thread.
|
||||
</p>
|
||||
<p>
|
||||
These days I write React and TypeScript for production, lead
|
||||
component-library work, and spend a lot of time in Claude Code —
|
||||
custom slash commands, MCP integrations, agent workflows. The
|
||||
AI-tooling layer is reshaping how I work across the stack.
|
||||
</p>
|
||||
<p>
|
||||
Based in Arizona, looking for remote-US roles where shipping
|
||||
frontend product and building AI tooling around it are both
|
||||
first-class. Bonus points for teams that take design seriously
|
||||
and don't hand things off at every layer.
|
||||
</p>
|
||||
</div>
|
||||
</Hero>
|
||||
|
||||
<section className="space-y-4">
|
||||
<SectionLabel label="Education" />
|
||||
<ul className="space-y-2">
|
||||
{education.map((row) => (
|
||||
<li key={row.span} className="flex gap-2 text-sm">
|
||||
<span className="w-36 shrink-0 text-neutral-500">
|
||||
{row.span}
|
||||
</span>
|
||||
<span className="text-neutral-200">{row.degree} · {row.location}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section className="space-y-4">
|
||||
<SectionLabel label="Timeline" />
|
||||
<ul className="space-y-2">
|
||||
{timeline.map((row) => (
|
||||
<li key={row.span} className="flex gap-2 text-sm">
|
||||
<span className="w-36 shrink-0 text-neutral-500">
|
||||
{row.span}
|
||||
</span>
|
||||
<span className="text-neutral-200">{row.role}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<AccentLink link="/cv.pdf" label="Download CV (PDF)" />
|
||||
|
||||
<nav aria-label="Contact" className="flex gap-5 text-neutral-300">
|
||||
<Tooltip text="Email">
|
||||
<a
|
||||
href="mailto:angelmankel@gmail.com"
|
||||
aria-label="Email"
|
||||
className={`hover:text-neutral-200 rounded-md hover:bg-[${colors.accent}] p-1 transition-colors duration-200`}
|
||||
>
|
||||
<IconMailFilled size={32} />
|
||||
</a>
|
||||
</Tooltip>
|
||||
<Tooltip text="LinkedIn">
|
||||
<a
|
||||
href="https://www.linkedin.com/in/angel-mankel-0616aa132/"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
aria-label="LinkedIn"
|
||||
className={`hover:text-neutral-200 rounded-md hover:bg-[${colors.accent}] p-1 transition-colors duration-200`}
|
||||
>
|
||||
<IconBrandLinkedinFilled size={32} />
|
||||
</a>
|
||||
</Tooltip>
|
||||
<Tooltip text="Gitea">
|
||||
<a
|
||||
href="#"
|
||||
aria-label="Gitea"
|
||||
className={`hover:text-neutral-200 rounded-md hover:bg-[${colors.accent}] p-1 transition-colors duration-200`}
|
||||
>
|
||||
<GiteaIcon size={32} />
|
||||
</a>
|
||||
</Tooltip>
|
||||
</nav>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+3
-1
@@ -4,6 +4,7 @@ import "./globals.css";
|
||||
import Header from "@/components/layout/Header";
|
||||
import Footer from "@/components/layout/Footer";
|
||||
import Container from "@/components/layout/Container";
|
||||
import Cursor from "@/components/ui/Cursor";
|
||||
|
||||
const inter = Inter({
|
||||
variable: "--font-inter",
|
||||
@@ -29,9 +30,10 @@ export default function RootLayout({
|
||||
return (
|
||||
<html
|
||||
lang="en"
|
||||
className={`${inter.variable} ${instrumentSerif.variable} h-full antialiased`}
|
||||
className={`${inter.variable} ${instrumentSerif.variable} h-full antialiased scrollbar-track-transparent scrollbar-thumb-neutral-700`}
|
||||
>
|
||||
<body className="min-h-full flex flex-col font-sans">
|
||||
{/* <Cursor /> */}
|
||||
<Header />
|
||||
<Container>{children}</Container>
|
||||
<Footer />
|
||||
|
||||
+34
-40
@@ -1,49 +1,22 @@
|
||||
import Hero from "@/components/content/Hero";
|
||||
import Testimonials from "@/components/content/Testimonials";
|
||||
import RotatingWord from "@/components/content/RotatingWord";
|
||||
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.",
|
||||
},
|
||||
];
|
||||
import ProjectCard from "@/components/content/ProjectCard";
|
||||
import { testimonials, projects } from "@/constants";
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<div>
|
||||
<Hero label="Angel Mankel">
|
||||
<div className="space-y-5">
|
||||
<div className="space-y-5 mb-4">
|
||||
<p className="font-serif italic text-3xl leading-[1.3]">
|
||||
I’m a creator at heart.
|
||||
I'm{" "}
|
||||
<RotatingWord
|
||||
items={["a developer", "a creative", "a tinkerer"]}
|
||||
/>
|
||||
.
|
||||
</p>
|
||||
|
||||
<p className="text-[19px] leading-[1.65]">
|
||||
@@ -52,16 +25,37 @@ export default function HomePage() {
|
||||
</p>
|
||||
|
||||
<p className="text-[19px] leading-[1.65]">
|
||||
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.
|
||||
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.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<AccentLink label="About Me" link="/about" />
|
||||
</div>
|
||||
</Hero>
|
||||
|
||||
{/* Projects */}
|
||||
<div className="mt-20">
|
||||
<SectionLabel label="Selected Projects" />
|
||||
|
||||
{projects.slice(0,3).map((project, index) => (
|
||||
<ProjectCard key={index} {...project} />
|
||||
))}
|
||||
|
||||
<div className="mt-5">
|
||||
<AccentLink label="See all projects" link="/projects" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Testimonials */}
|
||||
<div className="mt-20">
|
||||
<SectionLabel label="What people say" />
|
||||
<Testimonials items={testimonialsData} />
|
||||
<div className="mt-5">
|
||||
<Testimonials items={testimonials} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import Hero from "@/components/content/Hero";
|
||||
import type { Metadata } from "next";
|
||||
import ProjectCard from "@/components/content/ProjectCard";
|
||||
import { projects } from "@/constants";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Work — Angel Mankel",
|
||||
@@ -7,6 +9,14 @@ export const metadata: Metadata = {
|
||||
|
||||
export default function ProjectsPage() {
|
||||
return (
|
||||
<>
|
||||
<div className="mb-15">
|
||||
<Hero label="Projects" subtitle="Selected work, written as postmortems." />
|
||||
</div>
|
||||
|
||||
{projects.map((project, index) => (
|
||||
<ProjectCard key={index} {...project} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
+67
-2
@@ -1,12 +1,77 @@
|
||||
import Hero from "@/components/content/Hero";
|
||||
import type { Metadata } from "next";
|
||||
import Hero from "@/components/content/Hero";
|
||||
import SectionLabel from "@/components/layout/SectionLabel";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Uses — Angel Mankel",
|
||||
};
|
||||
|
||||
type Section =
|
||||
| { label: string; kind: "list"; items: string[] }
|
||||
| { label: string; kind: "prose"; paragraphs: string[] };
|
||||
|
||||
const sections: Section[] = [
|
||||
{
|
||||
label: "Hardware",
|
||||
kind: "list",
|
||||
items: [
|
||||
"Custom desktop — i9-12900H, 32GB RAM, Intel Iris Xe",
|
||||
"Nobara Linux 43 · KDE Plasma 6 · Wayland",
|
||||
"Headphones / keyboard / monitor — placeholder",
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Editor & Shell",
|
||||
kind: "list",
|
||||
items: [
|
||||
"VS Code with a personal extension pack — placeholder",
|
||||
"Bash / zsh — placeholder for shell",
|
||||
"JetBrains Mono as the editor font",
|
||||
"Theme — placeholder",
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "AI Workflow",
|
||||
kind: "prose",
|
||||
paragraphs: [
|
||||
"Claude Code is the daily driver — custom slash commands, MCP servers wired into my editor, and agent workflows that handle the repeat work so I can stay in the design problem.",
|
||||
"Placeholder paragraph two — name a specific workflow and the time it saves.",
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Self-hosting",
|
||||
kind: "list",
|
||||
items: [
|
||||
"Bare-metal home server, exposed to the internet through Traefik",
|
||||
"This site lives on it — Next.js standalone build, no managed host",
|
||||
"Other services — placeholder",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default function UsesPage() {
|
||||
return (
|
||||
<Hero label="Uses" subtitle="Tools and technologies I use in my work."/>
|
||||
<div className="space-y-14">
|
||||
<Hero label="Uses" subtitle="What I reach for daily." />
|
||||
|
||||
{sections.map((section) => (
|
||||
<section key={section.label} className="space-y-4">
|
||||
<SectionLabel label={section.label} />
|
||||
{section.kind === "list" ? (
|
||||
<ul className="space-y-2 text-[15px] leading-[1.65] text-neutral-200">
|
||||
{section.items.map((item) => (
|
||||
<li key={item}>{item}</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<div className="space-y-4 text-[15px] leading-[1.65] text-neutral-200">
|
||||
{section.paragraphs.map((p) => (
|
||||
<p key={p}>{p}</p>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user