portfolio developer personal-website dark-theme tech dark
Portfolio Developer
Dark developer portfolio with terminal-inspired design, project showcase, tech stack badges, and timeline experience section.
dark Responsive Vanilla JS
Live Preview
Sections
navbarherotech-stackprojectsexperienceblogcontactfooter
Patterns used
HTML
<!DOCTYPE html>
<html lang="en" class="scroll-smooth">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Alex Chen — Full-Stack Engineer</title>
<meta name="description" content="Full-stack engineer building reliable systems with TypeScript, Go, and cloud-native infrastructure." />
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://webspire.de/webspire-tokens.css">
<link rel="stylesheet" href="https://webspire.de/webspire-components.css">
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
<style>
body { font-family: 'Inter', system-ui, sans-serif; }
.font-mono { font-family: 'JetBrains Mono', ui-monospace, monospace; }
/* Brand tokens */
:root {
--ws-color-accent: oklch(0.68 0.14 205);
--ws-color-accent-light: oklch(0.76 0.12 205);
--ws-color-accent-dark: oklch(0.56 0.16 205);
}
/* Subtle cyan grid lines over dark background */
.grid-bg {
background-image:
linear-gradient(oklch(0.68 0.14 205 / 0.03) 1px, transparent 1px),
linear-gradient(90deg, oklch(0.68 0.14 205 / 0.03) 1px, transparent 1px);
background-size: 48px 48px;
}
/* Timeline connector */
.timeline-line::before {
content: '';
position: absolute;
left: 7px;
top: 28px;
bottom: 0;
width: 2px;
background: linear-gradient(to bottom, oklch(0.68 0.14 205), transparent);
}
/* interactions/hover-lift */
.hover-lift {
--lift-distance: -4px;
--lift-shadow: 0 8px 24px oklch(0 0 0 / 0.4);
--lift-duration: 0.25s;
transition:
transform var(--lift-duration) cubic-bezier(0.16, 1, 0.3, 1),
box-shadow var(--lift-duration) cubic-bezier(0.16, 1, 0.3, 1);
}
.hover-lift:hover {
transform: translateY(var(--lift-distance));
box-shadow: var(--lift-shadow);
}
@media (prefers-reduced-motion: reduce) {
.hover-lift { transition: none; }
}
</style>
</head>
<body class="bg-slate-950 text-slate-300 antialiased grid-bg">
<!-- Navbar -->
<nav class="ws-navbar fixed top-0 inset-x-0 z-50 border-b border-slate-800/60 bg-slate-950/80 backdrop-blur-md" aria-label="Main navigation">
<div class="mx-auto max-w-5xl flex items-center justify-between px-6 py-4">
<a href="#" class="font-mono text-sm font-medium text-white tracking-tight">
<span style="color: var(--ws-color-accent);">~/</span>alex.chen
</a>
<ul class="hidden md:flex items-center gap-8 text-sm" role="list">
<li><a href="#projects" class="text-slate-400 hover:text-white transition-colors">Projects</a></li>
<li><a href="#experience" class="text-slate-400 hover:text-white transition-colors">Experience</a></li>
<li><a href="#writing" class="text-slate-400 hover:text-white transition-colors">Writing</a></li>
<li><a href="#contact" class="text-slate-400 hover:text-white transition-colors">Contact</a></li>
</ul>
<button
type="button"
class="md:hidden p-2 text-slate-400 hover:text-white"
aria-label="Open menu"
aria-expanded="false"
id="menu-toggle"
>
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
<!-- Mobile menu -->
<div id="mobile-menu" class="hidden md:hidden border-t border-slate-800/60 bg-slate-950/95 backdrop-blur-md">
<ul class="flex flex-col gap-1 px-6 py-4 text-sm" role="list">
<li><a href="#projects" class="block py-2 text-slate-400 hover:text-white transition-colors">Projects</a></li>
<li><a href="#experience" class="block py-2 text-slate-400 hover:text-white transition-colors">Experience</a></li>
<li><a href="#writing" class="block py-2 text-slate-400 hover:text-white transition-colors">Writing</a></li>
<li><a href="#contact" class="block py-2 text-slate-400 hover:text-white transition-colors">Contact</a></li>
</ul>
</div>
</nav>
<main>
<!-- Hero -->
<section class="ws-hero min-h-[85vh] flex items-center pt-20" aria-label="Introduction">
<div class="mx-auto max-w-5xl px-6 py-24">
<p class="font-mono text-sm mb-4" style="color: var(--ws-color-accent);">Hi, my name is</p>
<h1 class="text-4xl sm:text-5xl lg:text-6xl font-bold text-white tracking-tight leading-tight">
Alex Chen.
</h1>
<h2 class="mt-2 text-3xl sm:text-4xl lg:text-5xl font-bold text-slate-500 tracking-tight leading-tight">
I build things for the web.
</h2>
<p class="mt-6 max-w-xl text-base sm:text-lg text-slate-400 leading-relaxed">
Full-stack engineer with 8 years of experience shipping products at scale.
I care about clean APIs, resilient infrastructure, and interfaces that get out of the way.
Currently building developer tools at <span style="color: var(--ws-color-accent);">Vercel</span>.
</p>
<div class="mt-10 flex flex-wrap gap-4">
<a href="#projects" class="hover-lift inline-flex items-center gap-2 rounded-md border px-5 py-2.5 text-sm font-medium transition-colors" style="border-color: var(--ws-color-accent); color: var(--ws-color-accent);">
View my work
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" /></svg>
</a>
<a href="/resume.pdf" class="inline-flex items-center gap-2 text-slate-400 hover:text-white px-5 py-2.5 text-sm font-medium transition-colors">
Resume
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /></svg>
</a>
</div>
</div>
</section>
<!-- Tech Stack -->
<section class="ws-features py-20 border-t border-slate-800/40" aria-labelledby="stack-heading">
<div class="mx-auto max-w-5xl px-6">
<div class="flex items-center gap-3 mb-10">
<span class="font-mono text-sm" style="color: var(--ws-color-accent);">01.</span>
<h2 id="stack-heading" class="text-xl font-semibold text-white">Tech Stack</h2>
<div class="flex-1 h-px bg-slate-800" aria-hidden="true"></div>
</div>
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-3">
<div class="hover-lift flex items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-4 py-3 text-sm">
<span class="text-lg" aria-hidden="true">TS</span>
<span>TypeScript</span>
</div>
<div class="hover-lift flex items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-4 py-3 text-sm">
<span class="text-lg" aria-hidden="true">Go</span>
<span>Golang</span>
</div>
<div class="hover-lift flex items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-4 py-3 text-sm">
<span class="text-lg" aria-hidden="true">Rs</span>
<span>Rust</span>
</div>
<div class="hover-lift flex items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-4 py-3 text-sm">
<span class="text-lg" aria-hidden="true">Py</span>
<span>Python</span>
</div>
<div class="hover-lift flex items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-4 py-3 text-sm">
<span class="text-lg" aria-hidden="true">Re</span>
<span>React</span>
</div>
<div class="hover-lift flex items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-4 py-3 text-sm">
<span class="text-lg" aria-hidden="true">Nx</span>
<span>Next.js</span>
</div>
<div class="hover-lift flex items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-4 py-3 text-sm">
<span class="text-lg" aria-hidden="true">Nd</span>
<span>Node.js</span>
</div>
<div class="hover-lift flex items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-4 py-3 text-sm">
<span class="text-lg" aria-hidden="true">Pg</span>
<span>PostgreSQL</span>
</div>
<div class="hover-lift flex items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-4 py-3 text-sm">
<span class="text-lg" aria-hidden="true">Rd</span>
<span>Redis</span>
</div>
<div class="hover-lift flex items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-4 py-3 text-sm">
<span class="text-lg" aria-hidden="true">Dk</span>
<span>Docker</span>
</div>
<div class="hover-lift flex items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-4 py-3 text-sm">
<span class="text-lg" aria-hidden="true">K8</span>
<span>Kubernetes</span>
</div>
<div class="hover-lift flex items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-4 py-3 text-sm">
<span class="text-lg" aria-hidden="true">Aw</span>
<span>AWS</span>
</div>
</div>
</div>
</section>
<!-- Projects -->
<section id="projects" class="ws-cards py-20 border-t border-slate-800/40" aria-labelledby="projects-heading">
<div class="mx-auto max-w-5xl px-6">
<div class="flex items-center gap-3 mb-10">
<span class="font-mono text-sm" style="color: var(--ws-color-accent);">02.</span>
<h2 id="projects-heading" class="text-xl font-semibold text-white">Featured Projects</h2>
<div class="flex-1 h-px bg-slate-800" aria-hidden="true"></div>
</div>
<div class="grid gap-6 md:grid-cols-3">
<!-- Project 1 -->
<article class="hover-lift group rounded-lg border border-slate-800 bg-slate-900/40 p-6 hover:border-slate-700 transition-colors">
<div class="flex items-start justify-between mb-4">
<svg class="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true" style="color: var(--ws-color-accent);"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" /></svg>
<div class="flex gap-3">
<a href="#" class="text-slate-500 hover:text-white transition-colors" aria-label="View Synth CLI on GitHub">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" /></svg>
</a>
<a href="#" class="text-slate-500 hover:text-white transition-colors" aria-label="Open Synth CLI live demo">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /></svg>
</a>
</div>
</div>
<h3 class="text-lg font-semibold text-white mb-2 group-hover:transition-colors" style="--tw-text-opacity: 1;">
<span class="group-hover:text-[oklch(0.68_0.14_205)] transition-colors">Synth CLI</span>
</h3>
<p class="text-sm text-slate-400 leading-relaxed mb-4">
A code generation CLI that scaffolds full-stack TypeScript apps from schema definitions. Supports REST, GraphQL, and tRPC targets.
</p>
<ul class="flex flex-wrap gap-2" role="list" aria-label="Technologies used">
<li class="font-mono text-xs bg-slate-800/60 border border-slate-700/40 rounded px-2 py-0.5" style="color: oklch(0.68 0.14 205 / 0.8);">TypeScript</li>
<li class="font-mono text-xs bg-slate-800/60 border border-slate-700/40 rounded px-2 py-0.5" style="color: oklch(0.68 0.14 205 / 0.8);">Node.js</li>
<li class="font-mono text-xs bg-slate-800/60 border border-slate-700/40 rounded px-2 py-0.5" style="color: oklch(0.68 0.14 205 / 0.8);">Zod</li>
</ul>
</article>
<!-- Project 2 -->
<article class="hover-lift group rounded-lg border border-slate-800 bg-slate-900/40 p-6 hover:border-slate-700 transition-colors">
<div class="flex items-start justify-between mb-4">
<svg class="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true" style="color: var(--ws-color-accent);"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2" /></svg>
<div class="flex gap-3">
<a href="#" class="text-slate-500 hover:text-white transition-colors" aria-label="View Pulse Monitor on GitHub">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" /></svg>
</a>
<a href="#" class="text-slate-500 hover:text-white transition-colors" aria-label="Open Pulse Monitor live demo">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /></svg>
</a>
</div>
</div>
<h3 class="text-lg font-semibold text-white mb-2">
<span class="group-hover:text-[oklch(0.68_0.14_205)] transition-colors">Pulse Monitor</span>
</h3>
<p class="text-sm text-slate-400 leading-relaxed mb-4">
Real-time infrastructure monitoring dashboard with anomaly detection. Processes 50K+ events/sec using Go workers and Redis streams.
</p>
<ul class="flex flex-wrap gap-2" role="list" aria-label="Technologies used">
<li class="font-mono text-xs bg-slate-800/60 border border-slate-700/40 rounded px-2 py-0.5" style="color: oklch(0.68 0.14 205 / 0.8);">Go</li>
<li class="font-mono text-xs bg-slate-800/60 border border-slate-700/40 rounded px-2 py-0.5" style="color: oklch(0.68 0.14 205 / 0.8);">Redis</li>
<li class="font-mono text-xs bg-slate-800/60 border border-slate-700/40 rounded px-2 py-0.5" style="color: oklch(0.68 0.14 205 / 0.8);">React</li>
<li class="font-mono text-xs bg-slate-800/60 border border-slate-700/40 rounded px-2 py-0.5" style="color: oklch(0.68 0.14 205 / 0.8);">WebSocket</li>
</ul>
</article>
<!-- Project 3 -->
<article class="hover-lift group rounded-lg border border-slate-800 bg-slate-900/40 p-6 hover:border-slate-700 transition-colors">
<div class="flex items-start justify-between mb-4">
<svg class="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true" style="color: var(--ws-color-accent);"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z" /></svg>
<div class="flex gap-3">
<a href="#" class="text-slate-500 hover:text-white transition-colors" aria-label="View Edge Functions Kit on GitHub">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" /></svg>
</a>
<a href="#" class="text-slate-500 hover:text-white transition-colors" aria-label="Open Edge Functions Kit live demo">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /></svg>
</a>
</div>
</div>
<h3 class="text-lg font-semibold text-white mb-2">
<span class="group-hover:text-[oklch(0.68_0.14_205)] transition-colors">Edge Functions Kit</span>
</h3>
<p class="text-sm text-slate-400 leading-relaxed mb-4">
A library of composable middleware for Cloudflare Workers and Deno Deploy. Auth, rate limiting, caching, and CORS out of the box.
</p>
<ul class="flex flex-wrap gap-2" role="list" aria-label="Technologies used">
<li class="font-mono text-xs bg-slate-800/60 border border-slate-700/40 rounded px-2 py-0.5" style="color: oklch(0.68 0.14 205 / 0.8);">TypeScript</li>
<li class="font-mono text-xs bg-slate-800/60 border border-slate-700/40 rounded px-2 py-0.5" style="color: oklch(0.68 0.14 205 / 0.8);">Workers</li>
<li class="font-mono text-xs bg-slate-800/60 border border-slate-700/40 rounded px-2 py-0.5" style="color: oklch(0.68 0.14 205 / 0.8);">Deno</li>
</ul>
</article>
</div>
</div>
</section>
<!-- Experience -->
<section id="experience" class="ws-steps py-20 border-t border-slate-800/40" aria-labelledby="experience-heading">
<div class="mx-auto max-w-5xl px-6">
<div class="flex items-center gap-3 mb-10">
<span class="font-mono text-sm" style="color: var(--ws-color-accent);">03.</span>
<h2 id="experience-heading" class="text-xl font-semibold text-white">Experience</h2>
<div class="flex-1 h-px bg-slate-800" aria-hidden="true"></div>
</div>
<div class="space-y-10 max-w-2xl">
<!-- Role 1 -->
<div class="relative pl-8 timeline-line">
<div class="absolute left-0 top-1.5 w-4 h-4 rounded-full border-2 bg-slate-950" style="border-color: var(--ws-color-accent);" aria-hidden="true"></div>
<div class="flex flex-col sm:flex-row sm:items-baseline sm:justify-between gap-1 mb-2">
<h3 class="text-white font-semibold">Senior Software Engineer <span style="color: var(--ws-color-accent);">@ Vercel</span></h3>
<span class="font-mono text-xs text-slate-500">2022 -- present</span>
</div>
<ul class="space-y-2 text-sm text-slate-400">
<li class="flex gap-2"><span class="mt-0.5 shrink-0" style="color: var(--ws-color-accent);" aria-hidden="true">></span>Lead development of the edge middleware runtime, serving 2B+ requests/month</li>
<li class="flex gap-2"><span class="mt-0.5 shrink-0" style="color: var(--ws-color-accent);" aria-hidden="true">></span>Designed the incremental build cache system, reducing cold builds by 60%</li>
<li class="flex gap-2"><span class="mt-0.5 shrink-0" style="color: var(--ws-color-accent);" aria-hidden="true">></span>Mentoring a team of 4 engineers across the platform infrastructure group</li>
</ul>
</div>
<!-- Role 2 -->
<div class="relative pl-8 timeline-line">
<div class="absolute left-0 top-1.5 w-4 h-4 rounded-full border-2 border-slate-600 bg-slate-950" aria-hidden="true"></div>
<div class="flex flex-col sm:flex-row sm:items-baseline sm:justify-between gap-1 mb-2">
<h3 class="text-white font-semibold">Software Engineer <span style="color: var(--ws-color-accent);">@ Stripe</span></h3>
<span class="font-mono text-xs text-slate-500">2019 -- 2022</span>
</div>
<ul class="space-y-2 text-sm text-slate-400">
<li class="flex gap-2"><span class="mt-0.5 shrink-0" style="color: var(--ws-color-accent);" aria-hidden="true">></span>Built the real-time fraud detection pipeline processing 500K+ transactions/day</li>
<li class="flex gap-2"><span class="mt-0.5 shrink-0" style="color: var(--ws-color-accent);" aria-hidden="true">></span>Migrated the payments API from Ruby to Go, improving p99 latency by 40%</li>
<li class="flex gap-2"><span class="mt-0.5 shrink-0" style="color: var(--ws-color-accent);" aria-hidden="true">></span>Authored internal RFC for the distributed rate-limiting architecture</li>
</ul>
</div>
<!-- Role 3 -->
<div class="relative pl-8">
<div class="absolute left-0 top-1.5 w-4 h-4 rounded-full border-2 border-slate-700 bg-slate-950" aria-hidden="true"></div>
<div class="flex flex-col sm:flex-row sm:items-baseline sm:justify-between gap-1 mb-2">
<h3 class="text-white font-semibold">Full-Stack Developer <span style="color: var(--ws-color-accent);">@ Postman</span></h3>
<span class="font-mono text-xs text-slate-500">2017 -- 2019</span>
</div>
<ul class="space-y-2 text-sm text-slate-400">
<li class="flex gap-2"><span class="mt-0.5 shrink-0" style="color: var(--ws-color-accent);" aria-hidden="true">></span>Developed the collection runner v2 with parallel execution support</li>
<li class="flex gap-2"><span class="mt-0.5 shrink-0" style="color: var(--ws-color-accent);" aria-hidden="true">></span>Built the team workspace collaboration features used by 100K+ teams</li>
<li class="flex gap-2"><span class="mt-0.5 shrink-0" style="color: var(--ws-color-accent);" aria-hidden="true">></span>Shipped the first public GraphQL API integration for Postman</li>
</ul>
</div>
</div>
</div>
</section>
<!-- Writing -->
<section id="writing" class="ws-blog py-20 border-t border-slate-800/40" aria-labelledby="writing-heading">
<div class="mx-auto max-w-5xl px-6">
<div class="flex items-center gap-3 mb-10">
<span class="font-mono text-sm" style="color: var(--ws-color-accent);">04.</span>
<h2 id="writing-heading" class="text-xl font-semibold text-white">Writing</h2>
<div class="flex-1 h-px bg-slate-800" aria-hidden="true"></div>
</div>
<div class="grid gap-6 md:grid-cols-3">
<article class="group">
<a href="#" class="hover-lift block rounded-lg border border-slate-800 bg-slate-900/40 p-6 hover:border-slate-700 transition-colors h-full">
<time class="font-mono text-xs text-slate-500" datetime="2026-02-15">Feb 2026</time>
<h3 class="mt-3 text-white font-semibold group-hover:text-[oklch(0.68_0.14_205)] transition-colors">Edge-first Architecture: Patterns That Actually Work</h3>
<p class="mt-2 text-sm text-slate-400 leading-relaxed">
Practical patterns for building applications that run at the edge without the usual cold-start headaches.
</p>
</a>
</article>
<article class="group">
<a href="#" class="hover-lift block rounded-lg border border-slate-800 bg-slate-900/40 p-6 hover:border-slate-700 transition-colors h-full">
<time class="font-mono text-xs text-slate-500" datetime="2025-11-08">Nov 2025</time>
<h3 class="mt-3 text-white font-semibold group-hover:text-[oklch(0.68_0.14_205)] transition-colors">Why I Switched from REST to tRPC (and Back Again)</h3>
<p class="mt-2 text-sm text-slate-400 leading-relaxed">
A candid look at the tradeoffs of end-to-end type safety versus ecosystem compatibility in large teams.
</p>
</a>
</article>
<article class="group">
<a href="#" class="hover-lift block rounded-lg border border-slate-800 bg-slate-900/40 p-6 hover:border-slate-700 transition-colors h-full">
<time class="font-mono text-xs text-slate-500" datetime="2025-08-22">Aug 2025</time>
<h3 class="mt-3 text-white font-semibold group-hover:text-[oklch(0.68_0.14_205)] transition-colors">Building a Code Generator That Developers Don't Hate</h3>
<p class="mt-2 text-sm text-slate-400 leading-relaxed">
Lessons learned from Synth CLI: how to make generated code feel hand-written.
</p>
</a>
</article>
</div>
</div>
</section>
<!-- Contact -->
<section id="contact" class="ws-contact py-24 border-t border-slate-800/40" aria-labelledby="contact-heading">
<div class="mx-auto max-w-xl px-6 text-center">
<span class="font-mono text-sm" style="color: var(--ws-color-accent);">05. What's next?</span>
<h2 id="contact-heading" class="mt-4 text-3xl sm:text-4xl font-bold text-white">Get In Touch</h2>
<p class="mt-4 text-slate-400 leading-relaxed">
I'm always interested in hearing about new opportunities, open-source collaborations,
or just a good conversation about distributed systems. My inbox is open.
</p>
<a href="mailto:alex@alexchen.dev" class="hover-lift mt-8 inline-flex items-center gap-2 rounded-md border px-6 py-3 text-sm font-medium transition-colors" style="border-color: var(--ws-color-accent); color: var(--ws-color-accent);">
Say Hello
</a>
<ul class="mt-10 flex justify-center gap-6" role="list" aria-label="Social links">
<li>
<a href="#" class="text-slate-500 hover:text-[oklch(0.68_0.14_205)] transition-colors" aria-label="GitHub profile">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" /></svg>
</a>
</li>
<li>
<a href="#" class="text-slate-500 hover:text-[oklch(0.68_0.14_205)] transition-colors" aria-label="LinkedIn profile">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" /></svg>
</a>
</li>
<li>
<a href="#" class="text-slate-500 hover:text-[oklch(0.68_0.14_205)] transition-colors" aria-label="X (Twitter) profile">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" /></svg>
</a>
</li>
</ul>
</div>
</section>
</main>
<!-- Footer -->
<footer class="ws-footer border-t border-slate-800/40 py-8">
<div class="mx-auto max-w-5xl px-6 flex flex-col sm:flex-row items-center justify-between gap-4">
<p class="font-mono text-xs text-slate-600">
Designed & built by Alex Chen
</p>
<a href="https://github.com/alexchen/portfolio" class="font-mono text-xs text-slate-600 hover:text-[oklch(0.68_0.14_205)] transition-colors" aria-label="View source code on GitHub">
source on github
</a>
</div>
</footer>
<script>
const toggle = document.getElementById('menu-toggle');
const menu = document.getElementById('mobile-menu');
if (toggle && menu) {
toggle.addEventListener('click', () => {
const expanded = toggle.getAttribute('aria-expanded') === 'true';
toggle.setAttribute('aria-expanded', String(!expanded));
menu.classList.toggle('hidden');
});
menu.querySelectorAll('a').forEach(link => {
link.addEventListener('click', () => {
menu.classList.add('hidden');
toggle.setAttribute('aria-expanded', 'false');
});
});
}
</script>
</body>
</html>
Developer-focused portfolio with dark theme and terminal-inspired design. Cyan accents and monospace touches create an authentic developer aesthetic.