I turn product ideas into interfaces that are fast, accessible, and used in production

Seven years shipping production-ready software

Previously

  • Rabobank
  • University of Edinburgh
  • Merck & Co
  • FedEx

Case studies

NgRx Signal Store migration

Architecture · Rabobank · 2025

Moved limits and fraud off a bloated Redux setup onto Signal Store, across 11 modules, without taking live payments down.

The problem

The limits and fraud domain sat on a heavy Angular/Redux setup across 11 modules. Lots of boilerplate, and it was slow to change a flow that has to stay up.

What I did

  • I led the migration to NgRx Signal Store. We split it into smaller stores, one per journey.
  • Every release went out behind a feature flag after UAT.
  • Wrote a test helper that logged each state, so we could see what the store was doing from the console.

Outcome

  • 11 modules on Signal Store, live payments still running.
  • Cleaner, more modular stores, and we could actually track state while we tested.

Stack

Angular, NgRx Signal Store

Vizvest

Personal project · Next.js · 2026

A privacy-first portfolio analytics app for self-directed investors. Live, with real users.

The problem

Trading 212 and similar apps show you what you own, not what it means. Dividend growth, trade patterns, compound performance, and a journal are buried or missing. Active retail investors are flying blind.

What I did

  • I built a privacy-first portfolio analytics app in Next.js.
  • In-depth trade history analysis.
  • Dividend compounding visualisation.
  • A trading journal with gamification mechanics.

Outcome

  • Live with real users.
  • People are arriving from LLM search. I track that in PostHog, including funnels and drop-off.

Stack

Next.js, TypeScript, privacy-first

GA to Piano

Analytics · Rabobank · 2024

Moved us off Google Analytics onto Piano for GDPR, then trained teams to use it.

The problem

We needed GDPR-compliant analytics. GA wasn't going to cut it.

What I did

  • I did the Piano training, then ran workshops.
  • Helped 10+ teams build dashboards, funnels, and reports.

Outcome

  • 10+ teams on Piano.
  • The bank has a GDPR-compliant analytics setup people can actually use.

Stack

Google Analytics, Piano Analytics

Accessibility uplift, 3 apps

Accessibility · Rabobank · 2023

WCAG 2.1 across three payment apps, with a11y in the definition of done and e2e tests for focus and ARIA.

The problem

Three payment apps hadn't been built for assistive tech. Keyboard and screen reader users were stuck.

What I did

  • Overhaul across all three: VoiceOver testing, full keyboard nav, WCAG 2.1.
  • Put a11y in the definition of done, wrote testing standards, and added e2e tests for focus and ARIA labels.
  • Apps made compliant with the European Accessibility Act (EAA).

Outcome

  • All three apps at WCAG 2.1.
  • A11y is part of how the team ships, not a one-off audit.

Stack

WCAG 2.1, VoiceOver, keyboard

Payment request flow

Product engineering · Rabobank · 2025

Replaced a long, silent form with a step-by-step dialogue. About 250k requests a day.

The problem

The old payment request flow was a long form with no feedback until you submitted.

What I did

  • I was one of three. We turned it into a step-by-step dialogue.
  • Each step checks amount, recipient, and reference before you continue. You catch the mistake there, not in a pile at the end.

Outcome

  • Shipped on about 250k requests a day.
  • Available to 7 million customers.

Stack

Angular, Customer journeys

Hiring process redesign

Leadership · Rabobank · 2023

Rebuilt technical hiring for frontend and full-stack across a 300+ person department. Still the standard test.

The problem

A 300+ person engineering department had no shared bar for frontend and full-stack candidates. Hiring was inconsistent.

What I did

  • I rebuilt the technical hiring process for frontend and full-stack.
  • Structured assessments, rubrics, skills by level, and interviewers on the same process.

Outcome

  • Still the standard technical test.

Stack

Rubrics, structured assessment

about

Creative builder at heart

Zagreb
London
San Francisco
New York
Dubai
Tokyo
Sydney
São Paulo
45.81° N · 15.98° EZagreb · GMT+1
Based in Europe · Working Worldwide

Skills

top of the stack · 2026
languages
TypeScriptJavaScriptJavaPythonSQLHTMLCSS
frameworks
ReactNext.jsAngularReduxSpringBootTailwind CSS
quality
JestPlaywrightWebdriverIOSpectator
observability
SplunkDynatraceSignalFXPostHogDevTools
tooling
GitNxAzure DevOpsFigma
agentic
Claude CodeCursorCodexSubagent Driven Development
7+
Years building for the web
favorite tools

Fast loops, finished work

Status: Pair-programming with Claude and Codex, day in, day out

off the clock

Growing up around the world gave me a global perspective I'm genuinely proud of. It helps me connect with people from different backgrounds. When I'm not working, I'm out on a run, exploring a new place, or lost in music - which I love enough that I recently got into DJing.

things I made

Problems? I got solutions

Listicle pipeline: 1 image creates shopify listicles

The automated reply guy X strategy

Know exactly where your money goes

Creative pipeline for brands

In depth claude usage analysis

skills, in motion

What I reach for

Small animations of the ideas that show up in almost every project.

See all 12 skills
type Payment = {  amount: number,  currency: 'USD' | 'EUR',  status: 'paid' | 'open' | 'void'}pay(1499, 'USD')
Engineering · TypeScript
Type-safe APIs
Contracts shared from server to client. Errors caught before the request leaves the editor.
TypeScriptZod
SET_USER
ADD_ITEM
store
usercartprefs
<Avatar />
<Total />
<Theme />
Engineering · State
State at scale
A single store, many subscribers. Actions in; only the right selectors light up.
ReduxSignalsNgRx
Tab ⇥
aria-label="Continue"  role="button"
Product · UX
Accessibility & focus
Tab order, ARIA, contrast. Keyboard-first means everyone-first.
WCAGARIAkeyboard
development concepts

Patterns I keep using

Short loops of the ones that show up in the work.

See all 15 concepts
client
LB
svr-0
svr-1
svr-2
svr-3
Back-end · Infra
Load balancer
Spreads requests across healthy servers; reroutes around a failure.
stream
1
2
3
4
.map(×2)
2
4
6
8
.filter(>4)
×
×
6
8
sub
6
8
Front-end · Reactive
Observable streams
Values flow through map / filter operators - describe what should happen, not when.
polling
repeat requests - most return nothing
req
res
websocket
one connection - server pushes when ready
conn
push
Back-end · Sync
Polling vs WebSockets
Polling asks ‘anything yet?’ on a loop. A socket stays open and pushes when ready.