Projects

This page is basically my engineering notebook: what I built, what broke, what I changed, and what I learned while shipping things across software and hardware.

Featured engineering work

Compiler pipelines, autodiff, embedded IoT, and hardware integration.

SystemsFeatured
P01
Compiler Systems·Spring 2026

C Compiler

OCaml compiler from a supported C subset to runnable x86-64, with TACKY IR and instruction fixups in between.

Motivation: I got tired of treating compilers like magic, so I started building one. Nora Sandler's book gave me the roadmap; I wrote the passes myself. Lexer and parser into an AST, then TACKY to flatten nested expressions, then stack-backed x86 with a fixup pass when memory-to-memory ops are illegal. Right now it honestly covers return constants and nested unaries like return ~(-2);. Broader C is next, but only after each stage stays correct.

Challenge: Direct AST-to-assembly stopped scaling once expressions nested.

OCamlRecursive DescentASTSemantic AnalysisTACKY IRx86-64
IteratingActively Expanding
Machine LearningFeatured
P02
ML Systems·Spring 2026

MiniTorch-OCaml

Reverse-mode autodiff in OCaml: forward builds a graph, backward fills grads, gradcheck keeps me honest.

Motivation: Framework backprop always felt like a black box, so I wrote my own. Nodes store values, grads, parents, and ops. Forward grows the graph; backward walks it. Most bugs do not show up in the forward pass; they show up when a shared node silently gets the wrong accumulated gradient. Finite-difference gradcheck is what I trust. The tiny MLP with SGD/Adam is just a smoke test that the pieces still talk to each other.

Challenge: Gradient bugs rarely show in forward outputs.

OCamlAutodiffComputation GraphsGradient CheckingSGD/Adam
IteratingExtending operator coverage
EmbeddedFeatured
P03
Embedded Robotics·Spring 2026

BloomBot IoT

IoT flower for long-distance check-ins: proximity opens the bloom, and remote messages blink out in Morse on an LED heart.

Motivation: The idea was simple: people far apart should still have something physical to share. BloomBot lives on an Arduino UNO R4 WiFi with Blynk. Get close and an ultrasonic sensor drives the servos to open the flower. Send a message from the app and an LED heart inside blinks that message in Morse. LCD output helps when I cannot sit on serial during a demo. The cute part is the flower. The hard part was keeping WiFi, sensing, multi-servo peaks, and Morse timing honest on one board without brownouts.

Challenge: Power rails brown out under concurrent servo peaks without margin and sequencing.

Arduino UNO R4 WiFiBlynkWiFiS3ServosUltrasonicI2C LCD
ShippedShipped demo; next hardware revision
HardwareFeatured
P04
Electromechanical Systems·Spring 2026

Analog Electromechanical Lightsaber

Designed and fabricated a handheld electromechanical system integrating custom mechanical packaging, discrete analog electronics, embedded lighting control, and structural design into a durable wearable prototype.

Motivation: I built this in Detkin Lab as a handheld system that had to leave the breadboard. The work meant designing a custom Fusion 360 hilt, emitter, and battery carrier across multiple print revisions; integrating a discrete analog audio circuit (NE555 timer, RC network, PN2222A transistor) alongside LED blade illumination on a switched 9V power architecture; and manufacturing the boards with 40+ through-hole joints. The electronics were straightforward; the challenge was packaging them into a handheld device that could survive repeated impact and handling. Blade bending loads broke the hilt twice; cable length forced an LED pad salvage.

Challenge: Polycarbonate blade as a lever arm concentrated bending moment at the printed hilt.

Fusion 3603D PrintingNE555PN2222APerfboardThrough-hole Soldering
ShippedShipped Demo
EmbeddedFeatured
INT-01
Electromechanical Systems·Summer 2026

Vend-A-Shoe

Designed and shipped a client-facing electromechanical dispensing platform integrating mechanical packaging, embedded control, and cloud-connected automation.

Motivation: During my internship at BrainChild Engineering, I developed Vend-A-Shoe for a client deployment. The work meant designing a custom mechanical enclosure; integrating electrical distribution for 4 MG996R servos, 8 LED indicators, and a cooling fan across 40+ wire interconnects; writing embedded control on a Raspberry Pi; and connecting that stack to an existing frontend through a cloud command pipeline. The hardest part was not any single subsystem; it was integrating them. Packaging moved the harness; electrical changes moved the enclosure; software had to absorb real manufacturing tolerances.

Challenge: Fitting 4 servos, 8 LEDs, a fan, harness, Pi, and power in a serviceable volume.

Raspberry Pi 4PythonRPi.GPIOMG996RLEDsCooling fan
ShippedClient Deployment
EmbeddedFeatured
P16
Electromechanical Systems·2025–2026

Automatic Tennis Ball Shooter

Designed and fabricated a client tennis-ball launcher prototype at BrainChild Engineering integrating ESP32 wireless control, dual RS-775 flywheel drive, NEMA 17 stepper feed, MOSFET motor switching, and 12V-to-5V power regulation into a modular electromechanical system.

Motivation: I built this at BrainChild Engineering for a client demo that had to leave USB babysitting. The work meant migrating from an Arduino Mega / Bluetooth path to an ESP32 that owned motor sequencing; driving dual RS-775 flywheels through MOSFET modules under MCU PWM instead of pot speed controllers; indexing balls with a NEMA 17 on an A4988; and splitting a fused 12 V pack so actuators stayed on the high rail while a buck fed 5 V logic. The MOSFETs are hard switches: PWM duty cycle sets average motor voltage, and the motor’s inductance / inertia smooth the pulses. Failures taught as much as the architecture: no buck at first left the ESP32 dead on battery, the stepper print was too flimsy until a denser reprint, and a PWM test oversped a motor so hard that the fuse did not open, buck / battery solder joints came off, and a wire melted. It stayed a prototype on purpose: enough for a Replit-controlled multi-motor demo, not a finished consumer launcher.

Challenge: 12 V pack without a buck converter left the ESP32 unable to run correctly off battery.

ESP32C++NEMA 17 StepperA4988RS-775 DC MotorsMOSFET Modules
ShippedClient prototype / demo

Supporting builds

Smaller builds, but still real engineering: web apps, CV pipelines, signal processing experiments, and embedded games that made me sharper across different parts of the stack.

Final 3D render of the ultrasonic sensor PCB
Hardware
P15
PCB Design·Summer 2026

Custom Arduino Sensor PCB

First complete PCB: KiCad schematic through two-layer layout and Gerbers for an Arduino Nano, HC-SR04, and status LED.

Motivation: I built this to learn the real board house pipeline, not to invent a fancy circuit. Custom HC-SR04 footprint from measured dimensions, two-layer routing with a ground plane, DRC, then Gerber and Excellon export for PCBWay. Breadboards were familiar. Owning symbols, copper, mask, and fab files was the point.

Challenge: Stock connector footprints did not match the real ultrasonic module.

KiCadArduino NanoHC-SR04Through-Hole PCBGerber
ShippedFabrication-ready Gerbers
Afterthought landing page with dual-axis rating promise
Full-Stack
P17
Product Systems·Summer 2026

Afterthought

Built a deployed personal media archive that separates perceived film quality from personal impact, captures short post-watch reflections, and organizes them into a searchable theme-based knowledge base.

Motivation: I kept remembering that a movie was an 8/10 and forgetting why it stayed with me. Existing trackers are excellent at logging titles and scores; they lose scenes, questions, and takeaways. I designed Afterthought as a Next.js App Router product with dual-axis ratings (Overall vs Personal Impact), a hard 2–3 minute capture constraint centered on one prompt (“What stuck with you?”), browser voice notes with transcription and AI organization, TMDB-backed media identity, and a persistence boundary that runs on a seeded Zustand demo store or Supabase auth/Postgres/storage. The hard problem was not adding fields. A multi-section journal felt like homework, so I forced capture and organization apart: the user writes the thought; AI may suggest themes afterward, never overwrite the original.

Challenge: A richer schema (lessons, scenes, quotes, techniques) made post-movie capture feel like a questionnaire.

Next.jsTypeScriptReactSupabaseTMDB API
ShippedDeployed MVP
CIS 5450 loan default risk cover
Machine Learning
P05
ML Pipelines·Spring 2026

Loan Default Risk (CIS 5450)

Lending Club default model for CIS 5450: clean the data, kill leakage, then rank risk under a messy class balance.

Motivation: Course project on ~1M Lending Club loans. I filtered to paid vs charged-off, threw out post-outcome cheat columns like recoveries and total_pymnt, and only fitted transforms after the train/test split. Models went from logistic regression up to tuned XGBoost around 0.7175 AUC. Tuning barely moved the needle once the columns were honest. Accuracy was a trap with an 80/20 split, so I cared about AUC, PR, and the fact that a 0.5 threshold is not a business decision.

Challenge: Some of the strongest-looking columns only exist after default.

PythonPandasscikit-learnXGBoostimbalanced-learn
ShippedCourse project complete
Machine Learning
P06
ML + Tools·2026

LabReach AI

Research outreach helper: scrape lab pages, draft with a local LLM option, and never send until I review.

Motivation: Cold email prep was eating time, so I automated the boring parts and refused to automate the dangerous one. LabReach finds faculty pages, pulls context, drafts with Ollama when I want text to stay local, and writes a review artifact before Gmail can do anything. JS-heavy department sites break naive scrapers. That is fine. Guessing an email and blasting it is not.

Challenge: JS-heavy faculty pages break static scrapers.

PythonOllamaBeautifulSoupPlaywrightSQLite
IteratingCLI pipeline working; expanding campaign tooling
Video
Full-Stack
P07
Signal + Web·2025-2026

Count Coach

Dance practice tool: scrub a waveform, get BPM for that section, keep rehearsing.

Motivation: I kept losing time hunting song sections and tempos, so I built the tool I wanted. Pick a region on the waveform, send it for tempo analysis, get numbers back without breaking rehearsal flow. Started in Colab, ended as a deployed Next.js app with Python on the backend. When the selection edges are wrong, the BPM looks wrong, and dancers blame the model. Sync mattered more than fancy DSP.

Challenge: Selection boundaries must match what the analyzer hears.

Next.jsWaveSurferLibrosaPythonVercel
ShippedShipped personal practice tool
Video
Embedded
P08
Embedded·2026

Arduino TFT Tetris

Handheld Tetris on Arduino Nano + ST7735: game loop, SPI draw, buttons, and sound all on-device.

Motivation: I wanted a real embedded game loop, not a simulation. Everything runs on the Nano: gravity, collision, scoring, SPI redraw, piezo cues. Half the 'bugs' were solder joints on the display. I staged controls on a two-button harness first so I was not debugging mechanics and firmware at the same time.

Challenge: Intermittent SPI looked like sprite corruption.

Arduino NanoC++ST7735SPIAdafruit GFX
ShippedPlayable prototype complete
Video
Machine Learning
P09
CV + ML·2026

Bhangra Coach

CV dance coach: compare your form to a reference clip and get cues that actually mean something.

Motivation: I dance, so I care when feedback is useless. Bhangra Coach uploads a clip, runs MediaPipe landmarks, aligns against a reference when tempos differ, then surfaces deltas in a Next.js UI with FastAPI and Supabase behind it. Raw joint error is not coaching. Alignment and wording are the product right now, and both still need work.

Challenge: Tempo differences break naive frame-wise compare.

Next.jsFastAPIMediaPipeSupabaseComputer Vision
In progressIterating on feedback quality
Video
Full-Stack
P10
Product·2026

Penn Plates

Campus dining social app from Penn SPARK: auth, profiles, and a small student loop that actually shipped.

Motivation: SPARK project with a real deadline. We built Penn Plates on Next.js and Supabase so students could coordinate around dining without a bloated feature list. Auth and RLS had to be right. Scope cuts hurt, but they are why we had a demo instead of half-finished screens.

Challenge: Ambition versus timeline.

Next.jsSupabaseReact
ShippedDemo-ready build completed
Video
Full-Stack
P11
Meta·2025-2026

Portfolio Website

Living engineering portfolio that turns projects into structured technical case studies instead of a static screenshot gallery.

Motivation: I built this site so recruiters and engineers can evaluate my work the way I want it evaluated: systems thinking, design decisions, iterations, evidence, and reflection. Hardware, software, research, embedded, ML, CAD, and product work all land in one visual and narrative system. Typed project data drives cards, routes, heroes, and media. Case studies attach by slug. Featured work and supporting builds get different homepage weight so experiments stay archived without competing with flagship projects. Adding a project should feel like publishing into a system, not redesigning a page.

Challenge: Earlier pages showed outcomes without process, failures, or tradeoffs.

Next.js 16React 19TypeScriptTailwind CSS 4Framer Motion
IteratingContinuous iteration

Earlier work

Course and earlier builds. I keep them here for context because they show how my approach changed over time.

3D Brain Model media 1
CAD / Design
P12
CAD·High School

3D Brain Model

Maya brain model that I cleaned up and 3D printed as a labeled study piece.

Motivation: Early project. I modeled cortical detail in Maya, fought overhangs and wall thickness for FDM, then printed and labeled it. Pretty geometry that will not print is useless. Kept here because it is one of the first times I cared about a physical artifact, not just a screenshot.

Challenge: Detail versus FDM reliability.

MayaCAD3D Printing
ArchivedArchived
Health Outcomes Analysis media 1
Data Science
P13
Data·Course project

Health Outcomes Analysis

OIDD capstone: socioeconomic factors and health outcomes, with models I could actually explain.

Motivation: Course analysis in Python. Clean the data, plot what matters, try interpretable trees, and write the assumptions next to the charts. Observational data does not get to pretend it is causal. The deadline was real, so communication had to travel with the numbers.

Challenge: Rigor versus deadline.

PythonPandasSeabornDecision Trees
ArchivedArchived