831 lines
31 KiB
HTML
831 lines
31 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>John Gatward | Software Engineer</title>
|
||
<meta
|
||
name="description"
|
||
content="Portfolio of John Gatward, a software engineer specialising in backend development, interactive visualisations, and self-hosted systems."
|
||
/>
|
||
<meta name="theme-color" content="#1e1e2e" />
|
||
<link rel="icon" href="icons/favicon.ico" sizes="any" />
|
||
<link rel="apple-touch-icon" href="icons/apple-touch-icon.png" />
|
||
<link
|
||
rel="preload"
|
||
href="fonts/geist-variable.ttf"
|
||
as="font"
|
||
type="font/ttf"
|
||
crossorigin
|
||
/>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||
<link
|
||
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,400;0,700;1,400&family=Fraunces:ital,opsz,wght@0,9..144,300;0,9..144,600;1,9..144,300&display=swap"
|
||
rel="stylesheet"
|
||
/>
|
||
<link rel="stylesheet" href="style.css" />
|
||
</head>
|
||
|
||
<body>
|
||
<a class="skip-link" href="#main-content">Skip to main content</a>
|
||
<!-- ─── Nav ─────────────────────────────────────────────────── -->
|
||
<nav>
|
||
<a href="#hero" class="nav-logo">havox</a>
|
||
<ul class="nav-links">
|
||
<li><a href="#about">about</a></li>
|
||
<li><a href="#skills">skills</a></li>
|
||
<li><a href="#projects">projects</a></li>
|
||
<li><a href="#contact">contact</a></li>
|
||
</ul>
|
||
<details class="nav-menu">
|
||
<summary>Menu</summary>
|
||
<ul class="mobile-nav-links">
|
||
<li><a href="#about">about</a></li>
|
||
<li><a href="#skills">skills</a></li>
|
||
<li><a href="#projects">projects</a></li>
|
||
<li><a href="#contact">contact</a></li>
|
||
</ul>
|
||
</details>
|
||
</nav>
|
||
|
||
<main id="main-content" tabindex="-1">
|
||
<!-- ─── Hero ─────────────────────────────────────────────────── -->
|
||
<section id="hero">
|
||
<div class="hero-copy">
|
||
<h1 class="hero-name">John <em>Gatward</em></h1>
|
||
<p class="hero-subtitle">Backend engineer. Curious builder.</p>
|
||
<p class="hero-desc">
|
||
I build services, interactive experiments, and things my family
|
||
actually uses.
|
||
</p>
|
||
<div class="hero-links">
|
||
<a href="#projects" class="btn btn-primary">View projects</a>
|
||
<a href="#contact" class="btn btn-ghost">Contact me</a>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ─── About ─────────────────────────────────────────────────── -->
|
||
<section id="about" class="about-section">
|
||
<div class="reveal">
|
||
<h2 class="section-heading">Havox & me</h2>
|
||
</div>
|
||
|
||
<div class="about-lead reveal">
|
||
<img
|
||
class="about-portrait"
|
||
src="images/headshot.jpeg"
|
||
alt="John Gatward"
|
||
width="800"
|
||
height="800"
|
||
loading="lazy"
|
||
decoding="async"
|
||
/>
|
||
<p class="about-intro">
|
||
Havox started in 2017 as a place to dump whatever projects I had
|
||
written. Four redesigns and several dead domains later, it's still
|
||
going. Less a portfolio, more a scrapbook.
|
||
</p>
|
||
</div>
|
||
|
||
<div class="about-columns">
|
||
<div class="about-details reveal" style="transition-delay: 0.05s">
|
||
<div class="about-block">
|
||
<h3>Day job</h3>
|
||
<p>
|
||
Backend engineer at <strong>Sainsbury's</strong> Supply Chain
|
||
& Logistics. It's good fun.
|
||
</p>
|
||
</div>
|
||
|
||
<div class="about-block">
|
||
<h3>Always learning</h3>
|
||
<p>
|
||
Fascinated with new languages, frameworks, and shiny tech I
|
||
probably don’t need. Constantly learning just enough to build
|
||
something slightly cooler next time.
|
||
</p>
|
||
</div>
|
||
|
||
<div class="about-block">
|
||
<h3>Off the clock</h3>
|
||
<p>
|
||
Long-time Linux user and distro-hopper. Self-hosted server
|
||
running 24/7 for friends and family who didn't ask for it but
|
||
<s>probably</s> definitely appreciate it.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Version timeline -->
|
||
<div class="reveal" style="transition-delay: 0.15s">
|
||
<h3 class="about-subheading">Version history</h3>
|
||
<div class="version-timeline">
|
||
<div class="version-item">
|
||
<div class="v-dot v-dot--current"></div>
|
||
<div class="v-content">
|
||
<div class="v-title">
|
||
Havox V4 <span class="v-current-badge">current</span>
|
||
</div>
|
||
<div class="v-year">2026 → present</div>
|
||
<div class="v-desc">
|
||
Catppuccin Mocha. Single page. Professional.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<a
|
||
class="version-item version-item--link"
|
||
href="archive/v3/index.html"
|
||
>
|
||
<div class="v-dot"></div>
|
||
<div class="v-content">
|
||
<div class="v-title">
|
||
Havox V3 <span class="v-link-arrow">↗</span>
|
||
</div>
|
||
<div class="v-year">2022 → 2025</div>
|
||
<div class="v-desc">
|
||
Borrowed a professional template and tried to make it suit
|
||
my needs. Wasn't very 'me'.
|
||
</div>
|
||
</div>
|
||
</a>
|
||
|
||
<a
|
||
class="version-item version-item--link"
|
||
href="archive/v2/index.html"
|
||
>
|
||
<div class="v-dot"></div>
|
||
<div class="v-content">
|
||
<div class="v-title">
|
||
Umbra.cyou <span class="v-link-arrow">↗</span>
|
||
</div>
|
||
<div class="v-year">2019 → 2022</div>
|
||
<div class="v-desc">
|
||
Built from the ground up focusing on a minimal clean design.
|
||
Stole my code VS Code theme for a colour palette.
|
||
</div>
|
||
</div>
|
||
</a>
|
||
|
||
<a
|
||
class="version-item version-item--link"
|
||
href="archive/v1/index.html"
|
||
>
|
||
<div class="v-dot"></div>
|
||
<div class="v-content">
|
||
<div class="v-title">
|
||
Havox.org <span class="v-link-arrow">↗</span>
|
||
</div>
|
||
<div class="v-year">2016 → 2019</div>
|
||
<div class="v-desc">
|
||
Wrote the entire site in one php file. Hosted on a £1/year
|
||
VPS.
|
||
</div>
|
||
</div>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ─── Skills ─────────────────────────────────────────────────── -->
|
||
<section id="skills">
|
||
<h2 class="section-heading reveal" style="transition-delay: 0.05s">
|
||
What I know
|
||
</h2>
|
||
|
||
<div class="skills-grid">
|
||
<div class="skill-card reveal">
|
||
<span class="skill-card-icon">
|
||
<img
|
||
src="icons/java-icon.svg"
|
||
alt="Java"
|
||
class="skill-card-icon-image"
|
||
/>
|
||
</span>
|
||
<h3>Backend</h3>
|
||
<p>
|
||
Professional experience designing, building and deploying
|
||
services. Using a modern tech stack in the Supply Chain &
|
||
Logistics industry.
|
||
</p>
|
||
<div class="tag-row">
|
||
<span class="tag tag-blue">Java</span>
|
||
<span class="tag tag-green">Spring Boot</span>
|
||
<span class="tag tag-teal">AWS</span>
|
||
<span class="tag tag-peach">Kafka</span>
|
||
<span class="tag tag-sky">MongoDB</span>
|
||
</div>
|
||
</div>
|
||
<div class="skill-card reveal" style="transition-delay: 0.08s">
|
||
<span class="skill-card-icon">
|
||
<img
|
||
src="icons/react-logo.svg"
|
||
alt="React"
|
||
class="skill-card-icon-image"
|
||
/>
|
||
</span>
|
||
<h3>Frontend & Creative</h3>
|
||
<p>
|
||
Comfortable with React and CSS. I've always enjoyed visualising
|
||
algorithms interactively - it's way more fun than a console
|
||
output.
|
||
</p>
|
||
<div class="tag-row">
|
||
<span class="tag tag-teal">React</span>
|
||
<span class="tag tag-green">TypeScript</span>
|
||
<span class="tag tag-blue">HTML/CSS</span>
|
||
</div>
|
||
</div>
|
||
<div class="skill-card reveal" style="transition-delay: 0.16s">
|
||
<span class="skill-card-icon">
|
||
<img
|
||
src="icons/docker-logo.svg"
|
||
alt="Docker"
|
||
class="skill-card-icon-image"
|
||
/>
|
||
</span>
|
||
<h3>Systems & Infra</h3>
|
||
<p>
|
||
Long-term Linux & Vim user. Self-hosted web & media servers. Using
|
||
industry practices when it comes to networks & security.
|
||
</p>
|
||
<div class="tag-row">
|
||
<span class="tag tag-green">Linux</span>
|
||
<span class="tag tag-teal">Docker</span>
|
||
<span class="tag tag-blue">Self-Hosting</span>
|
||
<span class="tag tag-peach">Wireguard</span>
|
||
</div>
|
||
</div>
|
||
<div class="skill-card reveal" style="transition-delay: 0.24s">
|
||
<span class="skill-card-icon">
|
||
<img
|
||
src="icons/haskell-logo.svg"
|
||
alt="Haskell"
|
||
class="skill-card-icon-image"
|
||
/>
|
||
</span>
|
||
<h3>Academic Breadth</h3>
|
||
<p>
|
||
C, C++, x86_64 assembly, Haskell, R & MatLab from uni. Modules
|
||
in Advanced networking, algorithms, compilers, graphics,
|
||
cryptography, malware analysis & many more.
|
||
</p>
|
||
<div class="tag-row">
|
||
<span class="tag tag-blue">C / C++</span>
|
||
<span class="tag tag-mauve">Haskell</span>
|
||
<span class="tag tag-yellow">Algorithms</span>
|
||
<span class="tag tag-teal">Security</span>
|
||
<span class="tag tag-peach">Low Level OS</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ─── Projects ──────────────────────────────────────────────── -->
|
||
<section id="projects">
|
||
<h2 class="section-heading reveal" style="transition-delay: 0.05s">
|
||
Things I built
|
||
</h2>
|
||
<p class="section-intro reveal" style="transition-delay: 0.1s">
|
||
A timeline of my projects and an overview of my journey as a
|
||
developer. Often inspired by something cool I saw and set out to
|
||
recreate.
|
||
</p>
|
||
|
||
<h3 class="projects-subheading reveal" style="transition-delay: 0.12s">
|
||
Featured projects
|
||
</h3>
|
||
|
||
<div
|
||
class="card-grid card-grid--featured reveal"
|
||
style="transition-delay: 0.14s"
|
||
>
|
||
<article class="card featured-card">
|
||
<img
|
||
class="project-preview"
|
||
src="images/wordle-solver-preview.webp"
|
||
alt="Wordle Solver showing a colour-coded guess and suggested next words"
|
||
width="1200"
|
||
height="800"
|
||
loading="lazy"
|
||
decoding="async"
|
||
/>
|
||
<div class="featured-card-content">
|
||
<a class="card-title" href="https://wordlesolver.umbra.mom">
|
||
Wordle Solver
|
||
<span class="card-action">Open solver (external)</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>Built after one too many missed 3-guess games. Now it plays
|
||
marginally better than me. Uses information theory to recommend
|
||
the next best guess.</span
|
||
>
|
||
<div class="project-meta">
|
||
<span class="card-date">9 Feb 2025</span>
|
||
<span class="project-status project-status--active"
|
||
>Active development</span
|
||
>
|
||
</div>
|
||
<span class="tag-row">
|
||
<span class="tag tag-yellow">Rust</span>
|
||
<span class="tag tag-teal">React</span>
|
||
<span class="tag tag-peach">TypeScript</span>
|
||
</span>
|
||
<span class="card-source">
|
||
Source code:
|
||
<a
|
||
href="https://github.com/jayo60013/wordle-solver-api"
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
>API</a
|
||
>
|
||
·
|
||
<a
|
||
href="https://github.com/jayo60013/wordle-solver-frontend"
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
>Frontend</a
|
||
>
|
||
</span>
|
||
</div>
|
||
</article>
|
||
<article class="card featured-card">
|
||
<img
|
||
class="project-preview"
|
||
src="images/crack-the-quote-preview.webp"
|
||
alt="Crack the Quote showing the daily cipher puzzle and letter controls"
|
||
width="1200"
|
||
height="800"
|
||
loading="lazy"
|
||
decoding="async"
|
||
/>
|
||
<div class="featured-card-content">
|
||
<a class="card-title" href="https://crackthequote.umbra.mom">
|
||
Crack the Quote
|
||
<span class="card-action">Play game (external)</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>A substitution-cipher puzzle game with a daily challenge. Built
|
||
for me and my family to play after getting bored with NYT
|
||
games.</span
|
||
>
|
||
<div class="project-meta">
|
||
<span class="card-date">13 Apr 2024</span>
|
||
<span class="project-status project-status--active"
|
||
>Active development</span
|
||
>
|
||
</div>
|
||
<span class="tag-row">
|
||
<span class="tag tag-yellow">Rust</span>
|
||
<span class="tag tag-teal">React</span>
|
||
<span class="tag tag-green">JavaScript</span>
|
||
</span>
|
||
<span class="card-source">
|
||
Source code:
|
||
<a
|
||
href="https://github.com/jayo60013/crack-the-quote-api"
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
>API</a
|
||
>
|
||
</span>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
|
||
<h3 class="projects-subheading reveal" style="transition-delay: 0.16s">
|
||
All projects
|
||
</h3>
|
||
|
||
<fieldset
|
||
class="project-filters reveal"
|
||
style="transition-delay: 0.18s"
|
||
aria-label="Filter projects by tech stack"
|
||
hidden
|
||
>
|
||
<button
|
||
type="button"
|
||
class="filter-chip active"
|
||
data-filter="all"
|
||
aria-pressed="true"
|
||
>
|
||
All
|
||
</button>
|
||
<button
|
||
type="button"
|
||
class="filter-chip"
|
||
data-filter="javascript"
|
||
aria-pressed="false"
|
||
>
|
||
JavaScript
|
||
</button>
|
||
<button
|
||
type="button"
|
||
class="filter-chip"
|
||
data-filter="python"
|
||
aria-pressed="false"
|
||
>
|
||
Python
|
||
</button>
|
||
<button
|
||
type="button"
|
||
class="filter-chip"
|
||
data-filter="rust"
|
||
aria-pressed="false"
|
||
>
|
||
Rust
|
||
</button>
|
||
<button
|
||
type="button"
|
||
class="filter-chip"
|
||
data-filter="react"
|
||
aria-pressed="false"
|
||
>
|
||
React
|
||
</button>
|
||
<button
|
||
type="button"
|
||
class="filter-chip"
|
||
data-filter="webassembly"
|
||
aria-pressed="false"
|
||
>
|
||
WebAssembly
|
||
</button>
|
||
<button
|
||
type="button"
|
||
class="filter-chip"
|
||
data-filter="p5"
|
||
aria-pressed="false"
|
||
>
|
||
p5.js
|
||
</button>
|
||
<button
|
||
type="button"
|
||
class="filter-chip"
|
||
data-filter="zig"
|
||
aria-pressed="false"
|
||
>
|
||
Zig
|
||
</button>
|
||
<button
|
||
type="button"
|
||
class="filter-chip"
|
||
data-filter="cpp"
|
||
aria-pressed="false"
|
||
>
|
||
C / C++
|
||
</button>
|
||
</fieldset>
|
||
<p
|
||
id="project-count"
|
||
class="project-count"
|
||
role="status"
|
||
aria-atomic="true"
|
||
hidden
|
||
></p>
|
||
<div id="projects-empty" class="projects-empty" hidden>
|
||
<h3>No projects match this filter</h3>
|
||
<p>Choose another technology or browse all projects.</p>
|
||
<button id="projects-reset" class="btn btn-ghost" type="button">
|
||
Show all projects
|
||
</button>
|
||
</div>
|
||
|
||
<div
|
||
id="project-grid"
|
||
class="card-grid reveal"
|
||
style="transition-delay: 0.2s"
|
||
>
|
||
<article class="card project-card" data-tech="python">
|
||
<span class="card-date">03 Apr 2025</span>
|
||
<a class="card-title" href="https://pubquiz.umbra.mom">
|
||
Pub Quiz Dashboard
|
||
<span class="card-action">Open dashboard (external)</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>A Python dashboard to track our local pub quiz
|
||
performances.</span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-red">Python</span>
|
||
</span>
|
||
</article>
|
||
<article class="card project-card" data-tech="cpp webassembly">
|
||
<span class="card-date">14 Nov 2024</span>
|
||
<a class="card-title" href="projects/thin_ice/thin_ice.html">
|
||
Thin Ice
|
||
<span class="card-action">Play game</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>A small browser tile game inspired by one I played growing
|
||
up.</span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-blue">C++</span>
|
||
<span class="tag tag-teal">WebAssembly</span>
|
||
<span class="tag tag-peach">Raylib</span>
|
||
</span>
|
||
</article>
|
||
<article class="card project-card" data-tech="zig webassembly">
|
||
<span class="card-date">20 Mar 2024</span>
|
||
<a class="card-title" href="projects/tsp/index.html">
|
||
Travelling Salesman Problem
|
||
<span class="card-action">Open visualiser</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>A nearest-neighbor + 2-opt visualiser. Wanted to revisit one of
|
||
my first projects with an optimised tech stack and
|
||
algorithm.</span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-yellow">Zig</span>
|
||
<span class="tag tag-sky">WebGL</span>
|
||
<span class="tag tag-teal">WebAssembly</span>
|
||
</span>
|
||
</article>
|
||
<article class="card project-card" data-tech="rust">
|
||
<span class="card-date">31 Jan 2024</span>
|
||
<a class="card-title" href="projects/flocking/index.html">
|
||
Flocking
|
||
<span class="card-action">Open visualiser</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>Rewrote the project from Go to Rust, compiling it to WebAssembly.
|
||
Was fun being able to use DOM controls to affect the
|
||
simulation.</span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-yellow">Rust</span>
|
||
<span class="tag tag-peach">Raylib</span>
|
||
</span>
|
||
</article>
|
||
<article class="card project-card" data-tech="javascript">
|
||
<span class="card-date">1 Nov 2023</span>
|
||
<span class="project-status project-status--active"
|
||
>Active development</span
|
||
>
|
||
<a class="card-title" href="https://samstoreymusic.com">
|
||
samstoreymusic.com
|
||
<span class="card-action">Visit website (external)</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>A website design and build for a friend working in music. Saving
|
||
him the hosting fees :)</span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-mauve">HTML/CSS</span>
|
||
<span class="tag tag-green">JavaScript</span>
|
||
</span>
|
||
</article>
|
||
<article class="card project-card" data-tech="javascript react">
|
||
<span class="card-date">21 Jul 2023</span>
|
||
<a class="card-title" href="projects/cellular_automata/index.html">
|
||
Game of Life
|
||
<span class="card-action">Open simulator</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>After building Conway's Game of Life in p5.js as one of my first
|
||
projects, I expanded it into a generic automata simulator.</span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-teal">React</span>
|
||
<span class="tag tag-green">JavaScript</span>
|
||
</span>
|
||
</article>
|
||
<article class="card project-card" data-tech="cpp webassembly">
|
||
<span class="card-date">5 Feb 2022</span>
|
||
<a class="card-title" href="projects/percolation/index.html">
|
||
Percolation
|
||
<span class="card-action">Open visualiser</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>Watched a brilliant video by
|
||
<a
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
href="https://youtu.be/a-767WnbaCQ?si=f3NM95INeoZqzIi8"
|
||
>Spectral Collective</a
|
||
>
|
||
and just had to recreate it.</span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-blue">C</span>
|
||
<span class="tag tag-peach">Raylib</span>
|
||
<span class="tag tag-teal">WebAssembly</span>
|
||
</span>
|
||
</article>
|
||
<article class="card project-card" data-tech="javascript p5">
|
||
<span class="card-date">1 Oct 2021</span>
|
||
<a class="card-title" href="projects/cubic_bezier_curve/index.html">
|
||
Drawing Bézier curves
|
||
<span class="card-action">Open visualiser</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>An interactive animation for how cubic Bézier curves are
|
||
constructed. Inspired by this beautiful video by
|
||
<a
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
href="https://youtu.be/aVwxzDHniEw?si=mCylw_p-fMSdhyvN"
|
||
>Fraya Holmér</a
|
||
></span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-green">JavaScript</span>
|
||
<span class="tag tag-red">p5.js</span>
|
||
</span>
|
||
</article>
|
||
<article class="card project-card" data-tech="javascript p5">
|
||
<span class="card-date">17 Sep 2021</span>
|
||
<a class="card-title" href="projects/marching_squares.html">
|
||
2D Marching Squares
|
||
<span class="card-action">Open generator</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>I saw the 3D version of this algorithm in a game dev log and was
|
||
inspired to create this 2D land-and-sea map generator.</span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-green">JavaScript</span>
|
||
<span class="tag tag-red">p5.js</span>
|
||
</span>
|
||
</article>
|
||
<article class="card project-card" data-tech="javascript p5">
|
||
<span class="card-date">2 Apr 2020</span>
|
||
<a class="card-title" href="projects/warping_lines.html">
|
||
Müller-Lyer illusion
|
||
<span class="card-action">Open visualiser</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>JavaScript visualisation of the Müller-Lyer optical
|
||
illusion.</span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-green">JavaScript</span>
|
||
<span class="tag tag-red">p5.js</span>
|
||
</span>
|
||
</article>
|
||
<article class="card project-card" data-tech="javascript p5">
|
||
<span class="card-date">27 Feb 2019</span>
|
||
<a class="card-title" href="projects/fourier_series.html">
|
||
Fourier series
|
||
<span class="card-action">Open visualiser</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>Builds a square wave from sine components to show Fourier series
|
||
in motion.</span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-green">JavaScript</span>
|
||
<span class="tag tag-red">p5.js</span>
|
||
</span>
|
||
</article>
|
||
<article class="card project-card" data-tech="javascript p5">
|
||
<span class="card-date">23 Feb 2019</span>
|
||
<a class="card-title" href="projects/ellipse_construction.html">
|
||
Constructing an ellipse
|
||
<span class="card-action">Open visualiser</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>A geometric construction demo inspired by
|
||
<a
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
href="https://youtu.be/xdIjYBtnvZU?si=uI66LS_O_eAWqG4e"
|
||
>3Blue1Brown's video</a
|
||
>
|
||
on Feynman's lost lecture.</span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-green">JavaScript</span>
|
||
<span class="tag tag-red">p5.js</span>
|
||
</span>
|
||
</article>
|
||
<article class="card project-card" data-tech="javascript p5">
|
||
<span class="card-date">18 Mar 2018</span>
|
||
<a class="card-title" href="projects/pi_approximation.html">
|
||
Calculating Pi
|
||
<span class="card-action">Open visualiser</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>A Monte Carlo approximation of pi using random sampling.</span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-green">JavaScript</span>
|
||
<span class="tag tag-red">p5.js</span>
|
||
</span>
|
||
</article>
|
||
<article class="card project-card" data-tech="javascript p5">
|
||
<span class="card-date">17 Dec 2017</span>
|
||
<a class="card-title" href="projects/oscillations_in_3d.html">
|
||
Oscillations in 3D
|
||
<span class="card-action">Open visualiser</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>A JavaScript recreation of a Bees and Bombs animation.</span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-green">JavaScript</span>
|
||
<span class="tag tag-red">p5.js</span>
|
||
</span>
|
||
</article>
|
||
<article class="card project-card" data-tech="javascript p5">
|
||
<span class="card-date">13 Nov 2017</span>
|
||
<a class="card-title" href="projects/maze_generation/index.html">
|
||
Maze generator
|
||
<span class="card-action">Open generator</span>
|
||
</a>
|
||
<span class="card-desc"
|
||
>Discovered the
|
||
<a
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
href="https://youtu.be/HyK_Q5rrcr4?si=G6g8xDHK0cc_MwhG"
|
||
>Coding Train's channel</a
|
||
>
|
||
and learnt coding through following along.</span
|
||
>
|
||
<span class="tag-row">
|
||
<span class="tag tag-green">JavaScript</span>
|
||
<span class="tag tag-red">p5.js</span>
|
||
</span>
|
||
</article>
|
||
</div>
|
||
|
||
<div class="projects-more-row reveal" style="transition-delay: 0.22s">
|
||
<button
|
||
id="projects-see-more"
|
||
type="button"
|
||
class="projects-more-btn"
|
||
aria-expanded="false"
|
||
aria-controls="project-grid"
|
||
hidden
|
||
>
|
||
Show more projects
|
||
</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ─── Contact ───────────────────────────────────────────────── -->
|
||
<section id="contact">
|
||
<div class="contact-inner reveal" style="transition-delay: 0.1s">
|
||
<div>
|
||
<h2>Let's talk</h2>
|
||
<p>
|
||
I am currently employed and open to the right software engineering
|
||
opportunity, particularly backend or full-stack roles with
|
||
friendly, close-knit teams.
|
||
</p>
|
||
<p>For professional enquiries, connect with me on LinkedIn.</p>
|
||
</div>
|
||
<div class="contact-links">
|
||
<a
|
||
href="https://www.linkedin.com/in/jaygatward"
|
||
class="btn btn-primary contact-link"
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
>
|
||
<span
|
||
class="contact-link-icon contact-link-icon--linkedin"
|
||
aria-hidden="true"
|
||
></span>
|
||
<span>Connect on LinkedIn</span>
|
||
</a>
|
||
<a
|
||
href="https://github.com/jayo60013"
|
||
class="contact-link contact-link--secondary"
|
||
aria-label="Explore my code on GitHub"
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
>
|
||
<span
|
||
class="contact-link-icon contact-link-icon--github"
|
||
aria-hidden="true"
|
||
></span>
|
||
<span>Explore my code</span>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<!-- ─── Footer ─────────────────────────────────────────────────── -->
|
||
<footer>
|
||
<span>umbra.mom - John Gatward</span>
|
||
<span>
|
||
Source code (self‑hosted):
|
||
<a
|
||
href="https://gitea.umbra.mom/jay/havox"
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
>repository</a
|
||
>
|
||
</span>
|
||
</footer>
|
||
|
||
<script src="script.js"></script>
|
||
</body>
|
||
</html>
|