Selected
Works.
Here's the curated selection of what I'm most proud of. The whole is always greater than the sum of its parts, but sometimes, the parts can be pretty big on their own. In those cases, where one massively-scoped project encapsulated multiple standalone sub-projects, I've broken them apart. Some of these ship to real users, some I built to learn, and a couple are still under construction and experiencing rolling updates.
DoorDroppr — Mobile Field Platform with Sensor-Based Work Verification
DoorDroppr is a standalone, multi-tenant mobile platform for teams doing coordinated work out in the field, expected to enter private beta by mid-August 2026. The engineering problem we care most about is verification, given only a phone in someone's pocket, can you tell genuine on-foot activity apart from someone who drove, biked, or spoofed their GPS? We build it as Heurix Corp's three-person team, across the whole system: the React Native field app with live GPS tracking, the PostGIS-backed Supabase backend with row-level tenant isolation, and the sensor-fusion ML model (detailed in a companion entry) that scores whether activity really happened on foot. The phone handles capture and feature extraction; scoring runs server-side.
Highlights
- ▹A cross-platform mobile app for coordinated field work: a React Native field client streams live GPS coverage over PostGIS, and a sensor-fusion ML model fuses the phone's sensors to verify t...
- ▹Built the field app in React Native (Expo / TypeScript): crew start a shift and the app streams live GPS breadcrumbs into PostGIS as they move, drawing a live trail on the map with a camera...
- ▹Fuses the phone's sensors, GPS, pedometer (steps + cadence), accelerometer/gyroscope (gait + heading), barometer (elevation), into a feature stream for the verification model, so the system...
- ▹Designed a multi-tenant PostgreSQL + PostGIS schema (orgs, members, projects, routes, shifts, positions) with row-level-security tenant isolation enforced through SECURITY DEFINER helper fun...
Universal Conversion Tracking — Pixel + Server-Side CAPI
Browser-only conversion tracking quietly loses a large slice of events to ad blockers, iOS App Tracking Transparency, and privacy-strict browsers. This is a design for a drop-in measurement layer modeled on the Meta Pixel + Conversions API pattern: a lightweight browser snippet fires a standard event taxonomy (Landing, Lead, Booking, Purchase, Call), and a server-side Conversions API hardens those events against ad blockers and cookie loss, so conversions stay measurable on essentially any site. This is a concept and forward-roadmap piece, not yet built; the design draws directly on the dual-path Pixel + CAPI stack proven at Lustr.
Highlights
- ▹A self-hosted, Meta-Pixel-style event-tracking layer, a browser snippet plus a server-side Conversions API, that measures real conversions on any business's website without depending on a fr...
- ▹Browser-side snippet: a small JS tag dropped on a business's landing and checkout pages, firing a standard event taxonomy (Landing, Lead, Booking, Purchase, Call) keyed to a first-party attr...
- ▹Server-side Conversions API: a companion server-side path mirrors the key revenue events with a shared deduplication event_id, recovering the conversions that browser-only tracking loses to...
- ▹No-code install targets: planned plugins for common stacks (Shopify, WordPress, Calendly, Stripe, GTM) so a non-technical owner can adopt measurement without a developer.
Activity Verification ML — Sensor-Fusion Model
The verification problem behind DoorDroppr is: given only a phone, can you tell a genuine on-foot route from someone who drove it, biked it, or faked GPS from home? We're building the answer as a sensor-fusion classifier that turns the phone's signals into a single score for P(genuine on-foot activity). What makes it tractable is the data strategy: we generate labeled training data by running real routes. It's already working: the step-count-vs-distance and gait signals reliably separate genuine walking from driving. The model is engineered features feeding gradient-boosted trees, deliberately not deep learning. We prototyped running it on-device with Core ML, but continuous inference was too power-hungry (the phones were overheating in testing), so scoring and the final verdict run server-side while the phone handles cheap capture and feature extraction. Current work is the learned model plus hardening against biking and GPS spoofing.
Highlights
- ▹A sensor-fusion classifier that scores whether physical work was genuinely done on foot, versus driven, biked, or GPS-spoofed, trained on labels we generate by doing the work and recording i...
- ▹Sensor fusion: combines GPS, the pedometer (step count + cadence), the accelerometer/gyroscope (gait + heading), and the barometer (elevation) into one feature stream, so the model sees far...
- ▹Genuine-activity signature: walking 1 km logs ~1,300 steps while a car logs ~0, the hardest-to-fake tell; a human gait waveform in the accelerometer (vs. an engine's vibration or a phone res...
- ▹Self-generated labels (the data flywheel): we walk real routes for genuine positive labels, then deliberately drive, bike, and spoof the same routes to generate negatives, a clean supervised...
Azimuth — Flight Club & FBO Management
Flying clubs and FBOs (fixed-base operators) still run on dated software like MyFBO. Azimuth is a modern replacement covering the full operational core: members and their pilot credentials, the aircraft fleet and its maintenance, scheduling and dispatch, flight logging, and member billing. The whole loop is where a reservation becomes a checked-out aircraft, becomes a logged flight, becomes a posted charge on a member's ledger. It's built multi-tenant from day one (every domain table is org-scoped, so adding a second club needs no schema change) and access is capability-based, not role-based. As Heurix Corp's three-person team, we built it end to end (schema, server actions, auth, RBAC, and UI), won a competitive evaluation against the incumbent vendors, and migrated the client off their legacy system. Azimuth is live in production today, running daily operations for a roster of roughly 1,500 members.
Highlights
- ▹Built a modern flight-club & FBO management platform, a multi-tenant Next.js 16 app covering members, fleet & maintenance, scheduling, dispatch, flight logging, and billing, over a 149-table...
- ▹Won the account against established competitors in the space: Heurix presented a one-hour walkthrough and live demo to the client's board of directors and came away with unanimous approval t...
- ▹Executed the cutover off the legacy platform, moving roughly 25 years of accumulated operational history: 29,172 reservations, 14,740 flights totalling over 18,000 Hobbs hours, and 5,167 wei...
- ▹Built the full operational loop across ten documented modules and 133 page routes, Members & roles, Fleet & maintenance, Scheduling & dispatch, Flight logging, Training, Billing, Weather & w...
Legacy Data Migration Engineering
Replacing the incumbent system was the easy half. The hard half was that a quarter century of the client's operating history lived in a schema nobody had documentation for, where the meanings had drifted from the column names. I treated the mapping as something to be measured against the live data rather than assumed, wrote the findings down as a runbook, and built every importer to be idempotent so a re-run writes nothing instead of silently doubling a member's logbook. The whole thing was rehearsed end to end against a full production snapshot before it was allowed near the real database.
Highlights
- ▹Reverse-engineered an undocumented legacy flight-ops database and moved roughly 25 years of it onto Azimuth: 29,172 reservations, 14,740 flights, 5,167 weight-and-balance loadings, with an i...
- ▹Reverse-engineered the legacy schema by measuring it, not by trusting it. The system had no cancelled flag: it rewrote a dispatch's type to 'Y' and prepended the reason to the remarks, which...
- ▹Caught a double-counting trap that would have inflated the club's flight hours. Dispatches nest, a rental being a parent row plus one row per leg flown inside it, and the legs subdivide the...
- ▹Established the join key empirically: the legacy short-login maps to Azimuth's member number, with email as fallback, resolving 27,001 of 28,905 dispatches at 93.4%. Three 'customers' turned...
Test & Release Engineering
A platform that a flying club depends on to know which aircraft is airworthy cannot ship on optimism. The test strategy is three-layered: unit tests for pure logic, integration tests against a real throwaway Postgres, and Playwright end-to-end tests against a production build. What makes it interesting is not the count but the plumbing, because getting a suite this size to run in a sane amount of time on self-hosted hardware turned into a genuine systems-debugging exercise involving fsync, tmpfs, and Postgres inode behaviour.
Highlights
- ▹675 test files across unit, integration, and Playwright end-to-end, run on a self-hosted runner against an ephemeral tmpfs Postgres, gating an hourly dev → stg → main promotion pipeline over...
- ▹675 test files split across three layers: 192 unit, 256 integration against a real ephemeral Postgres, and 227 Playwright end-to-end specs driven against a production build on that same data...
- ▹Cut the integration suite from over 33 minutes (never finished, killed) to 9m51s by running the throwaway Postgres on tmpfs with durability off, roughly a 3x win. The cause was that the harn...
- ▹Diagnosed a 'No space left on device' failure on a runner with 945 GB free. TRUNCATE assigns every table and index a new relfilenode and defers unlinking the old file to the next checkpoint,...
AI Support Triage Agent
Support reports from inside the product are the highest-signal bug reports there are, and they are also written by people who are not engineers and arrive faster than a three-person team can triage. This subsystem turns them into worked tickets. Members report from any screen with attachments, operators get a queue with severity triage, and an investigating agent can claim a report, post a task-by-task plan that the operator watches live, and link the pull request it opened. The design work that mattered was deciding what the agent is not allowed to hold.
Highlights
- ▹An in-app support system where members file reports, operators work a queue, and an autonomous investigating agent claims work through a credential-less machine API, publishes its plan, and...
- ▹Built the agent's interface as an HTTP machine API rather than a database connection, on the explicit reasoning that a process which reads untrusted member-written text and runs a shell shou...
- ▹Kept one status machine for three callers. The member's own pages, the operator panel, and the agent API all route their writes through a single module, because a state machine enforced in o...
- ▹Separated authorization from operations by design: each caller proves identity in its own way, a session for the panel and a bearer token for the API, then calls into shared logic. Mixing th...
Multi-Tenancy & Authorization
Keeping one club from ever seeing another club's data is a first-order security property rather than a feature, so Azimuth enforces it in two independent layers: every query filters on an org id resolved from the session and never from user input, and Postgres row-level security enforces the same boundary underneath. A bug in either layer alone therefore fails to become a data breach. Authorization on top of that is capability-based, and the capability grants are themselves per-organization data rather than hardcoded roles.
Highlights
- ▹One deployment serving many independent clubs from one Postgres database, with tenant isolation enforced twice (application layer and row-level security) across 149 org-scoped tables, and 89...
- ▹Every tenant-owned table carries an org_id and every query filters by the caller's, where that value is established at authentication time and re-resolved per request. It is never read from...
- ▹Row-level security enforces the same boundary a second time inside Postgres, so the isolation does not depend on the application layer being correct. Defense in depth here is not a slogan: i...
- ▹89 fine-grained capabilities across roughly a dozen domains (members, dispatch, fleet, maintenance, billing, curriculum, checkrides, broadcast, admin) checked by both server actions and UI s...
Weight & Balance Engine
Before a flight the crew has to prove the aircraft is loaded inside its certified envelope, and getting that arithmetic wrong is a safety event rather than a bug report. Every tail in Azimuth can carry a weight-and-balance profile made of its empty mass, fuel tanks, loading stations, and one or more certified centre-of-gravity envelopes. A planner takes that profile plus an actual load and computes total weight, moment, and CG, checks it against the selected envelope, and can save the result onto a reservation so it is ready at check-in.
Highlights
- ▹A per-aircraft mass and centre-of-gravity subsystem where one pure, dependency-free module powers both live client-side recompute on every keystroke and the authoritative server-side recompu...
- ▹The entire computation is one pure, dependency-free module, imported unchanged by the client planner for instant recompute as the crew types and by the server actions for an authoritative re...
- ▹The client's numbers are never trusted for storage. Live recompute exists for feedback; what gets written to the database is always recomputed server-side, which is the only version that mat...
- ▹Certified envelopes are modelled as interpolated limits rather than a single box, resolving the permitted forward and aft arm at a given weight by linear interpolation so an envelope with a...
Flight School & Training Records
A flying club is also a school, and the school half has its own object model. Staff author syllabus templates made of ordered lessons, instructors record progress lesson by lesson and grade assessments, and students see a live ladder of where they stand alongside the courses they are enrolled in. It hangs off the same org-scoped, capability-gated, soft-deletable foundation as the rest of the platform, and it is the schema the later assessment features (stage checks, checkrides, exam grading) are built on.
Highlights
- ▹The training-record backbone for the flight-school side of a club: authored syllabi of ordered lessons, per-student progress, in-cockpit lesson delivery, exam grading, stage checks, and chec...
- ▹Syllabus templates as authored curricula of ordered lessons, with per-student progress recorded against them, giving both the instructor and the student a shared view of position in the cour...
- ▹Assessment surfaces layered on that backbone: in-cockpit lesson delivery and gradesheets, exam grading, stage checks, and checkride records, plus aircraft checkouts and checkrides as their o...
- ▹Student-facing and instructor-facing views of the same data, so a member sees their courses and standing while an instructor works a roster.

Lustr Detailing: Production Platform and CRM
Lustr is a mobile-detailing business that Heurix Corp built the production platform for. As Heurix's software lead I built and operate the whole software stack: booking, memberships, scheduling, admin tooling, and the ops surfaces behind it. Shipping this to real customers has taught me more than any class project ever could.
Skills exercised
Highlights
- ▹Built and shipped a production full-stack platform for booking, scheduling, payments, and CRM. Real users, real revenue, real on-call.
- ▹Built and shipped a full-stack platform on React (Vite), Supabase/Postgres, Stripe, and Vercel that now runs real customer bookings and payments.
- ▹Implemented a conflict-aware scheduling engine with slot holds, overlap detection, crew-capacity logic, and DB locking to keep booking state consistent under concurrent checkout traffic.
- ▹Built a full booking + membership flow: draft-persistent multi-step wizard, cart checkout, recurring subscriptions, and customer-facing account management.
Admin Suite & CRM
Everything a customer sees is the booking front end. This is the other half: the internal admin suite the business is actually operated from. It spans roughly two dozen views behind an admin-only guard, covering a daily run-sheet, appointments and scheduling, a full customer record, revenue and funnel analytics, memberships, promotions, reviews, an admin quoting and booking tool, and a kanban ops board. I built it as a real operations product, not a settings page. I keep exact table and endpoint names private, since it runs on live customer and payment data.
Highlights
- ▹The back-office that actually runs the business: around two dozen admin views over a Supabase/Postgres backend, from a 360-degree customer record and booking-on-behalf to Stripe payments, a...
- ▹360-degree customer record: one page aggregates a customer's profile, vehicles, addresses, appointments, orders, carts, membership and credit balance, notes, and promo history. From it an ad...
- ▹Customer-health scoring: a hand-tuned exponential-decay RFM model (recency, frequency, and monetary value with roughly a 139-day half-life) combined with an ordinary-least-squares booking-ve...
- ▹Server-side scheduling and availability: slot bookability (business hours with effective-date fallbacks, vacation and partial-day blocks, per-vehicle-group service durations, buffer expansio...
Database Administration
This is the database backbone for everything Lustr does in production: bookings, payments, memberships, and CRM events. I built it RLS-first, pushed critical writes through stored procedures, and wired forward-only migrations into CI so changes don't get messy. I keep exact table and policy details private here because this system handles real customer and payment data.
Highlights
- ▹Production Postgres architecture on Supabase: ~30 tables, ~95 RLS policies, ~55 RPC procedures, and ~30 edge functions guarding money, scheduling, and secrets.
- ▹Roughly 30 tables across user identity, booking and availability, service and pricing catalog, membership and credit accounting, payment and order history, admin notes, notifications, and co...
- ▹RLS enabled on every user-facing table, with ~95 policies in four tiers: user-owned data keyed on the caller's auth identity, admin-only tables gated on a role helper, public-read catalog ta...
- ▹Stored procedures are the only write path for anything that touches money, scheduling, or credits. ~55 procedures handle availability calculation, hold/confirm/cancel lifecycle, reschedule,...
Brand & Marketing Design
I built Lustr's visual identity end to end, from logo system and type/color tokens to flyers, social creative, business cards, and in-app illustration. The same person writing the product code also shaped the brand language, which kept the product and marketing voice consistent from day one.
Highlights
- ▹Designed Lustr's brand from the ground up: logo, typography, social assets, and print collateral, all in Figma.
- ▹Designed Lustr's logo and brand system, typography, color palette, and component tokens, used consistently across the iOS app, web booking flow, and marketing surfaces.
- ▹Authored marketing collateral in Figma: launch flyers, social graphics, neighborhood door-hangers, business cards, and seasonal promo materials. Iterated against real conversion data from ea...
- ▹Built a small design library so non-designers (the ops team, partners) can produce on-brand assets without breaking the system.
Paid Acquisition & Ad Attribution
Lustr's paid channel runs on Instagram and Facebook. I own it end to end, the Meta Pixel and Conversions API integration that makes the data trustworthy, the creative that goes into the ads, the targeting and budget decisions in Meta Ads Manager, and the ROAS review that tells me which ads to kill and which to scale. The attribution infrastructure is what makes the rest possible: without server-side events, Meta's optimizer is flying blind on roughly a third of real conversions.
Skills exercised
Highlights
- ▹Wired up Meta Pixel + server-side Conversions API to recover the 30–40% of conversions that ad blockers and iOS ATT would have erased, then ran conversion-objective campaigns on Instagram an...
- ▹Built a dual-path attribution stack: browser-side Meta Pixel fires on every page and SPA route change, plus a server-side Conversions API call fires from the Stripe webhook after payment cle...
- ▹Six events instrumented: PageView, Lead (contact form), CompleteRegistration (verified signup), Schedule (booking confirmed), Purchase (Stripe payment), Subscribe (membership activated). The...
- ▹Server-side CAPI runs from the payment webhook, not the browser, it bypasses ad blockers, iOS App Tracking Transparency, and strict-mode browsers entirely. Pixel-only setups lose 30–40% of c...
DevOps & Release Engineering
This is the release and reliability system behind Lustr. I set up the dev-to-staging-to-main flow, hotfix backports, branch previews, migration deploys, and guardrails that block frontend promotion when backend migrations fail. It lets us move fast day to day without rolling broken changes into production.
Highlights
- ▹Built a release pipeline that lets us ship fast without breaking prod: layered branching, two CI gates, staged deploys, and migration-gated promotion.
- ▹Three-tier branching (dev/* → stg → main) with a hotfix/* lane that bypasses stg in emergencies and auto-opens a backport PR with auto-merge enabled, so a hotfix can never silently regress o...
- ▹Two PR gates. Gate 1 (PR into stg): Vitest plus a smoke Playwright suite (~6 critical specs covering auth, booking wizard, cart, checkout, membership, dashboard) against a fresh local Supaba...
- ▹Vercel previews per branch. dev/* and stg builds deploy to per-branch Vercel preview URLs gated behind Vercel team auth, scoped to the staging Supabase project and Stripe sandbox. Production...
Affiliate Partner & NFC Attribution System
Lustr's growth problem is one every local service business faces: you can't buy Google Ads into profitability on a finite crew calendar. The affiliate system is the answer, a network of partner businesses (gyms, car dealerships, body shops) each holding a branded NFC card that, when tapped or scanned, drops a first-party attribution cookie and routes the customer to self-book. The same infrastructure extends to social media influencers: a unique /r/<code> link works in an Instagram bio just as well as on a physical card. I designed and built the entire system from the DB schema to the partner portal UI.
Skills exercised
Highlights
- ▹Built a full affiliate attribution stack, NFC/QR referral cards, Vercel edge middleware, Stripe webhook stamping, tiered commission engine, and a partner portal, to turn physical business pa...
- ▹Designed the NFC card distribution model: each partner business receives a branded physical card programmed to their unique lustrservices.ca/r/<code> URL. Customers tap or scan at the partne...
- ▹Built Vercel edge middleware for the /r/<code> attribution hop: resolves the referral code via an anon-callable RPC, sets a first-party HttpOnly + readable cookie pair (48h, Secure, SameSite...
- ▹Threaded attribution through the full payment stack: the readable cookie passes affiliate_ref into the checkout body, both checkout edge functions re-validate it server-side, and the Stripe...
Tile-Level ML DSL Compiler
This was a passion project. I'd just built a general-purpose language compiler in my compilers course (CMPUT 415), and I wanted to take that same toolkit (grammar, AST, type checking, and lowering through MLIR/LLVM) into the machine-learning compiler world to understand how systems like Triton and XLA actually work. So I built one end to end, and it's a real pipeline, not a toy. You write a tile-level kernel with a separate schedule block; it parses (ANTLR4), type-checks with clang-style diagnostics, lowers into a custom MLIR dialect, and then splits into two backends off that one dialect: a CPU path that emits real x86-64 AVX2 assembly, and a GPU path that lowers the same source to Ampere tensor-core ops (mma.sync, cp.async, ldmatrix). It's an IR/codegen-level project (I haven't run kernels on hardware or benchmarked them yet), but every stage of the compiler is built and tested, and the two-backends-from-one-dialect design is the part I'm proudest of.
Highlights
- ▹A from-scratch tensor-DSL compiler: an ANTLR4 frontend and a custom MLIR dialect that lower one tile-level kernel language to both x86-64 AVX2 assembly and NVIDIA Ampere tensor-core ops.
- ▹A real language frontend: an ANTLR4 grammar for a tile-level kernel DSL with first-class tile types (shape + layout + memory space), load/store/matmul/elementwise/reduction ops, and a separa...
- ▹A type checker with clang-style diagnostics (`file:line:col: error:`, notes, source-line carets) that catches shape mismatches, dangling iteration-variable references, invalid bind dimension...
- ▹A custom MLIR dialect authored in ODS/TableGen with real op verifiers, the shared middle layer both backends lower from. Getting this dialect right (encoding memory hierarchy, tiling, and sc...
Gazprea was a full-compiler build in CMPUT 415, and we treated it like real engineering, not just coursework. Our team owned parsing, typing, lowering, runtime support, and CI-backed regression testing across a huge suite. We finished first in the course and were invited to present the work in an academic exchange with HSBI in Germany.
Skills exercised
Highlights
- ▹Built a full research-language compiler in a 4-person team: ANTLR4 frontend, rich type system, MLIR pipeline, LLVM backend, and 2k+ tests.
- ▹Nine-pass pipeline: ASTBuilder → ScopeAnalyzer → RoutineRecorder → TypeResolver → QualifierEnforcer → TypeChecker → TypeCastValidator → FinalJudgmentVisitor → CodeGenVisitor. Built on a 342-...
- ▹Polymorphic TypeInfo hierarchy (BasicType, ArrayType, VectorType, TupleType, StructType, IntervalType, TypeAliasRef) with an ArrayBase abstraction that unifies indexing, slicing, concatenati...
- ▹MLIR codegen using six standard dialects (Arith, SCF, Func, MemRef, Math, ControlFlow), lowered through a seven-stage pipeline (FuncToLLVM → SCFToCF → MathToLLVM → ArithToLLVM → MemRefToLLVM...
Language Frontend: Grammar & AST
Everything upstream of semantic analysis. The grammar defines Gazprea's surface syntax across roughly 30 rules, a custom token filter resolves an ambiguity the lexer cannot express on its own, and the AST builder walks the resulting parse tree into a hand-designed node hierarchy that every later pass visits. The design goal was that no pass after this one should ever have to think about parse-tree shape or token positions.
Highlights
- ▹The front half of the compiler: a 341-line ANTLR4 grammar, a custom token stream that fixes a lexing ambiguity without touching the grammar, and a 1,811-line builder that lowers a parse tree...
- ▹Solved a lexing ambiguity in the token stream rather than the grammar. Pre-dot scientific notation (.5E1) cannot be distinguished from a DOT followed by a real literal by the lexer alone, so...
- ▹Kept that fix out of the grammar deliberately: bending the grammar to accommodate it would have made every downstream rule that mentions DOT ambiguous, so the repair happens once at the toke...
- ▹Built the parse tree into a hand-designed AST hierarchy over a visitor interface, so the eight passes that follow all traverse the same node types rather than each re-interpreting ANTLR cont...
Type System & Promotion Rules
Gazprea is a research language whose whole point is rich types: sized vectors and matrices, tuples, structs, intervals, and user-defined aliases, with implicit promotion rules between them. This is the subsystem that decides what every expression's type is and what is allowed to become what. It is the largest piece of the static-analysis half of the compiler and the one where being wrong is quietest, since a bad promotion produces a program that compiles and computes the wrong answer.
Highlights
- ▹A polymorphic TypeInfo hierarchy covering scalars, arrays, vectors, tuples, structs, intervals and aliases, with resolution, promotion, casting and conversion split into their own services a...
- ▹Eight type kinds under one polymorphic base: BasicType for scalars, ArrayType and VectorType, TupleType, StructType, IntervalType, TypeAliasRef for user-defined names, and an explicit Unknow...
- ▹Factored the shape-carrying types behind a shared ShapeProvider interface, so the code that cares about dimensions works against that rather than testing which concrete type it holds.
- ▹Modelled type aliases as a reference node in the hierarchy rather than by eagerly substituting the underlying type, which keeps the user's own name available for diagnostics instead of repor...
Semantic Analysis Pipeline
The middle of the compiler, where a parsed program is proven legal before anything is emitted. Rather than one large semantic-analysis visitor, the work is split into nine passes that each run to completion over the whole tree. Every pass has a single responsibility and can assume the previous ones already succeeded, which is what makes the ordering meaningful instead of incidental.
Highlights
- ▹Nine ordered passes between the AST and code generation, each with one job: scope resolution, routine recording, type resolution, qualifier enforcement, type checking, cast validation, and a...
- ▹Nine passes in a fixed order, each assuming the invariants of the one before: ASTBuilder, ScopeAnalyzer, RoutineRecorder, TypeResolver, QualifierEnforcer, TypeChecker, TypeCastValidator, and...
- ▹Scope resolution owns the symbol table outright: it is the only component permitted to push or pop a scope, and every other pass queries it. Distributed scope mutation is how symbol tables e...
- ▹Maintained two independent scope stacks, one for compile-time resolution and one modelling runtime scope, because the question 'is this name visible here' and the question 'is this storage l...
MLIR Code Generation & LLVM Lowering
Where a verified AST becomes runnable code. Generation targets MLIR rather than LLVM IR directly, using the standard Arith, SCF, Func, MemRef, Math and ControlFlow dialects, then runs a fixed sequence of conversion passes down to the LLVM dialect and out to LLVM IR. The generator itself is deliberately not one visitor: it is a thin dispatcher over nine services that each own one category of emission.
Highlights
- ▹The back half: a 5,166-line code generator split into nine emitter services, targeting six standard MLIR dialects and lowered to LLVM IR through a seven-stage pass pipeline with staged dumps...
- ▹Emits into six standard MLIR dialects (Arith, SCF, Func, MemRef, Math, ControlFlow) rather than hand-rolling LLVM IR, so structured control flow is expressed structurally and lowered by pass...
- ▹Lowers through a seven-stage pipeline, FuncToLLVM, SCFToCF, MathToLLVM, ArithToLLVM, ControlFlowToLLVM, FinalizeMemRefToLLVM, and a reconcile-unrealized-casts pass to clean up the type mater...
- ▹Split emission into nine services by concern: binary operations, loops, calls, subroutines, compound and aggregate values, matrices, casting, and shared utilities. A 5,000-line switch statem...
Compiler Test Infrastructure
A compiler's unit tests tell you very little, because the thing that matters is whether the emitted program produces the right output when it actually runs. Every test here is therefore a full pipeline: source in, compiled to LLVM IR by our compiler, assembled by llc, linked against the runtime library by clang, executed, and its stdout compared to an expected file. Memory correctness is checked in the same run rather than as a separate exercise.
Highlights
- ▹Over 2,100 end-to-end compiler tests, each one compiled, assembled, linked against the runtime, executed and diffed, run under Valgrind in CI on a self-hosted container across five configura...
- ▹Every test exercises the whole toolchain, four external steps per case: our compiler produces LLVM IR, llc produces an object file with position-independent relocation, clang links it agains...
- ▹Runs under Valgrind memcheck in CI on all three suites, so a memory leak or invalid access in the compiler is a test failure rather than something discovered later. For a C++ codebase genera...
- ▹Five configuration profiles for different environments and suites, including a separate Mac profile, so the suite runs on the machines the team actually develops on rather than only in CI.

RISC-V Snake Game
This was my deep dive into low-level systems work at the core of a Computer Architecture course. The capstone was a complete Snake implementation in RISC-V assembly running on RARS MMIO primitives, with keyboard and timer interrupts sharing one trap path, event-driven game-state updates, and rendering optimized to redraw only what changed each tick. It was a practical way to build interrupt handling, MMIO I/O, and state management directly in assembly. There are also a few honorable-mention projects in the full write-up!
Highlights
- ▹Built a full event-driven Snake game in raw RISC-V assembly with MMIO interrupts, custom trap handling, and efficient incremental redraws.
- ▹Built a complete event-driven game loop in raw RISC-V assembly with keyboard and timer interrupts routed through one trap path.
- ▹Implemented incremental redraw logic so each tick updates only changed cells instead of repainting the whole board.
- ▹Wrote collision detection, movement state transitions, apple spawning, and score/timer handling directly over MMIO primitives.

Native Android Application: Event Scheduling
This was a team-built Android app for users, organizers, and admins handling real event workflows from signup to check-in. We built it end to end on Firebase with QR generation and scanning, waitlist lottery logic, role-based routing, and admin tooling.
Highlights
- ▹Built a multi-role Android event platform in Java with QR check-in, lottery selection, and Firebase-backed lifecycle management.
- ▹Built a three-role Android app (users, organizers, admins) with Firebase-backed event flows from signup to check-in.
- ▹Implemented QR-based attendance and waitlist lottery logic with state transitions for invites, enrollment, and organizer controls.
- ▹Added admin cleanup flows that remove related event/user data across Firestore and Firebase Storage.

SFU Research Contribution
BookNook was a research and engineering collaboration with SFU Linguistics, and the software itself was the research output. We built a platform that lets students in multilingual classrooms read the same content in the language they are strongest in, including languages that are usually ignored by edtech tools. I served as product owner across five two-week sprints while also contributing implementation work.
Skills exercised
Highlights
- ▹Shipped a multilingual reading platform with a 7-person SFU team, supporting 200+ languages including low-resource classroom languages.
- ▹The platform itself is the research contribution. Delivered as a seven-person collaborative team effort for the Simon Fraser Dept. Linguistics: scoped, prioritized, and shipped 300+ user sto...
- ▹Architected a FastAPI backend (14,000+ lines Python, SQLAlchemy ORM) with a 5-stage asynchronous PDF processing pipeline (upload, OCR extraction via PyMuPDF, confidence-threshold review gati...
- ▹Built an LLM-powered adaptive quiz system (Groq API) generating questions across 3 Bloom's taxonomy difficulty tiers; enforced quiz eligibility via a state machine gating on reading progress...
