Software engineer at Notable Health Bay Area, California

AJUppal

I build across the stack: zero-to-one services, AI and voice systems, infrastructure, and, off the clock, worlds that run in a browser.

At Notable, a healthcare AI company, I work across the stack: integrations, voice AI, the conversation and API layers, frontend to database, and the occasional flight to a customer’s site to make it work in the room.

01 / Playground

3 running inline

Eleven years of this, and the oldest ones still run.

All three run here in the page, on their original code. Go ahead.

Runs

AutoTyperc. 2019

Types a block of text into a field, character by character, at a rate you choose.

Rendered by AutoTyper.tsx

Live output

Local offline port, zero dependenciesRead the original
Runs

deviation.htmlc. 2015

Give it a mean, a spread and a sample size for two distributions and it samples both and overlays the histograms. Homework that turned into a small tool and then stayed.

Rendered by DeviationFrame.tsx

legacy-deviation.webp

Not made by the image recipe. No crop is on record for it.

Two distributions
The deviation.html chart at this seed: two overlapping bell curves of a thousand samples each, a dark green one centred near -4 and a pale green one centred near 6, over a table holding the six numbers that made them.

Swipe sideways for the second distribution

The 2015 file itself, unmodified, seeded from its query stringOpen original

Original artifact Its own 2015 colours

Repaired

GrinchJumpc. 2015

Doodle Jump in three dimensions, built while I was learning three.js. Its keyboard library vanished along with a CDN, so the dependencies now live in the repo.

  • Steer
  • Tap Steer
  • P Pause
  • Esc Exit
  • R Restart

The jump is not a control: landing on a platform is what throws him.

Rendered by GameFrame.tsx

legacy-grinchjump.webp

Shipped from
1,200 × 710 · 5 kB
Capture
legacy-grinchjump-REVIVED.png · 2,560 × 1,514
File dated
2026-08-06
Cut away
Nothing. The frame is whole.
Playable
GrinchJump running in a browser: a low-poly figure on a stack of green platforms against a pale sky, score counter in the corner.
Vendored three.js r70, served from its original URLOpen original
Nothing left to run

Rendezvousc. 2020

A central place for UMass students to find each other through the classes they were taking. Everyone’s assignments in one calendar, a chat per lecture, and, that year, a Zoom link where the room number used to be.

React · Redux · Flask · PostgreSQL · GCP

The Rendezvous dashboard in its dark theme: four courses listed down a sidebar, a month of colour-coded assignment bars across a calendar, and a right-hand column of the day’s lectures, each with a Zoom button.
The dashboard. Term’s classes down the left, every assignment in one calendar, the day’s lectures on the right.
The same dashboard in its light theme, week view: five courses in the sidebar, a week of assignment bars, and two lectures on the right with their times. Light
The identical view in the dark theme, the same courses and the same two lectures, changed only in colour. Dark
The same screen at the same second, one toggle apart. Thursday 14 October 2021, 5:16 in the afternoon, both times.
The Physics 568 course page in its light theme: two problem sets with released and due dates in a table, and a docked Official Lecture Chat panel on the right carrying five messages between two students. Light
The identical course page and the identical chat in the dark theme, the same two problem sets and the same five messages, changed only in colour. Dark
One course, with its lecture chat open: the room the class talked in, the two problem sets due out of it, and the seed message every new room opens with. Same screen, one toggle apart, again.

Rendered by astro:assets Picture

rendezvous-dashboard.webp

Shipped from
2,400 × 1,495 · 132 kB
Capture
rz-rendezvous-main.png · 2,920 × 1,840
File dated
2026-08-09
Cut away
28 left · 28 top · 28 right · 28 bottom
Which held
the speckled decorative border the capture was framed in

rendezvous-day.webp

Shipped from
1,400 × 879 · 64 kB
Capture
rz-rendezvous1light.png · 2,744 × 1,722
File dated
2026-08-09
Cut away
Nothing. The frame is whole.

rendezvous-night.webp

Shipped from
1,400 × 875 · 65 kB
Capture
rz-rendezvous1dark.png · 2,738 × 1,712
File dated
2026-08-09
Cut away
Nothing. The frame is whole.

rendezvous-chat-day.webp

Shipped from
1,400 × 877 · 57 kB
Capture
rz-rendezvous2light.png · 2,736 × 1,714
File dated
2026-08-09
Cut away
Nothing. The frame is whole.

rendezvous-chat-night.webp

Shipped from
1,400 × 876 · 61 kB
Capture
rz-rendezvous2dark.png · 2,738 × 1,714
File dated
2026-08-09
Cut away
Nothing. The frame is whole.

Also built

  • High school

    PICKLE

    Designed, built and calibrated low-cost air pollution monitors to make the problem visible. Hardware, firmware, cloud and data science in one project, with Sonoma Technology, BAAQMD and Manylabs.

    C · Python · R · Time-series storage

02 / Experience

Eight roles, one through-line

Physics research, university software, first-engineer jobs, and production healthcare AI. Most of my work has been building first versions of new systems.

8 roles, all shown

Rendered by StackFilter.tsx

  1. Summer 2017

    Bay Area Air Quality Management District

    Air Quality Scientist and Data Analytics Intern · C · Python · Cloud data pipeline

    Built, tested and calibrated low-cost air pollution monitors, and built the cloud networking interface for viewing their data from anywhere. Secured a $3,000 grant for Los Altos High School to bring monitor building into its APES curriculum.

  2. Summer 2018

    YouWeb, Inc.

    Software Engineering Intern · JavaScript · Node.js

    Led a marketing campaign for a YouWeb project and built its campaign website and web application.

  3. Jun 2019 - Aug 2019

    Got It.AI

    Software Engineering and AI Intern · Python · JavaScript · Chrome extensions

    Built the ExcelChat Chrome extension, and a microservice automating dataflow through Got It Study while holding problem volume steady. Helped serve the QueryChat AI demo.

  4. Oct 2019 - Oct 2020

    UMass Amherst, Physics Department

    Research Assistant · Python (numpy, scipy, pandas, matplotlib) · MATLAB

    Simulated fluid dynamics for CO2 cooling in particle physics detectors.

  5. Apr 2020 - Sep 2020

    The Arena, Inc.

    Software Engineering Intern · React · Google Cloud

    First engineer at an education non-profit. Built a database and a React site helping students from non-traditional backgrounds find careers and programs.

  6. Jan 2021 - May 2022

    UMass Amherst, Physics Department

    Student Software Developer · Express · React · PostgreSQL

    Built and maintained the software professors used to acquire and share demonstrations across 20+ courses and 1000+ students. Ported a legacy WordPress site with a JSON backend to an Express, React and PostgreSQL application deployed on site. Published résumé · 2026

  7. Jul 2021 - Jan 2022

    Harvest Fintech, Inc. · Remote

    Software Architect and Engineer · Flask · React Native · PostgreSQL

    First significant engineer on the product. Built the backend and database engineering for a mobile application and architected its microservices.

Aug 2022 - Present

Current role

Notable Health · San Mateo, CA

Software Engineer · Python · TypeScript · Node.js · React · PostgreSQL · BigQuery · SIP · GCP · Kubernetes · Terraform

My team owns the voice and conversations platform at a healthcare AI company serving 100+ enterprise customers: the AI-driven patient calls and the whole stack under them, from the conversation services and workflow APIs down to carrier-facing telephony. It handles around 250,000 patient calls a month at 99% uptime, and I set the technical direction for patient identity, routing, observability and reliability. Published résumé · 2026

  • Design the telephony integrations down to the protocol - SIP and TLS, SRTP, caller-ID preservation, DTMF, DID routing - and I wrote the specification health systems build against to connect their phone systems to ours. It has driven more than $1M in ARR.
  • Own secure caller authentication end to end: EHR and FHIR patient lookup, one-time-code verification by SMS, and the auditable hand-off of a verified caller into a customer’s own call center. HIPAA-compliant verification across 5+ health systems.
  • Own reliability and incident response for voice: I lead the debriefs and turn failure modes into platform fixes, including customer-configurable fallback routing that keeps a caller connected when an upstream provider goes dark.
  • Lead the AI-powered testing capability for the flow builder, so a builder can trust a flow before it ever takes a real call. Flow success rates are above 90%.
  • Shipped multilingual conversations, configurable transfer workflows and builder-facing configuration, which cut new-customer launch time from weeks to days. I also contribute to the healthcare-integration core - HL7 and Mirth encounter ingestion, FHIR authorization, insurance data modeling - and mentor engineers from junior through senior.

Tech lead, mentor, and the primary reviewer for a distributed contractor team. Evidence pending

Education · 2018 - 2022

University of Massachusetts Amherst

Both degrees at once, in four years.

B.S. Computer Science
Dean’s List. Student software developer for the Physics Department.
B.S. Astrophysics
Dean’s List. Honors thesis. Research assistant in the Physics Department.
  • CS Machine Learning
  • CS Neural Networks
  • CS Algorithms
  • CS Computer Networking
  • Phys General Relativity
  • Phys Quantum Mechanics
  • Phys Computational Physics
  • Ind. Cosmology and Consciousness  · independent study

03 / Projects

7 entries · 5 open to anyone

Seven projects

Five are live today. Two aren’t finished yet.

saltline at 06:31: an island silhouetted under a blue dawn sky, three named raiders strung along the horizon, a light path on the water, the sloop under full sail. The Ghostgale status panel and the nav chart sit down the right edge.

06:31 · 14.0 kn · seed 4193

Sailing, actually simulated. 06:31, sea state moderate, wind at forty degrees, seed 4193. Sail full, 14 knots, no heel - all of it read straight off the HUD. Capture on this page · 6 Aug 2026

Rendered by astro:assets Picture

saltline-lead-dawn.webp

Shipped from
2,776 × 1,291 · 387 kB
Capture
saltline-dawn-island-blue.png · 3,456 × 2,234
File dated
2026-08-06
Cut away
680 left · 75 top · 0 right · 868 bottom
Which held
the developer panel down the left edge, the top bar, and open water below the hull
Plate 01 / saltline
Live 01 · Flagship Multiplayer Six frames · one seed

saltline

Age of sail in a browser, with a real sailing model under it.

My role
The sailing model, the renderer, the multiplayer, the accounts.
Hard part
Thrust comes off the point of sail, so aim too close to the wind and you stop.
Proof
Live at saltline.app with accounts, up to twenty people to a sea. Live probe · 8 Aug 2026 Project configuration

An age-of-sail game you play in a browser. You captain a sloop, trade between islands, and get chased by raiders. The part I care about is the sailing itself: the boat isn’t steered like a car.

The ocean is generated from a seed. Drag the clock below - same seed, same wind, and the water reads completely differently at four in the morning than it does at sunset.

Off the wind
105°
Point of sail
Beam reach
Thrust
100%
Boat speed
16.0 kn
VMG
4.1 kn downwind
The curve is saltline’s own point-of-sail function, so the boat here behaves the way the boat there does. Drag it, or nudge it with the arrow keys. Thrust comes off the polar, boat speed comes off thrust, and VMG is the part of that speed going the way you actually want to go, which is why the fastest heading is almost never the useful one.
Technical notes
Status
Live, with accounts
Multiplayer
Live, sail together, up to 20 players a sea
Transport
Colyseus rooms over WebSocket
Model
Point of sail sets thrust; thrust and heading set VMG
Luffing
Point too close to the wind and you stop
HUD
Relative wind, heel angle, thrust percent, VMG in knots
Nav chart
Merchant, raider, hunter, elite, derelict, flotsam
Persists
Cargo hold, hull integrity, account progress
Renderer
Babylon.js on Fly.io
Hardening
CSP script-src 'self', frame-ancestors 'none', full Permissions-Policy

One seed at six times of day. Sea state moderate, wind at forty degrees, crest sharpness 0.68, seed 4193, identical in all six. Only the clock moved.

Drag the clock, or use the arrow keys

saltline at night: a full moon low over dark water, the sloop under full sail trailing a wide luminous teal wake.
Speed
14.4 kn
Rel. wind
66°
Thrust
89%
VMG
5.8 kn

At golden hour the sloop is doing 15 knots through the water but only 2.3 toward the mark; at sunrise it’s 13.6 and 11. Picking the angle is the whole game.

Rendered by Arc.tsx

saltline-arc-night.webp

Shipped from
1,600 × 900 · 49 kB
Capture
saltline-night-moon-wake.png · 3,456 × 2,234
File dated
2026-08-06
Cut away
680 left · 75 top · 0 right · 597 bottom
Which held
the developer panel down the left edge, and the bar above the viewport

saltline-arc-sunrise.webp

Shipped from
1,600 × 900 · 140 kB
Capture
saltline-dawn-island-ships.png · 3,456 × 2,234
File dated
2026-08-06
Cut away
680 left · 75 top · 0 right · 597 bottom
Which held
the developer panel down the left edge, and the bar above the viewport

saltline-arc-dawn.webp

Shipped from
1,600 × 900 · 172 kB
Capture
saltline-dawn-island-blue.png · 3,456 × 2,234
File dated
2026-08-06
Cut away
680 left · 75 top · 0 right · 597 bottom
Which held
the developer panel down the left edge, and the bar above the viewport

saltline-arc-daylight.webp

Shipped from
1,600 × 900 · 175 kB
Capture
saltline-fleet-raiders-daylight.png · 3,456 × 2,234
File dated
2026-08-06
Cut away
680 left · 75 top · 0 right · 597 bottom
Which held
the developer panel down the left edge, and the bar above the viewport

saltline-arc-golden.webp

Shipped from
1,600 × 900 · 168 kB
Capture
saltline-golden-hour-calm.png · 3,456 × 2,234
File dated
2026-08-06
Cut away
680 left · 75 top · 0 right · 597 bottom
Which held
the developer panel down the left edge, and the bar above the viewport

saltline-arc-sunset.webp

Shipped from
1,600 × 900 · 139 kB
Capture
saltline-sunset-dramatic.png · 3,456 × 2,234
File dated
2026-08-06
Cut away
680 left · 75 top · 0 right · 597 bottom
Which held
the developer panel down the left edge, and the bar above the viewport
The same 16:46 frame uncropped, with the development panel down the left edge: time of day, sea state, wind angle, crest sharpness and seed. Three raider contacts are marked on the nav chart.

Rendered by astro:assets Picture

saltline-proof-panel.webp

Shipped from
2,400 × 1,499 · 364 kB
Capture
saltline-fleet-raiders-daylight.png · 3,456 × 2,234
File dated
2026-08-06
Cut away
0 left · 75 top · 0 right · 0 bottom
Which held
the bar above the viewport; the developer panel is kept, on purpose

The dev panel, uncropped

This is the 16:46 frame, uncropped. The panel on the left is the simulation’s actual inputs: time of day, sea state, wind angle, crest sharpness, seed. New seed, new ocean, same rules.

Fallowmere in Ember Wilds at dusk: an ember-orange plain of voxel trees, a level thirty character in the centre, quest log and satchel along the edges.

Fallowmere · level 30 · dusk

A voxel MMORPG, shipped. Fallowmere at dusk, level 30, nine thousand fame in. World state, quests and loot all live on the realm server - the browser just renders it.

Rendered by astro:assets Picture

ember-spread-fallowmere-dusk.webp

Shipped from
3,000 × 1,667 · 269 kB
Capture
emberwilds-biome-fallowmere-dusk.png · 3,456 × 2,160
File dated
2026-08-06
Cut away
0 left · 120 top · 0 right · 120 bottom
Which held
the black letterbox bars the capture window puts on the top and bottom
Plate 02 / Ember Wilds
Live MMORPG 02 · In production 64-player realm

Ember Wilds

Browser-based voxel MMORPG. Designed, built, and in production.

My role
Designed it, built it, put it in production.
Hard part
One world staying consistent for everyone in it. The realm server simulates every player.
Proof
Open a tab, make a character, run into somebody. Sixty-four to a realm. Live probe · 8 Aug 2026 Project configuration

A voxel MMORPG that runs in a browser tab. I designed it, built it, and put it in production on Fly.io, where a web tier and a separate realm service keep one world consistent for everyone in it.

Technical notes
Status
Live, no install
Shape
Web tier plus realm service
Realm cap
64 players in one realm
Transport
Colyseus rooms over WebSocket
Renderer
three.js in the browser tab
Host
Fly.io
World
Seven regions, harder as you travel outward
Classes
Unlocked by beast lore and study, not a skill tree
Economy
Fame, satchel, tiered gear

Seven regions, one level-30 character.

Choose a region, or use the arrow keys

The Hearthvale in Ember Wilds: green voxel meadows split by a river, a level one character on the bank, quest panel at top left.
Region
The Hearthvale
Character
Level 1

Where everyone starts. A river, a goblin headman, and a field note telling you that you can tilt the camera.

Rendered by FrameSwitcher.tsx

ember-region-hearthvale.webp

Shipped from
2,000 × 1,111 · 134 kB
Capture
emberwilds-hearthvale-water.png · 3,456 × 2,160
File dated
2026-08-06
Cut away
0 left · 120 top · 0 right · 120 bottom
Which held
the black letterbox bars the capture window puts on the top and bottom

ember-region-fallowmere.webp

Shipped from
2,000 × 1,111 · 133 kB
Capture
emberwilds-biome-fallowmere-wide.png · 3,456 × 2,160
File dated
2026-08-06
Cut away
0 left · 120 top · 0 right · 120 bottom
Which held
the black letterbox bars the capture window puts on the top and bottom

ember-region-greenmarch.webp

Shipped from
2,000 × 1,111 · 107 kB
Capture
emberwilds-greenmarch-ruin-loot.png · 3,456 × 2,160
File dated
2026-08-06
Cut away
0 left · 120 top · 0 right · 120 bottom
Which held
the black letterbox bars the capture window puts on the top and bottom

ember-region-fenmarch.webp

Shipped from
2,000 × 1,111 · 91 kB
Capture
emberwilds-biome-fenmarch.png · 3,456 × 2,160
File dated
2026-08-06
Cut away
0 left · 120 top · 0 right · 120 bottom
Which held
the black letterbox bars the capture window puts on the top and bottom

ember-region-ashen-waste.webp

Shipped from
2,000 × 1,111 · 146 kB
Capture
emberwilds-combat-ashen-waste-nova.png · 3,456 × 2,160
File dated
2026-08-06
Cut away
0 left · 120 top · 0 right · 120 bottom
Which held
the black letterbox bars the capture window puts on the top and bottom

ember-region-greywall-peaks.webp

Shipped from
2,000 × 1,111 · 127 kB
Capture
emberwilds-biome-greywall-peaks-combat.png · 3,456 × 2,160
File dated
2026-08-06
Cut away
0 left · 120 top · 0 right · 120 bottom
Which held
the black letterbox bars the capture window puts on the top and bottom

ember-region-black-plateau.webp

Shipped from
2,000 × 1,111 · 150 kB
Capture
emberwilds-biome-black-plateau.png · 3,456 × 2,160
File dated
2026-08-06
Cut away
0 left · 120 top · 0 right · 120 bottom
Which held
the black letterbox bars the capture window puts on the top and bottom
Two Ember Wilds clients side by side in the Hearthvale. Each character has a speech bubble above it and the same two lines appear in the chat log at bottom left.

Rendered by astro:assets Picture

ember-proof-two-players.webp

Shipped from
2,400 × 1,260 · 160 kB
Capture
emberwilds-MULTIPLAYER-two-players-chat.png · 3,456 × 1,814
File dated
2026-08-06
Cut away
Nothing. The frame is whole.

One realm, up to 64 players

This frame is two of us in the same Hearthvale from two browsers, and a realm holds up to 64 at once. Everyone in it is simulated by the same server, which was the hard part. Capture on this page · 6 Aug 2026 Project configuration

murmuration in ribbon style: a dense violet and white form of drawn-out particle streaks against black, filling most of the frame.

ribbon · 620k particles · 97 fps

A field that listens. Ribbon style at 1.6x sensitivity, 620k particles, 97 fps. Captured against Pink Floyd, four minutes in.

Rendered by astro:assets Picture

murmuration-lead-ribbon.webp

Shipped from
1,999 × 1,145 · 469 kB
Capture
murmuration-ribbon-violet.png · 1,999 × 1,254
File dated
2026-08-27
Cut away
0 left · 0 top · 0 right · 109 bottom
Which held
the transport and readout pinned along the bottom of the browser window
Plate 03 / murmuration
Live 03 · Shipped WebGPU

murmuration

A music visualiser that works out what the music is doing, not just how loud it is.

My role
The analysis, the WebGPU renderer, the whole thing.
Hard part
Frequency cannot separate a voice from a piano - they share the octaves. Stereo placement can.
Proof
Live, runs on a phone, 1.2M particles in 11.9 ms of GPU time. Capture on this page · 27 Aug 2026 Project configuration Developer measurement

A million grains of light pushed through a curl-noise flow field in a WebGPU compute shader, then drawn as velocity-stretched additive sprites. Play it anything - the bundled track, a file you drop on it, or your microphone.

The part I care about is that it is listening rather than reacting. Loudness is easy and it is what most visualisers use. This works out the key and whether the piece is major or minor, the tempo, where the transients are, whether a band is being struck or held, and - the one I am most pleased with - where the music stops to breathe.

Technical notes
Status
Live, and it runs on a phone
Renders
WebGPU: compute sim, additive sprites, bloom, ACES grade
Cost
620k particles at 8.07 ms of GPU time; 1.2M at 11.85 ms
Key and mode
Chroma against Krumhansl-Kessler profiles
Tempo
Autocorrelated spectral flux, phase-locked between estimates
The voice
Centre against sides - 3.5x separation on the bundled track
Articulation
Per-band attack against sustain: struck 0.71, held 0.06
The breath
Quiet passages thin, dim and slow the whole field
Styles
nebula, ink, constellation, ribbon, etching
Sources
Bundled track, any dropped file, or live microphone

Two styles and a lull, all from one session. Only the style and the music changed.

Pick a style, or use the arrow keys

murmuration in ribbon style: long teal and violet strands drawn out into continuous calligraphic curves against black.

Ribbon draws each grain as a long continuous strand. 78 fps at 1.4x sensitivity.

Rendered by FrameSwitcher.tsx

murmuration-frame-ribbon.webp

Shipped from
1,800 × 1,031 · 215 kB
Capture
murmuration-ribbon-teal.png · 1,999 × 1,254
File dated
2026-08-27
Cut away
0 left · 0 top · 0 right · 109 bottom
Which held
the transport and readout pinned along the bottom of the browser window

murmuration-frame-constellation.webp

Shipped from
1,800 × 1,031 · 593 kB
Capture
murmuration-constellation-dense.png · 1,999 × 1,254
File dated
2026-08-27
Cut away
0 left · 0 top · 0 right · 109 bottom
Which held
the transport and readout pinned along the bottom of the browser window

murmuration-frame-lull.webp

Shipped from
1,800 × 1,031 · 161 kB
Capture
murmuration-constellation-lull.png · 1,999 × 1,254
File dated
2026-08-27
Cut away
0 left · 0 top · 0 right · 109 bottom
Which held
the transport and readout pinned along the bottom of the browser window
The full murmuration window: a sparse violet and white constellation of particles on black, and along the bottom a bar reading Pink Floyd - Shine On You Crazy Dia..., 4:21 of 13:35, a waveform, then PARTICLE, CONSTELLATION, SENS 1.6X, FULL, 106 FPS and the key hints beside them.

Rendered by astro:assets Picture

murmuration-proof-interface.webp

Shipped from
1,999 × 1,254 · 257 kB
Capture
murmuration-constellation-sparse.png · 1,999 × 1,254
File dated
2026-08-27
Cut away
Nothing. The frame is whole.

The readout, uncropped

Mode, style, sensitivity, quality and frame rate along the bottom are live controls, not captions. B cycles the render mode, V the style, and the minus and equals keys scale how hard the music drives the field.

hidamari: an autumn canopy path at golden hour, low sun through orange leaves, the trail running away between the trees.

Blender Cycles, offline · 116 fps live

Rendered by astro:assets Picture

hidamari-spread-canopy.webp

Shipped from
3,000 × 1,286 · 1169 kB
Capture
hidamari-hero-canopy-3360x1440.png · 3,360 × 1,440
File dated
2026-08-06
Cut away
Nothing. The frame is whole.
Plate 04 / hidamari
Not public 04 · Rendering

hidamari

Ambient app. Japanese for a sunny spot, the pool of light you stand in.

My role
The offline bake, the runtime reprojection, the delivery.
Hard part
Photoreal light on hardware that cannot path-trace a frame of it. Cycles bakes offline, the browser reprojects.
Proof
116 frames per second live. Developer measurement

A calm ambient app: one autumn canopy path at golden hour, still enough to leave open on a second monitor. It holds 116 frames per second on hardware that could not path-trace a single frame of it.

None of the lighting is computed live. The frames are rendered offline in Blender Cycles and reprojected against a depth pass, so the camera gets real parallax through pre-lit plates - the browser is compositing photographs of a place that doesn’t exist. It’s not public yet; I want the audio right first.

The backing plate: a smeared, inpainted version of the whole scene, sharp only down the centre of the path where the layers in front leave a gap. The backing plate as depth: almost flat, because nearly all of it is far away.
The background trees: autumn canopy across the top and sides, with a hole punched through the middle where the sunlit path runs away from the camera. The background trees as depth: mid grey, darkening into the hole where there is nothing on this layer.
The midground arch: the two big trunks and the branches that meet overhead, which is most of what the finished frame looks like. The midground arch as depth: the brightest of the four, because it is the nearest thing that fills the frame.
The foreground: a band of leaf litter and grass along the bottom with the path cut through it, and nothing at all above. The foreground as depth: bright along the bottom edge and falling away up the path.
The same canopy in the running app, with the camera leaned to its limit: the near trunks have swung across the frame and the path down the middle has hardly moved.
  1. 0 Backing plate 35 to 260 m
  2. 1 Background trees 15 to 63 m
  3. 2 Midground arch 5.5 to 22 m
  4. 3 Foreground 18% of the frame
One frame of hidamari in the four plates it is composited from, their four depth passes, and the same scene alive in the browser. The distances are hidamari’s own, taken over the whole plate rather than this window, and the greys run on one log scale from 4 to 300 metres across all four. Nothing in the finished frame was lit by the browser. What the browser does is move the camera through it.
Technical notes
Status
Not public
Lighting
Baked offline, Blender Cycles
Runtime
Depth reprojection, 116 fps
Delivery
PWA, service worker, AVIF with PNG fallback
Audio
Layered ambience, LUFS calibrated
A sim core that ignores the browser
Greybox 05 · Architecture

Elderwood Vale

Browser-native tower defense. Playable greybox, and an architecture argument.

My role
The sim core, the renderer, the HUD, and the boundary between them.
Hard part
Keeping the simulation away from everything that draws it, with the compiler enforcing that rather than me.
Proof
Playable greybox: placement, waves, enough economy to lose. Capture on this page · 6 Aug 2026

A browser-native tower defense. The part that’s done is the part I care about: the simulation is fully separated from everything that draws it.

The sim can’t touch the DOM, import three.js, read the clock, or call Math.random - and that’s enforced by the compiler and the linter, not by me remembering.

Technical notes
Status
Playable greybox: placement, waves, enough economy to lose
Sim
Fixed 1/30 s tick, snapshot interpolation
Render
three.js, free of the tick rate
HUD
React, subscribed at 10 Hz
Boundary
DOM lib removed from tsconfig, ESLint restricted paths

Three captures of the same board.

Click a tab, or use the arrow keys

Elderwood Vale, greybox geometry, no art pass.

Greybox geometry, no art pass.

Rendered by FrameSwitcher.tsx

elderwood-default.webp

Shipped from
1,280 × 720 · 36 kB
Capture
elderwood-vale-default-1280x720.png · 1,280 × 720
File dated
2026-08-06
Cut away
Nothing. The frame is whole.

elderwood-coverage.webp

Shipped from
1,280 × 720 · 51 kB
Capture
elderwood-vale-placement-coverage-1280x720.png · 1,280 × 720
File dated
2026-08-06
Cut away
Nothing. The frame is whole.

elderwood-stress.webp

Shipped from
1,280 × 720 · 90 kB
Capture
elderwood-vale-stress-burst-1280x720.png · 1,280 × 720
File dated
2026-08-06
Cut away
Nothing. The frame is whole.
Blockhold mid-battle on Greenhollow: a column of voxel enemies walking up the road into shielded soldiers and a hero, arrow and cannon towers firing from the plots beside them, health bars and damage numbers over the fight, a gargoyle in the air.

Greenhollow · wave 16 of 16 · the last road

Rendered by astro:assets Picture

blockhold-lead-battle.webp

Shipped from
2,400 × 1,117 · 195 kB
Capture
blockhold-greenhollow-hollow-king.png · 2,560 × 1,440
File dated
2026-08-27
Cut away
0 left · 0 top · 0 right · 249 bottom
Plate 06 / Blockhold
Live 06 · Shipped Models are code

Blockhold

Voxel tower defense. Ten maps, 249 authored waves, and three boards that each break a rule the other nine keep.

My role
All of it: the voxel modeler, the fixed-step sim, ten maps, 249 waves, the balance.
Hard part
Shipping a game this size with almost nothing to download. Every model is colored boxes placed in code, every sound is synthesized the moment it plays, every icon is a hand-drawn SVG.
Proof
Playable right now: ten maps, three difficulties, three heroes, an endless mode with saved records. Capture on this page · 27 Aug 2026 Project configuration

Elderwood Vale, one row up, is a tower defense as an architecture argument. This is the one that shipped. Ten maps and 249 authored waves, and under them four tower families that go three levels deep, split into two elite branches, and end in two different tier-5 crowns - so the branch you pick decides how the map ends. Plus road traps, a shard economy that overcharges and ascends towers, Veiltide surges under a violet sky, three heroes taking A* move orders, and an endless mode 200 waves deep with a record to chase.

The last three boards are past the finale, and each one breaks a rule the other nine keep. Sunderfall Terraces runs four roads at four heights, and a tower shoots from its own footing, so a ridge above you blocks the shot. Emberwind Reach sets a firestorm that follows your hero: lead it into the horde and it burns him too. Tidereach Causeway closes causeways and opens others mid-battle, and the traffic reroutes onto whatever is still standing, so the defense you paid for is not the one you keep.

Almost none of it is a file. Every model is colored voxel boxes placed in code, every sound is synthesized by WebAudio the moment it plays, and every symbol in the UI is a hand-drawn SVG. The deliberate exception is the painted art on the menus - map cards, heroes, bosses, a title screen - because a campaign screen wants a picture of the place, and a box cannot be one.

Built this August, working with agents - one writing under direction, one reviewing adversarially. Six rounds of that against the code, then a three-round design review where both models wrote independently and then attacked each other. Every report is committed next to the source.

Technical notes
Status
Live, installable, saves locally
Campaign
Ten maps · 249 authored waves · up to five roads
Towers
4 families · 3 tiers · 2 elite branches · 2 branch-locked crowns
Heroes
Three, with A* move orders
Meta
Royal Armory: 8 star-funded tracks, free respec
Endless
200 waves per map, deepest-wave record
Assets
None in 3D. Models are code, audio is synthesized, icons are SVG
Sim
Fixed 60 Hz tick behind an accumulator
Tests
154, vitest
Review
Six adversarial code rounds, then a three-round design review

Four of the ten boards.

Click a tab, or use the arrow keys

Blockhold, the first board entire: one road, thirteen plots, and the meadow you learn the trade on.

The first board entire: one road, thirteen plots, and the meadow you learn the trade on.

Rendered by FrameSwitcher.tsx

blockhold-frame-greenhollow.webp

Shipped from
2,000 × 1,125 · 138 kB
Capture
blockhold-greenhollow-board.png · 2,560 × 1,440
File dated
2026-08-27
Cut away
Nothing. The frame is whole.

blockhold-frame-veiltide.webp

Shipped from
2,000 × 1,125 · 122 kB
Capture
blockhold-frostmere-veiltide-board.png · 2,560 × 1,440
File dated
2026-08-27
Cut away
Nothing. The frame is whole.

blockhold-frame-cinderwake.webp

Shipped from
2,000 × 1,125 · 137 kB
Capture
blockhold-cinderwake-board.png · 2,560 × 1,440
File dated
2026-08-27
Cut away
Nothing. The frame is whole.

blockhold-frame-tidereach.webp

Shipped from
2,000 × 1,125 · 158 kB
Capture
blockhold-tidereach-board.png · 2,560 × 1,440
File dated
2026-08-27
Cut away
Nothing. The frame is whole.
Cubit with Space held: the three layers of the 3x3x3 cube spread apart against a starfield, tiles from 2 up to a glowing pink 1024, floating keycap gizmos marking the six slide directions.

Space held · layers apart

Rendered by astro:assets Picture

cubit-lead-peek.webp

Shipped from
2,400 × 1,116 · 98 kB
Capture
cubit-peek-spread.png · 2,560 × 1,440
File dated
2026-08-20
Cut away
0 left · 100 top · 0 right · 150 bottom
Which held
empty starfield above and below the cube; the band is composed for the lead slot
Plate 07 / Cubit
Live 07 · One file

Cubit

2048, cubed: slide and merge inside a 3×3×3 cube, across six directions instead of four.

My role
The whole file: engine, renderer, input, synthesized sound.
Hard part
Making six directions feel obvious. Swipes are scored against how each axis actually projects on screen, so a swipe along a lattice edge does what it looks like.
Proof
One self-contained 553 KB HTML file, 62 tests. Developer measurement Project configuration

It’s 2048 with a third axis: twenty-seven cells, six slide directions, the same merge rule. The axis you can’t see is the one that kills you, so tiles blocking your view of other tiles go translucent, and holding Space spreads the layers apart to let you read the inside of the board.

Vanilla JS with a vendored three.js, bundled into a single HTML file you could attach to an email. The input got the most iteration: swipes are matched to the on-screen projection of all six directions, and on a phone you can lean the device a capped twelve degrees to peek around the cube, without changing what any swipe means.

The compact Cubit board from the same game: tiles that sit between the camera and other tiles rendered translucent, so the 512 and 1024 read through the front layer.

Rendered by astro:assets Picture

cubit-inset-board.webp

Shipped from
2,000 × 1,125 · 65 kB
Capture
cubit-board-xray.png · 2,560 × 1,440
File dated
2026-08-20
Cut away
Nothing. The frame is whole.
Technical notes
Status
Live, saves locally
Board
3×3×3, six slide directions
Bundle
One HTML file, 553 KB, nothing external
Input
Swipes scored against screen-space axis projections
Tilt
Gyro peek, opt-in, capped at 12 degrees
Tests
62, node --test

04 / About

Two degrees, one habit

I learn things by building them.

Place
Bay Area California
Work
Software engineer Notable Health, since Aug 2022
Studied
B.S. Computer Science B.S. Astrophysics
Building
Six things four live, two not yet

I did two degrees at once, computer science and astrophysics, because I couldn’t choose between them. Some weeks that meant Algorithms and General Relativity in the same problem-set pile.

In college I simulated CO2 cooling for particle detectors. Now I simulate an ocean for a sailing game.

Off the clock
Heirloom tomatoes, bikes, and Pink Floyd, roughly in that order.
Long held
Wanted to be an astronaut since I was four. Still would.
Will debate
Python is the best language. I’ve heard the counterarguments. File an appeal
Best class
Cosmology and Consciousness. An independent study, and I had to ask for it.

05 / Skills

28 of 32 turn up above

Grouped, unrated

Pick one to see where it turns up.

Languages

Frontend

Turns up in Elderwood ValeNotable HealthHarvest FintechUMass Physics, softwareThe ArenaRendezvous

Turns up in Ember WildsElderwood ValeGrinchJump

Turns up in saltline

Turns up in AutoTyperdeviation.htmlGrinchJump

Turns up in hidamari

Backend

Turns up in Notable HealthYouWeb

Turns up in Harvest FintechRendezvous

Turns up in UMass Physics, software

Turns up in Notable HealthHarvest FintechUMass Physics, softwareRendezvous

Turns up in Notable Health

On the résumé only.

Turns up in saltlineEmber Wilds

Turns up in Notable Health

On the résumé only.

Infrastructure

Turns up in Notable HealthThe ArenaRendezvous

Turns up in Notable Health

On the résumé only.

Turns up in Notable Health

Turns up in saltlineEmber Wilds

On the résumé only.

Turns up in Notable Health

Data and scientific

Turns up in UMass Physics, research

Turns up in UMass Physics, research

Turns up in UMass Physics, research

Turns up in UMass Physics, research

Turns up in UMass Physics, research

Turns up in Notable HealthGot It.AICoursework

06 / Contact

Write to me

I read it, and I answer it. Send me a hard systems problem, an overambitious browser idea, or a reason Python isn’t the best language. Email is the fastest way in.

aj8uppal@gmail.com

Inspection mode · ?seed=4193 Leave