portfolio/app/cv/page.tsx
GeorgeWebberley 8508b679c0
All checks were successful
ci/woodpecker/release/woodpecker Pipeline was successful
Fixed mobile layout of CV
2026-02-04 16:45:06 +01:00

382 lines
18 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import PageLayout from "@/components/PageLayout";
import { Mail, Globe, MapPin, ExternalLink, Server, Zap } from "lucide-react";
export default function CVPage() {
return (
<PageLayout backLink="/" maxWidth="5xl">
{/* Hide the print button itself during printing */}
<div className="flex justify-end mb-4 no-print">
<button
onClick={() => window.print()}
className="flex items-center gap-2 px-4 py-2 bg-slate-800 hover:bg-orange-600 text-white text-xs font-mono tracking-widest uppercase transition-colors rounded-sm"
>
<Zap size={14} /> Print PDF
</button>
</div>
{/* Main Container*/}
<div className="bg-white text-slate-900 p-8 md:p-16 rounded-sm shadow-2xl print:shadow-none print:p-12 print:m-0 font-sans print:text-[12pt] leading-normal">
<header className="border-b-4 border-slate-900 pb-8 print:pb-4 mb-8 print:mb-6 flex flex-col md:flex-row print:grid print:grid-cols-[1.5fr_1fr] justify-between items-start gap-6">
<div className="flex flex-wrap items-center gap-4 sm:gap-6 mb-4 print:mb-2 print:flex-nowrap">
<div className="shrink-0">
<img
src="/profile.jpg"
alt="George A. Webberley"
className="w-20 h-20 md:w-24 md:h-24 print:w-16 print:h-16 rounded-full object-cover border-2 border-slate-100 shadow-sm"
/>
</div>
<div className="min-w-0 flex-1">
<h1 className="text-3xl md:text-5xl print:text-3xl font-extrabold tracking-tighter mb-1 text-slate-900 lg:whitespace-nowrap print:whitespace-nowrap">
George A. Webberley
</h1>
<p className="text-lg md:text-2xl print:text-[14pt] text-orange-600 font-bold uppercase tracking-tight lg:whitespace-nowrap print:whitespace-nowrap">
Full Stack Engineer // Systems Architect
</p>
</div>
</div>
{/* Contact Info */}
<div className="space-y-1 text-sm print:text-[9px] text-slate-500 font-mono text-right print:w-full print:flex print:flex-col print:items-end">
<div className="flex items-center md:justify-end gap-2">
<MapPin size={14} /> Copenhagen, Denmark
</div>
<div className="flex items-center md:justify-end gap-2">
<Mail size={14} /> george@georgew.dev
</div>
<div className="flex items-center md:justify-end gap-2 text-orange-600 font-bold">
<Globe size={14} /> georgew.dev
</div>
</div>
</header>
<div className="grid grid-cols-1 lg:grid-cols-12 print:grid-cols-12 gap-8 print:gap-10">
{/* Main Column */}
<div className="lg:col-span-8 print:col-span-8 space-y-10 print:space-y-6">
<section>
<h2 className="text-xs uppercase tracking-[0.2em] font-black text-slate-400 mb-4 print:mb-2 border-b border-slate-100 pb-2">
Professional Summary
</h2>
<p className="text-md print:text-sm leading-relaxed text-slate-700">
After 5 years as a dental surgeon, a serendipitous broken leg
led me to discover that software engineering perfectly suits my
analytical mind. Now an MSc (Distinction) graduate and Senior
Engineer, my core expertise lies in the entire product
lifecycle. Im less about a specific niche and more about the
whole stack. I enjoy the challenge of creating a clean frontend,
connecting a stable backend API, and building the infrastructure
that keeps it all running. I&apos;m always looking for the most
efficient way to get a project from &apos;concept&apos; to
&apos;shipped&apos;.
</p>
</section>
<section>
<h2 className="text-xs uppercase tracking-[0.2em] font-black text-slate-400 mb-6 print:mb-3 border-b border-slate-100 pb-2">
Engineering Experience
</h2>
<div className="space-y-10 print:space-y-6">
{/* Brain+ Section */}
<div className="break-inside-avoid">
<div className="flex justify-between items-baseline mb-1">
<h3 className="text-xl print:text-base font-bold italic text-slate-900">
Brain+, Copenhagen
</h3>
<span className="text-sm print:text-xs font-mono font-bold text-orange-600 uppercase">
2022 Present
</span>
</div>
<p className="text-slate-500 font-bold mb-3 print:mb-1 italic text-sm print:text-xs">
Technical Lead & Senior Full Stack Developer
</p>
<ul className="list-disc ml-5 space-y-2 text-slate-600 text-sm print:text-[12px] print:leading-snug">
<li>
<strong>Product Ownership:</strong> I act as the bridge
between technical and product teams; I handle the full
product lifecycle from initial design and sprint planning
to final demos.
</li>
<li>
<strong>Infrastructure:</strong> Architected a resilient
multi-cloud setup focusing on high availability,
scalability, and security. I leveraged container
orchestration (K8s), modern load balancers, and VPC
security policies all managed through IaC (Terraform) to
ensure 24/7 reliability.
</li>
<li>
<strong>DevOps & Automation:</strong> Built automated
CI/CD pipelines using GitHub Actions and Fastlane for
mobile releases. I utilize Kubectl and custom Makefiles to
streamline cluster management and standardize local
development environments.
</li>
<li>
<strong>Full Stack Delivery:</strong> Scaled core features
using Ruby on Rails REST API services and Flask, while
managing the rigorous documentation and release processes
required for high-stakes medical compliance.
</li>
</ul>
</div>
{/* Other Roles */}
<div className="space-y-8 print:space-y-4">
{/* StageUp */}
<div className="break-inside-avoid">
<div className="flex justify-between items-baseline mb-1">
<h4 className="text-lg print:text-sm font-bold italic text-slate-800">
StageUp, Cardiff
</h4>
<span className="text-xs font-mono text-slate-400 uppercase">
2021 2022
</span>
</div>
<p className="text-sm print:text-xs text-slate-600 mb-3 print:mb-1.5 leading-relaxed">
Delivered new features and backend logic for a startup
platform, while maintaining the GCP infrastructure and
deployment pipelines.
</p>
<div className="flex flex-wrap gap-1.5">
{[
"Angular",
"Node.js",
"PostgreSQL",
"Terraform",
"Docker",
"GCP",
].map((t) => (
<span
key={t}
className="text-[9px] print:text-[8px] font-bold px-1.5 py-0.5 bg-slate-50 border border-slate-200 text-slate-500 rounded-sm uppercase"
>
{t}
</span>
))}
</div>
</div>
{/* Startemup */}
<div className="break-inside-avoid">
<div className="flex justify-between items-baseline mb-1">
<h4 className="text-lg print:text-sm font-bold italic text-slate-800">
Startemup, Ontario
</h4>
<span className="text-xs font-mono text-slate-400 uppercase">
2021 2023
</span>
</div>
<p className="text-sm print:text-xs text-slate-600 mb-3 print:mb-1.5 leading-relaxed">
Technical troubleshooter for complex WordPress
customizations requiring bespoke PHP logic and deep
performance optimization.
</p>
<div className="flex flex-wrap gap-1.5">
{[
"PHP",
"WordPress",
"Performance Optimization",
"Bespoke Logic",
].map((t) => (
<span
key={t}
className="text-[9px] print:text-[8px] font-bold px-1.5 py-0.5 bg-slate-50 border border-slate-200 text-slate-500 rounded-sm uppercase"
>
{t}
</span>
))}
</div>
</div>
{/* Ratoong */}
<div className="break-inside-avoid">
<div className="flex justify-between items-baseline mb-1">
<h4 className="text-lg print:text-sm font-bold italic text-slate-800">
Ratoong, Copenhagen
</h4>
<span className="text-xs font-mono text-slate-400 uppercase">
2020 2022
</span>
</div>
<p className="text-sm print:text-xs text-slate-600 mb-3 print:mb-1.5 leading-relaxed">
Leading the end-to-end development of a functional SPA,
moving from initial UI designs to a live production
environment.
</p>
<div className="flex flex-wrap gap-1.5">
{["Angular", "Firebase", "GCP", "SPA Architecture"].map(
(t) => (
<span
key={t}
className="text-[9px] print:text-[8px] font-bold px-1.5 py-0.5 bg-slate-50 border border-slate-200 text-slate-500 rounded-sm uppercase"
>
{t}
</span>
),
)}
</div>
</div>
</div>
</div>
</section>
</div>
{/* Sidebar */}
<div className="lg:col-span-4 print:col-span-4 space-y-10 print:space-y-6">
<section>
<h2 className="text-xs uppercase tracking-[0.2em] font-black text-slate-400 mb-6 print:mb-3 border-b border-slate-100 pb-2 text-slate-900">
Technical Mastery
</h2>
<div className="space-y-6 print:space-y-4">
<div>
<p className="text-[10px] font-black uppercase mb-2 text-slate-500">
Infrastructure & Ops
</p>
<div className="flex flex-wrap gap-1.5">
{[
"Kubernetes",
"Docker",
"Terraform",
"GCP",
"OTC",
"CI/CD",
"VPC",
].map((s) => (
<span
key={s}
className="px-2 py-0.5 bg-slate-900 text-white text-[10px] print:text-[8px] font-bold rounded-sm uppercase"
>
{s}
</span>
))}
</div>
</div>
<div>
<p className="text-[10px] font-black uppercase mb-2 text-slate-500">
Full Stack Engineering
</p>
<div className="flex flex-wrap gap-1.5">
{[
"TypeScript",
"Flutter",
"Python",
"React",
"Angular",
"Node.js",
"Rails",
"PostgreSQL",
"NoSQL",
].map((s) => (
<span
key={s}
className="px-2 py-0.5 bg-slate-100 text-slate-700 text-[10px] print:text-[8px] font-bold rounded-sm uppercase"
>
{s}
</span>
))}
</div>
</div>
</div>
</section>
<section>
<h2 className="text-xs uppercase tracking-[0.2em] font-black text-slate-400 mb-6 print:mb-3 border-b border-slate-100 pb-2">
Education
</h2>
<div className="space-y-4 print:space-y-2">
<div>
<p className="font-bold text-slate-900 text-sm print:text-xs">
MSc Computer Science
</p>
<p className="text-[10px] text-orange-600 font-bold uppercase tracking-tighter">
Distinction
</p>
<p className="text-[10px] text-slate-400 italic">
Univ. of Bristol
</p>
</div>
<div>
<p className="font-bold text-slate-900 text-sm print:text-xs">
Bachelor of Dental Surgery
</p>
<p className="text-[10px] text-slate-400 italic">
Univ. of Bristol (Merit)
</p>
</div>
</div>
</section>
<section>
<h2 className="text-xs uppercase tracking-[0.2em] font-black text-slate-400 mb-6 print:mb-3 border-b border-slate-100 pb-2 text-slate-900">
Systems Tinkering
</h2>
<div className="space-y-6 print:space-y-3">
<div>
<div className="flex items-center gap-2 mb-1">
<Server size={14} className="text-orange-600" />
<p className="font-bold text-slate-900 text-xs">
Cloud-Hybrid Laboratory
</p>
</div>
<p className="text-[11px] print:text-[10px] text-slate-600 leading-snug">
I manage a suite of self-hosted services. A playground for
breaking things in private. I use{" "}
<strong>Tailscale and Woodpecker CI</strong> to orchestrate
everything from <strong>Grafana surf dashboards</strong> to
personal wikis.
</p>
</div>
<div>
<div className="flex items-center gap-2 mb-1">
<Zap size={14} className="text-orange-600" />
<p className="font-bold text-slate-900 text-xs">
Product Prototyping
</p>
</div>
<p className="text-[12px] print:text-[10px] text-slate-600 leading-snug">
Building quirky apps like a &quot;not-pokemon&quot; pet
collecting game and a space-rocket countdown dashboard.
Check out my <strong>portfolio website</strong> for full
details!
</p>
</div>
</div>
</section>
<section>
<h2 className="text-xs uppercase tracking-[0.2em] font-black text-slate-400 mb-6 print:mb-3 border-b border-slate-100 pb-2 text-slate-900">
Human
</h2>
<p className="text-[12px] print:text-[10px] text-slate-600 leading-relaxed italic">
Surfing, photography, and following space news. Usually found
watching anime while tinkering with my server stack. Currently
learning Danish (undskyld forhånd).
</p>
</section>
<div className="pt-4 print:pt-2">
<div className="p-4 print:p-3 bg-orange-50 rounded-sm border-l-4 border-orange-600">
<p className="text-[10px] font-bold text-orange-600 uppercase mb-2 print:mb-1">
Portfolio Deep Dive
</p>
<p className="text-[12px] print:text-[10px] text-slate-700 mb-3 print:mb-1.5 leading-tight">
Detailed architecture diagrams and documentation:
</p>
<a
href="https://georgew.dev"
className="text-sm print:hidden font-black flex items-center gap-1 hover:underline text-slate-900"
>
GEORGEW.DEV <ExternalLink size={14} />
</a>
<div className="hidden print:block text-sm font-black text-slate-900">
GEORGEW.DEV
</div>
</div>
</div>
</div>
</div>
</div>
</PageLayout>
);
}