Elan Nash

Software Engineer, Los Angeles, CA

Projects

Graphing Calculator

A C++ graphing calculator that parses typed equations and plots them.

Description

Type an equation like sin(1/x^2) or max(x, sin(x)) and the calculator plots it. A tokenizer splits the input, the Shunting Yard algorithm reorders it into postfix, and a stack-based evaluator computes y for each sampled x. The desktop build supports 28 named functions plus max, min, and pow, and draws 25,000 points per curve with SFML. The web demo compiles the C++ core to WebAssembly with Emscripten and draws 500 points per graph with Chart.js in a React page. The stack, queue, and vector it runs on are hand-written.

Stack

C++, SFML, WebAssembly, React, Chart.js, Shunting Yard

Links

Build notes

  • I gave each token type its own class. Number, Operator, Variable, Function, and SpecialFunction all inherit from Token, and the evaluator switches on type_of() to decide how many values to pop.
  • Plotting is brute force. The desktop build divides the domain into 25,000 even steps, evaluates the postfix queue at each x, and maps each point to the screen with a basis-vector transform. reverse_translate solves the same equation backward to turn a mouse position into graph coordinates.
  • On the desktop, zoom scales the domain and range by 6/5 or 5/6 per scroll step and stops at a width of 20,000. My comment in the code gives the reason: “weird stuff starts happening when the numbers get too big.” Pan moves one tenth of the visible domain per key press, so a press covers the same share of the screen at any zoom.
  • For the web demo I kept the tokenizer, Shunting Yard, and evaluator, dropped SFML, and added nine functions, among them gamma and erf. EMSCRIPTEN_BINDINGS exposes a Plot class to JavaScript, and its generate_points() returns x, y pairs that the React page hands to Chart.js.
  • I capped the web demo at 500 points per graph because point generation runs on one thread. When a pan or zoom ends, the page asks the C++ for 500 new points over a domain 1.5 times the visible width.

Architecture

  equation string, e.g. "sin(1/x^2)"
            |
  Tokenizer    -> Queue<Token*> infix
  ShuntingYard -> Queue<Token*> postfix
  RPN(x)       -> y for each sampled x
            |
      +-----+-------------------------+
      |                               |
  desktop build                  web demo
  SFML loop, 30 fps              C++ -> WebAssembly (Emscripten)
  25,000 points per curve        Plot.generate_points(): 500 points
  translate -> sf::RenderWindow  React page -> Chart.js line
  keyboard / scroll / mouse      chartjs-plugin-zoom: pan, zoom

Relational Database

A small SQL database engine in C++ with its own parser, B+ tree indexes, and binary file storage.

Description

A relational database engine in C++ that takes SQL-style commands: create table, insert into, and select with where clauses. A state-machine parser checks each query against an adjacency matrix and builds a parse tree. Every field gets its own B+ tree index that maps values to record numbers, and rows live in fixed-size binary records on disk. WHERE conditions go through Shunting Yard, and AND and OR become set intersection and union over record numbers. The B+ tree, AVL tree, stack, and queue are written from scratch.

Stack

C++, B+ Tree, Shunting Yard, Binary Storage

Links

Build notes

  • I built the parser as a table-driven state machine. A static int matrix has one row per state and one column per keyword, and the first column marks success states. A query is valid when the walk ends on one.
  • Every field gets its own B+ tree multimap from value to record numbers. Field names live in an AVL tree.
  • Rows are fixed-size records of 100 fields at 100 bytes each, so record n starts at n times the record size. A read seeks straight there.
  • Each comparison in a WHERE clause returns a list of record numbers. AND is set_intersection and OR is set_union. Range operators walk the multimap from lower_bound or upper_bound instead of scanning every row.
  • Every value is a string, so Age < 30 compares lexicographically. I say so up front in the README, and typed columns are the first item on its TODO list.

Architecture

       user command, or a batch .txt file -> SQL
                  /     \
          Parser           Table ("Student Table")
   tokenize                  field names:  AVL tree
   state matrix check        index/field:  B+ tree multimap, value -> recnos
   parse tree (MMap)         rows:         fixed-size records in a .bin file
                  \     /
   where -> Shunting Yard -> postfix -> RPN over the indexes
   comparison -> recno list;  AND = intersection,  OR = union
                     |
          result Table -> printed

not'd

The Postgres and Edge Function backend of not'd, a music-logging mobile app.

Description

The backend of not'd, a music-logging mobile app in development. In the Postgres schema, row-level-security policies decide who may read each row, and PL/pgSQL RPCs run writes that touch several tables inside one transaction. A Deno Edge Function proxies Apple Music and signs its ES256 tokens on the server, so the key never ships in the app. Consent is an append-only log, and a trigger locks the age-gate answer once it is set. Tests mock the network with MSW and check that optimistic updates roll back.

Stack

PostgreSQL, PL/pgSQL, Supabase, Deno, TypeScript, React Native

Build notes

  • I route reads that cross accounts through SECURITY DEFINER functions with an empty search_path. Each one checks the caller’s relationship to the account before it returns a row.
  • I page through a profile with a composite cursor of logged_at and log id, because a timestamp alone skipped or repeated rows when two logs shared a time. DISTINCT ON then keeps one row per album.
  • Reordering or removing items used to take several client requests, and a failure partway through left positions out of order. I replaced each with one PL/pgSQL function that checks ownership and every id, then writes inside a single transaction.
  • Consent rows go in only through RPCs, which read the policy version and timestamp on the server so the client cannot forge them. A per-user advisory lock stops two identical calls from appending duplicate rows.
  • The Edge Function signs its Apple Music JWT with Web Crypto, caches it in module memory, and refreshes it a minute before the one-hour expiry. On a 401 it clears the cache and retries once.

Architecture

            React Native app (TypeScript)
             |                         |
   supabase-js + user JWT        HTTPS + user JWT
             v                         v
   Postgres on Supabase          Deno Edge Function
     RLS: who reads each row       verify the user
     PL/pgSQL RPCs:                per-user rate limit
       atomic writes, cursors      cached ES256 token
     consent log: append-only            |
     age-gate trigger                    v
                                   Apple Music API

Job Matching Pipeline and CareerHub

A three-stage job-matching pipeline on Cloud Run, and CareerHub, the app where members review their matches.

Description

Built at GHN Career Academy. The pipeline runs as three stages on Cloud Run. Ingest pulls job listings for each member. Enrich turns a member’s intake answers into a structured profile with GPT-4o. Score runs each job through a cascade of hard filters, cheapest check first, and sends the survivors to GPT-4o-mini. CareerHub is the Next.js 15 app where members review those matches, mark roles Interested or Not a Fit, and apply on the employer’s site. It runs on the Edge Runtime with JWT auth and per-member rate limiting.

Stack

Python, Google Cloud Run, OpenAI API, Next.js 15, Edge Runtime, Playwright

Build notes

  • The hard filters run in a fixed order, and a job stops at the first one it fails. I put seniority first because it is a string lookup, so the costlier checks see fewer jobs.
  • If location is the only filter a job fails, a GPT-4o-mini metro classification gives it a second look before the pipeline drops it.
  • Pairs that pass the filters still need an embedding similarity above a threshold before GPT-4o-mini scores them.
  • CareerHub members arrive through a signed link. Middleware moves the token into an HttpOnly cookie and redirects to a clean URL, and the API routes accept only the cookie.
  • I run CareerHub’s Playwright suite against a production build with outbound network denied. A scanner fails the gate if any server-only variable name or secret-shaped value appears in the client bundle.

Architecture

  Cloud Scheduler -> HTTP trigger per stage
     |
  [1 ingest]  per-member search queries -> job API -> dedup
     |
  [2 enrich]  intake + résumé -> GPT-4o -> validated profile
     |
  [3 score]   new pairs -> hard filters, first failure exits
              -> embedding threshold -> GPT-4o-mini -> match store
     |
  CareerHub (Next.js 15, Edge): signed link -> HttpOnly cookie
     member: Interested / Not a Fit -> apply on employer site

About

Innie

Outie

Résumé

Elan Nash

Software Engineer, Los Angeles, CA

elanmnash@gmail.com | linkedin.com/in/elannash

github.com/elannash | elannash.com

Retrieve personnel file (PDF)

SUMMARY

Software engineer building member-facing web apps, Python backends, and AI-powered job-matching tools. Replaced spreadsheet workflows with member-facing job approval and automated resume generation.

SKILLS

Languages
Python, TypeScript/JavaScript, SQL, C++
Backend & APIs
FastAPI (async, streaming), Pydantic, SQLAlchemy, Alembic, REST APIs, JWT auth, Node.js, Next.js Edge Runtime
Frontend
React, Next.js, React Native (Expo), Zustand, React Query, TanStack Router, Tailwind
Databases & Data
PostgreSQL (RLS, RPCs, triggers, trigram similarity), Supabase, Airtable
Cloud & Testing
Docker, Google Cloud Run, Cloud Scheduler, Render, Vercel, GitHub Actions, pytest, Jest, Vitest, Playwright, Maestro
AI / LLM
Anthropic API (Managed Agents, custom tools), OpenAI API (embeddings, structured outputs), LiteLLM, source checks, per-run cost tracking and session budgets. Daily Claude Code and Codex with custom skills and CI gates

EXPERIENCE

GHN Career Academy – Software Engineer

Apr 2024–Present

Online career-coaching academy. First engineer, initially solo, now on a small team under a CTO. About 150 members.

Technologies: Python, FastAPI, PostgreSQL, Next.js, React, Google Cloud Run, Docker, Anthropic API, OpenAI API

NXTMode – Full-Stack Developer (Capstone)

Aug 2024–Dec 2024

Technologies: React, Node.js, Express, TypeScript, MongoDB, Firebase

TECHNICAL PROJECTS

not'd – Social Album-Logging Mobile App (Full-Stack Focus)

Technologies: React Native, Expo, TypeScript, PostgreSQL, Supabase, Edge Functions (Deno), React Query, Zustand, Jest, Maestro

Custom Relational Database Engine

Technologies: C++, SQL Parser, B+ Trees, Binary-File Storage

ADDITIONAL EXPERIENCE

Pasadena City College – Teaching Assistant

Jan 2022–May 2022

EDUCATION

University of Southern California – B.S. Computer Science

Graduated Dec 2024

Pasadena City College – A.S. Engineering and Technology

May 2022

Contact