A desktop app for creating live visuals that respond to music and performance controls.
- Electron
- TypeScript
- React
- Vite
- WebAssembly
- Sentry
- Ableton Link
- Syphon
- Role
- Product direction, interaction & system design, engineering
- Built with
- Electron · TypeScript · React · Vite · WebAssembly · Sentry · Ableton Link · Syphon
One abstraction, everywhere
Every parameter is a normalized value on a shared bus, so any signal can drive any target.
Routing you can see
Drag a modulator onto a parameter and a coloured cable appears — abstract signal made physical.
A clean render seam
Data one way to the GPU, control the other to the UI, so the interface never stalls mid-set.
Thirteen sculpted worlds, escalating physics systems, and one ball that cannot fall.
- Three.js
- WebGL
- JavaScript
- Netlify
- GLSL
- cannon-es
- Role
- Game design, level design, engineering
- Built with
- Three.js · WebGL · JavaScript · Netlify · GLSL · cannon-es
One rule, read instantly
Remove blocks, keep the ball up. Legible in a second, so difficulty can live in the materials.
Materials make the puzzle
Wood, stone, ice, metal, lava — each shifts the balance, so levels teach without hiding the rules.
A topple must feel earned
Mass, friction and the settling check are tuned so a fall reads as fair, never as the engine cheating.
A concept website for a fictional fragrance house, built around imagery and an interactive collection.
- Next.js
- React
- TypeScript
- CSS
- Netlify
- Role
- Brand direction, UX, interaction design, front-end
- Built with
- Next.js · React · TypeScript · CSS · Netlify
Desire before detail
Every route opens on atmosphere, then the formula. Six signatures, not six SKUs.
One product carries the proof
Noir 04 holds the full story — notes, maceration, price, waitlist — without breaking the mood.
A palette with weight
Bone, oxblood, antique gold. The material does the luxury signalling, so the type stays quiet.
An experiment that uses hand movement to control visuals and sound in the browser.
- JavaScript
- HTML5
- CSS
- Netlify
- MediaPipe
- Canvas 2D
- Role
- Product direction, interaction & gesture design, front-end
- Built with
- JavaScript · HTML5 · CSS · Netlify · MediaPipe · Canvas 2D
Privacy before permission
Tracking runs on device and one toggle releases the camera — the trust model is stated before play.
A small gesture vocabulary
Pinch, tilt and height recur across all four modes, normalized by hand size so depth never breaks them.
A path without the camera
Chords plays fully from the keyboard, so the most musical mode survives when a camera isn't wanted.
Adaptive taste and synchronized rooms turn group indecision into one shared pick.
- React
- TypeScript
- Vite
- Firebase
- Motion
- Netlify
- Role
- Product strategy, interaction & visual design, full-stack
- Built with
- React · TypeScript · Vite · Firebase · Motion · Netlify
Shared set, personal order
A room seed fixes the candidate pool; a per-person seed shuffles it — overlap without a copied deck.
Taste nudges, never filters
Swipes reorder titles at a capped 35% influence, so the common ground a group needs stays intact.
Two databases, two jobs
Firestore holds durable room state; Realtime Database handles presence for its disconnect behaviour.
A marketing site where visitors try shaders, modulation, and routing instead of reading claims.
- HTML5
- CSS
- JavaScript
- Netlify
- Role
- Positioning, IA, storytelling, interaction design, front-end
- Built with
- HTML5 · CSS · JavaScript · Netlify
One promise, not a list
Making visuals should feel like making music — a feature list reads as complicated, not capable.
Complexity in order
Parameters, routing, LFOs, then triggers and chains — one idea per demo, disclosed in sequence.
Canvases earn their cost
The GPU demos live on their own route; supporting sections use stills so the site isn't a benchmark.
Modern listening tastes become personal classical recommendations—with reasons why.
- React
- JavaScript
- Node.js
- Express
- PostgreSQL
- Gemini
- Role
- Product strategy, UX and visual design, front-end, APIs
- Built with
- React · JavaScript · Sass · Node.js · Express · PostgreSQL · Drizzle · Gemini · Netlify
Start at a familiar name
Search takes artists, not eras or catalogue numbers, so no classical vocabulary is needed to begin.
Never an empty result
Groq, Gemini, OpenAI, then a written catalogue — a provider outage can't break the explanation.
Search at thinking speed
120 ms debounce, cached queries, aborted stragglers — results hold on screen instead of flashing.
A scroll-choreographed tasting experience built around rotating cans and ingredients.
- Three.js
- WebGL
- JavaScript
- Vite
- Blender
- Netlify
- Role
- Art direction, UX, creative development
- Built with
- Three.js · WebGL · JavaScript · Vite · Blender · Netlify
The can is the story
Each flavour leaves the shelf, rotates through its own label, then returns — product as narrator.
Motion that explains
Rotation exposes the can’s real information order, so the 3D earns its place instead of decorating.
Five moods, one house
Botanicals and colour give every drink its own field while the lineup stays unmistakably Dillon’s.
A deep photo and video archive paced into a cinematic portfolio and inquiry journey.
- React
- TypeScript
- Vite
- Netlify
- Role
- Art direction, UX, front-end development
- Built with
- React · TypeScript · Vite · Netlify
Imagery owns the colour
Near-black and warm cream hold the stage; each film and shoot supplies its own visual energy.
Five doors, one archive
Narrative, music video, commercial, fashion, social — separate routes keep a deep body of work navigable.
Cut, pause, reveal
Dense image runs alternate with quiet editorial bands so the work gets absorbed, not skimmed.
Greenhouse intelligence translated into a clear, explorable story about crop confidence.
- Role
- Interactive storytelling, design, front-end
- Built with
- JavaScript · HTML5 · CSS · SVG
Lead with the grower
Felix and Roberto's own words open each turn — trusting data is a human claim before a technical one.
Discovered, not asserted
The before/after coverage shift is an interaction, so readers find the 500x jump instead of being told.
One signal carries it
Head-to-truss height, scrubbed across weeks 28 to 31, turns a dense report into one readable line.
Campaigns, delivery, education, and coordination for a touring North American exhibit.
- Webflow
- Vimeo
- Lottie
- jQuery
- Role
- Tour logistics, stakeholder comms, campaign marketing
- Built with
- Webflow · Vimeo · Lottie · jQuery
One chain, not silos
Technical prep, venue logistics, staffing and programming ran as one chain per stop, not four.
Right detail, right room
Schools, donors, venues and volunteers each got their own level of detail — one message, many depths.
Public scale, same mission
Times Square on Yom HaShoah had to reach strangers at scale without leaving the education behind.
A quiet material-led studio experience with a slow, tactile helix of selected work.
- Role
- Strategy, art direction, UX, front-end development
- Built with
- HTML5 · CSS · JavaScript
Light is the accent
Plaster, concrete, charcoal. Daylight carries the colour so photography never fights the interface.
Patient over spectacular
The work index rises on a slow helix and drifts back. An architecture portfolio shouldn't perform.
Structure without boxes
Hairline rules and negative space order the page, so the work never becomes a grid of cards.
A poster-grade label world with a rising, draggable helix discography at its center.
- Next.js
- React
- TypeScript
- CSS
- Role
- Art direction, UX, front-end development
- Built with
- Next.js · React · TypeScript · CSS
Unify by atmosphere
The roster spans seven genres, so the night became the connective tissue — not the sound.
Colour has a job
Vermilion marks whatever is live or actionable; cobalt belongs to Blue Hour and nothing else.
Make the archive playable
Eight sleeves on a drag-and-flick helix. A catalogue you turn, not a record grid you scroll.
A reference-grade headphone world pairing restraint with a tactile 3D collection.
- Next.js
- React
- TypeScript
- CSS
- Role
- Brand direction, UX, interaction, front-end
- Built with
- Next.js · React · TypeScript · CSS
Sell trust first
No comparison tables, no promo colour. Obsidian, off-white and one champagne accent do the work.
Two paths, not one
A 3D cylinder for feeling the range, then a plain grid for scanning it. Both visitors get served.
Redundant control
Drag, prev/next and dot navigation all reach the same model, so the signature moment traps no one.