Everything I make lived in five different places, none of which I owned, and none of which talked to each other.
APPROACH
Design the language first in Figma, then build a static Astro shell against it, with a token layer strict enough that the design cannot drift silently. Five sync scripts pull the sources in and commit what they find, so no page waits on someone else's API to render.
RESULT
This site — 480-odd pages off five feeds, a dark ground and a light one, and a drift report that says when code and design have stopped agreeing.
ARCHITECTURE
Architecture of SHINIGAMAE. SOURCES: Blogger, Goodreads, PlayStation Network, Flickr, Spotify, connected to design by sync scripts, committed as JSON. DESIGN: Figma library, Design tokens, connected to build by drift report on every check. BUILD: Astro static build, zod content schemas, connected to edge by static HTML. EDGE: Azure Static Web Apps, GitHub Pages mirror, connected to api by edits and comments, over HTTPS. API: .NET API on App Service, PostgreSQL: overrides, audit log.
SOURCES
BloggerGoodreadsPlayStation NetworkFlickrSpotify
sync scripts, committed as JSON
DESIGN
Figma libraryDesign tokens
drift report on every check
BUILD
Astro static buildzod content schemas
static HTML
EDGE
Azure Static Web AppsGitHub Pages mirror
edits and comments, over HTTPS
API
.NET API on App ServicePostgreSQL: overrides, audit log
—Publishing styles in Figma matters more than any sync script
—A token layer is only real if nothing can bypass it — a second theme then costs one file
—A feed you sync and commit beats an API you call at read time
—Deciding the shell before the pages saved a rewrite
02
GUILD MANAGEMENT PLATFORM
JUN 2026 — NOWLIVE
Roster, match records and a Discord bot for a Where Winds Meet guild
ROLESolo: architecture, build and operations, for the guild
IMPACT
REPOSITORIES
3
COMMITS
~500
BOT COMMANDS
41
MEMBERS
~95
PROBLEM
A guild of about ninety players ran on a Google Sheet that published itself as encrypted files, with the decryption key shipped in the browser bundle, so the private roster was readable by anyone who looked. Events, match footage and player stats lived in three other places on top of that.
APPROACH
Three parts, and one of them owns the data. An Angular site on GitHub Pages and a Discord bot both talk to a .NET 10 Minimal API over Postgres. The bot answers Discord over HTTP instead of holding a gateway connection open. Azure Functions sync live player stats from the game's own gateway, but only write when something has changed. Permissions are checked at the API, never in the client, and every design choice answers to one bill: how many hours the database is awake.
RESULT
Three repositories and about 500 commits in fifteen weeks, all on free-tier hosting. The guild gets Discord sign-in with three nested roles, GvG match history with footage, self-run PvP tournaments, scouting across some 6,500 opponent players, and a Discord bot with 41 commands.
ARCHITECTURE
Architecture of GUILD MANAGEMENT PLATFORM. CLIENTS: Angular site on GitHub Pages, Discord bot, HTTP interactions, connected to api by HTTPS: app JWT from Discord sign-in, or a bot key. API: .NET 10 Minimal API, Role checks per request, connected to data by EF Core. DATA: PostgreSQL on Neon, scales to zero, Blob storage: change hashes, connected to sync by written only when something changed. SYNC: Azure Functions: timers and on-demand refresh, connected to sources by signed msgpack. SOURCES: Game gateway, Discord REST.
CLIENTS
Angular site on GitHub PagesDiscord bot, HTTP interactions
HTTPS: app JWT from Discord sign-in, or a bot key
API
.NET 10 Minimal APIRole checks per request
EF Core
DATA
PostgreSQL on Neon, scales to zeroBlob storage: change hashes
—A static site cannot keep a secret from its viewers. An encryption key in the bundle is a key handed out.
—On a serverless database the bill is hours awake, not queries run, so the cheapest sync is one that never wakes it.
—Enforce permissions where the data lives. A role in localStorage is a suggestion anyone can edit.
—A green deploy proves the deploy ran, not that anything works: a 200 means the function ran, not that data arrived.
—Archive a third-party source while it is still up. The community relay that held our match history stopped resolving overnight, and our archive was the last copy.
—Generate the reference from the code. The hand-written command list had gone wrong in three places at once.
Medication administration between pharmacies and nursing homes, started by four developers and three QAs. Eight years on the same system still ships monthly, from an offshore centre that grew to thirty-two.
The frontend of a multi-tenant platform run by banks, financial firms and the US Department of Defense. Four of us own the face of the product alongside teams in the US, UK and India, keeping production issues short-lived and the test coverage honest.
The Social module of an ecosystem that also carries e-commerce and booking, on Java microservices behind several Angular applications. As assistant architect I held the contracts between modules, the migration plan and the review standard while the team grew past two hundred. The product is no longer under active development.
A decade-old ecosystem running kiwifruit from orchard growers through packhouses to market distribution. Joined as the only engineer on it, learned the business the slow way, then built the team that kept it moving — two or three months on site each open season.
Team Lead
Software Engineer
.NET · SQL Server · MS Office Suite
ZESPRI.COM ↗
03
CAREER
START
SOFTWARE ENGINEER
Building production software and learning systems from the inside out.
→
TEAM LEAD / PROJECT LEAD
Leading developers, technical decisions, and delivery — and growing the team that does it.
→
TECHNICAL PROJECT MANAGER
Leading delivery while keeping enough technical depth to challenge assumptions and make informed decisions.
04
CAPABILITIES
PROJECT & DELIVERY
Technical project management
Agile & Kanban delivery
Planning & estimation
Stakeholder management
Risk management
Cross-functional coordination
ENGINEERING
Software development
Code review
System design
API design
Database design
Testing
DevOps
ARCHITECTURE
Cloud architecture
Application modernisation
Integration
Security
Scalability
Cost optimisation
TECHNOLOGY
.NET
Angular
Azure
SQL Server
Java
AWS
05
GET IN TOUCH
For a project, a team, or a second opinion on an architecture — LinkedIn is where I answer.