Lucas Gold

AI Engineer · Toronto, ON

Software developer who builds production LLM systems and the products around them. Five years shipping to real users across mobile, web and backend; now building extraction and retrieval systems in daily use, plus a fully on-device AI assistant for macOS.

Experience

Software Developer, AI & Automation

March 2025 – Present

Above Ground Art Supplies — Independent art-supply retailer, two Toronto locations · Toronto, ON

Built a production invoice extraction pipeline pairing LLM extraction with deterministic pdfplumber parsing, layered behind a second model pass, independent re-parsing, and line-item and quantity sum checks — 94% of invoices from unseen vendor layouts come out fully correct, 97% from known ones, with 3.5% of line items escalated for human review.

Vendor invoices arrive as PDFs in well over a hundred different layouts, and the conventional approach — a parser per vendor — does not survive a supplier changing their template. The pipeline splits the problem instead. The model reads the layout and decides what each region means; deterministic pdfplumber extraction reads the actual numbers. Only one of the two is allowed to improvise, which keeps line-item arithmetic exact while still generalising to layouts never seen before. A verification pass re-checks its own output and escalates anything it is unsure about to a person rather than guessing, so the failure mode is a flagged field rather than a wrong number entering the books. That gate fires on about 3.5% of line items — enough review to catch the genuinely ambiguous cases, little enough that the tool replaces the work rather than relocating it. Accuracy is measured per whole invoice rather than per field — every figure on the document has to be right for it to count — and on that basis 94% of invoices from vendor layouts the system has never seen come out fully correct, against 97% from layouts it has. The gap between those two is the honest cost of generalising rather than templating. Whole-invoice correctness is the demanding way to measure it, and it is the one that matches what finance actually needs: a document they do not have to re-check. Anything that does pass carries several nets beneath it — a second model pass re-reads the extraction, deterministic parsing re-derives the numbers independently of the model, line-item amounts are summed against the invoice total and quantities against their own subtotals, and each line's printed amount is captured separately so the arithmetic can be checked against the document rather than against anyone's reading of it. Corrections made during review are captured and fed back so the same ambiguity is handled better next time, which is what makes the human step an investment rather than a tax. It was developed and validated against roughly 80 vendor formats and has since processed around 130 — the gap between those two figures is the evidence that the approach generalises.

Cut invoice processing from over an hour each to near-instant, reclaiming roughly 40 hours of manual work a month for the purchasing and finance team that now uses the tool daily.

The tool replaced a fully manual workflow. It is not a prototype that was demoed once — purchasing and finance run it as part of their normal month, which means it has had to survive malformed PDFs, suppliers changing templates, and users who do not read error messages.

Built a retrieval-augmented knowledge base into the company React app, combining vector similarity with keyword search over Postgres and pgvector — answers cite the documents they came from, 92% recall@5 against a query set drawn from real staff questions, used daily by 30+ staff.

Hybrid retrieval, built directly rather than through a framework. Vector similarity catches paraphrase and intent; keyword matching catches the exact product codes and brand names that embeddings reliably blur together. A retail catalogue is close to a worst case for pure semantic search — many near-identical SKUs differing by a single digit — which is what made the hybrid necessary rather than fashionable. Documents and embeddings live in Postgres with pgvector, and the two scores are normalised and combined as a weighted sum, with the weighting tuned against a query set built from the questions staff had actually asked it — the history is kept, so the evaluation set grows out of use rather than being written once and left to age — supplemented with synthesised variants to cover phrasings the real sample missed. Three kinds of source answer the same question — vendor documentation, the internal catalogue, and the store's own training and policy material — and retrieval spans all of them rather than leaving each in a silo. Every answer shows the sources behind it, down to the page range of a vendor guide or the numbered clause of a returns policy, with the date each internal document was last updated, because an assistant a shop-floor employee is about to repeat to a customer has to be checkable rather than merely confident. Measured against that set, the right product comes back first 84% of the time, is in the top five 92% of the time, and in the top ten 96% — the shape of that curve is what told us the weighting was tuned rather than merely plausible. It runs against the live inventory catalogue, so answers reflect what is in stock rather than a stale snapshot.

Replaced the company's Mailchimp subscription with an in-house campaign system on SendGrid, adding queued delivery, targeting from internal customer data, and a monitoring dashboard built around the metrics the business actually acts on.

A build-versus-buy decision that went the build way for a specific reason: the off-the-shelf product could report on a campaign, but it could not join campaign performance to the company's own inventory and customer data, and it could not be automated against internal events. Moving delivery to SendGrid and owning the layer above it meant campaign monitoring, segmentation and scheduling could be shaped around how the business runs rather than around a vendor's dashboard — at a lower recurring cost.

Shipped React internal tools for purchasing and finance: quote procurement that prices requested-product lists against prior-year margins, and payroll reconciliation that flags anomalies for review.

Two systems in the same internal React app, each replacing a spreadsheet-and-judgement process. The payroll reconciliation deliberately flags for human review rather than auto-correcting — surfacing anomalies to a person is the right design when the failure mode is someone's pay.

Packaged the extraction pipeline as a desktop client with multi-threaded processing, progress tracking, and CSV export, so finance staff run it without involving IT.

Multi-threaded processing keeps the interface responsive on large or malformed batches, and failures surface per-invoice rather than aborting the whole run.

Software Developer

August 2021 – February 2025

NextGen Kitchens — White-label restaurant commerce platform; 20+ restaurant brands · Vancouver, BC (Remote)

Built the initial MVP of a white-label restaurant commerce platform and grew it to production for 20+ restaurant brands across iOS, Android, web, in-store kiosk, and POS from a single React Native and React codebase on Node.js and GCP.

White-label means every restaurant gets an app that looks like theirs, out of one codebase — so branding, theming and feature availability had to be configuration rather than forks. The five surfaces share everything except where they genuinely differ: kiosk and web variants are platform-specific files resolved at build time, so a kiosk screen that needs a number pad and a larger pickup selector gets one without a second copy of the app to maintain. Redux Toolkit with persistence holds cart and session state identically across all of them. Taken from nothing to production over roughly four years, including loyalty, rewards, gift cards, referrals and QR-based in-store loyalty.

Co-planned and drove a second-generation rebuild of the platform backend with one other engineer — a consolidated order pipeline with explicit fee and disbursement handling, and every third-party integration reimplemented against it.

Four years of growth had left order handling spread across provider-specific paths that each knew a little too much about the others. The rebuild put a single order module at the centre — order creation, fee and disbursement calculation, status, payment — and reimplemented Deliverect, Square, Stripe, DoorDash and the notification layer against that interface instead of against each other. It shipped as a parallel run rather than a cutover: both generations stood up side by side, new data routed to the second while the first kept serving, restaurants moved across one at a time, and their history followed behind through a conversion script. A live platform taking real orders for real restaurants never had a flag day. Two of us planned the architecture; I drove the migration.

Shipped multi-provider payments across Stripe and Square — including card-present flows on Stripe Terminal and Square hardware, Apple Pay and Google Pay — with automated multi-restaurant payout splitting through Stripe Connect.

A single order can contain items from separate restaurant brands, each of which needs paying separately and correctly. Stripe Connect handles the split automatically at the moment of capture, which removed a manual reconciliation step that stops scaling somewhere around the third restaurant. Card-present transactions on Stripe Terminal and Square terminal hardware run through the same order pipeline as card-not-present payments on web and mobile, so the two paths cannot drift apart.

Built a custom DoorDash Drive integration giving every restaurant on-demand delivery — JWT-signed API auth, store provisioning, live delivery quoting at checkout, and status webhooks driving customer updates — plus Twilio and SendGrid notifications and Bluetooth receipt printing to Star and Epson hardware.

Delivery was built rather than bought: restaurants were provisioned as DoorDash stores programmatically, a quote was fetched live during checkout so the customer saw a real delivery fee before paying, the order was dispatched to a Drive courier on payment, and status webhooks fed customer-facing tracking plus the text and email updates. It went through DoorDash's own partner approval rather than being a matter of reading public docs.

Built bidirectional menu and order integrations reaching 40+ POS systems, implementing both sides of the Deliverect API — outbound as a sales channel and inbound as a POS — plus a direct Square integration, so orders flowed in from Uber Eats and DoorDash and out from the platform's own apps and kiosks.

Menus live in the POS and orders have to arrive there; both sides change independently and neither can be trusted to be authoritative about the other. This ran in both directions, and that is the part that mattered commercially. Outbound, an order placed in a restaurant's own app or on its in-store kiosk was pushed into that restaurant's POS as if it had been rung in at the counter. Inbound, an order placed anywhere else — the restaurant's own POS, Uber Eats, DoorDash — came back into the platform's order management dashboard, so a restaurant had one accurate picture of its revenue across every channel instead of reconciling four reports by hand at month end. Making the inbound half work meant implementing the POS side of Deliverect's API, not just the channel side: registering the platform as a point of sale, receiving and acknowledging orders, pushing catalogue changes back, and handling snooze and busy-mode state so an out-of-stock item disappeared everywhere at once. It was a custom integration built in direct contact with Deliverect's own team rather than from public documentation. Square, the most common POS among the platform's restaurants, was integrated directly — OAuth per restaurant, catalogue import and sync, order push, and Square Loyalty — for tighter control than a hub could give.

Built the order management dashboard restaurants ran on, consolidating orders from every channel into one view with the fee and disbursement calculation feeding accurate per-restaurant invoicing and reporting.

Once orders arrived from the platform's apps, in-store kiosks, the restaurant's own POS and third-party marketplaces, they needed one place to live. The dashboard was that place: live order state across every channel, with the fee and disbursement arithmetic deciding what each restaurant was actually owed on each order — which is what made invoicing and end-of-month reporting correct without anyone reconciling by hand.

Built an in-house POS surface with Stripe Terminal card-present payments, so restaurants without an existing POS could run the whole operation on the platform.

Integrating with a restaurant's existing POS covers most cases, but not the ones who have not bought one. The first-party POS closed that gap: order entry, a Stripe pinpad for card-present payments, and a Stripe account per restaurant to collect into — the same order pipeline as every other surface, so nothing had to be reconciled between them.

Gathered requirements directly from restaurant owners and shipped growth features — loyalty rewards, referrals, promo codes, deep linking — as one of 2-3 engineers, mentoring 4 interns through code review.

A team of two to three paid engineers meant owning a feature from the conversation with the restaurant owner through to the post-launch support call. The intern mentoring ran through code review rather than formal supervision.

Migrated the codebase to TypeScript, cut cold-start time and bundle size by enabling Hermes and lazy-loading data, and raised reliability through Jest coverage, Crashlytics monitoring, and on-call ownership of production incidents.

A growing React Native codebase across five surfaces reached the point where JavaScript's looseness was costing more than it saved, and the migration ran incrementally alongside feature work rather than as a freeze. Start-up cost came down by moving to the Hermes engine and by loading data lazily rather than up front, and the same pass broke large modules into smaller focused ones — which mattered less for the bundle than for how quickly anyone could find and change things afterwards.

Owned the mobile release cycle: App Store and Google Play submissions, TestFlight betas, and Expo OTA updates that delivered fixes to users the same day without waiting on store review.

Shipping to two app stores plus web plus kiosk hardware means release is its own discipline. OTA updates through Expo made the difference between a same-day fix and a three-day review queue.

Selected work

Fennel

2026

On-device AI voice companion for macOS

A fully on-device AI assistant — native SwiftUI app plus a Python/MLX backend bundled into one self-contained macOS app — so no model, audio, or user data leaves the machine.

Two processes with a clean split of responsibility: a native SwiftUI app owns audio capture, echo cancellation, playback and all UI, while a Python backend owns the machine learning, the two talking over a local WebSocket. Audio crosses that boundary as raw frames — 16 kHz int16 in, 24 kHz PCM out — and every control frame is a documented message shape rather than an ad-hoc payload. The voice loop runs Silero VAD for endpointing, Whisper for recognition, streaming LLM inference with prefix-cache reuse, and Kokoro synthesis speaking the reply as it generates, with barge-in interruption so it can be cut off mid-sentence. Memory persists across sessions in SQLite, retrieved by FTS5 full-text search combined with an embedding index written from scratch against MLX, and condensed by rolling summaries so context does not grow without bound. Fourteen tools extend the model into the rest of the machine: reminders and calendar events written through EventKit into Apple's own apps, macOS Shortcuts, web search, and on-device image generation that temporarily unloads the language model when memory is tight. The whole thing ships as one self-contained app with the Python runtime inside the bundle, so opening it is the entire install; models download on first use, after asking.

Model support is gated by an automated evaluation harness rather than by hand: a candidate MLX model has to load, hold a conversation and correctly render the tool definitions before it is added to the supported list. Anything from Qwen3 1.7B up to Hermes 4 14B qualifies that way, or any MLX repo from Hugging Face.

White-Label Restaurant Commerce Platform

2021-2025

iOS, Android, web, kiosk and in-store POS

White-label ordering platform sold to 20+ restaurant brands as a branded iOS, Android, web, kiosk and in-store POS product, from a single codebase.

Five surfaces from one React Native and React codebase, with kiosk and web differences handled as platform-specific files resolved at build time rather than as separate apps. Orders move in both directions: out to a restaurant's POS from the platform's own apps and kiosks, and back in from the restaurant's POS, Uber Eats and DoorDash, so every channel lands in one order management dashboard with the fee and disbursement arithmetic behind accurate invoicing. Payments run multi-provider with automatic multi-party payout splitting; delivery runs on a custom DoorDash Drive integration. See the experience section for the engineering detail.

AI Invoice Extraction

2025

LLM extraction with deterministic verification, in daily production use

Production extraction pipeline handling 130+ vendor invoice layouts with no per-vendor templates — 94% of invoices from unseen layouts extracted fully correct, 97% from known ones, 3.5% of line items escalated for review.

The design decision worth the page: the model reads the layout, the deterministic parser reads the numbers, and only one of them is allowed to improvise. A verification pass then re-checks the output and escalates low-confidence fields to a person instead of guessing. Developed against roughly 80 vendor formats; around 130 have passed through it in production.

Inventory Knowledge Base

2025

Cited hybrid retrieval over product data, policies and procedures

Hybrid retrieval over the live inventory catalogue and store documentation — vector similarity combined with keyword search over Postgres and pgvector, every answer citing the documents it came from, 92% recall@5 and used daily by 30+ staff.

A retail catalogue is close to a worst case for pure semantic search: hundreds of near-identical SKUs separated by a single digit or one word of finish, where an embedding model will cheerfully return the 300-series when you asked for the 500. Keyword matching catches those exact codes and brand names; vector similarity catches the customer who describes what they want rather than naming it. Neither alone is good enough, which is what made the hybrid necessary rather than fashionable. Embeddings and documents live in Postgres with pgvector, the two scores are normalised and combined as a weighted sum, and the weighting was tuned against a query set built from the questions staff had actually asked it, kept as they came in and supplemented with synthesised variants to cover phrasings the real sample missed — so the evaluation set grows out of the product rather than being written once and left to age. Every answer shows the documents behind it — vendor product guides down to the page range, the internal catalogue with its last-updated date, the staff training guides — because an assistant a shop-floor employee is about to repeat to a customer has to be checkable, not just confident. Policy answers quote the clause verbatim and link the full document. Three different kinds of source answer the same question — vendor documentation, the internal catalogue, and the store's own training material — and retrieval spans all of them rather than leaving each in its own silo. It covers store policies and returns, procedures, inventory and stock, vendors and brands, and training material as well as products, scoped to the location the person is working at, browsable by category or asked in plain language with follow-ups in the same thread.

Harvest Rush

2025-2026

Real-time multiplayer arena game

Server-authoritative multiplayer architecture in Node.js: the server owns all game state at a fixed tick rate and clients send input intent only, making client-side cheating impossible.

The server simulates every lobby on a 60ms tick and broadcasts the result; clients send only a movement direction and whether they are firing, and render what comes back. Movement, collisions, seed flight, hit resolution and pickups are decided server-side exclusively, which is what keeps the game fair once strangers are playing each other for score — peer-to-peer would have made that either laggy or trivially exploitable. Bandwidth is kept down by sending what actually changes: player and projectile positions every tick, but crops and power-ups only as add and remove events, since a crop that has not moved is not worth re-sending. A room manager caps lobbies at 40 real players and spins up new ones as they fill, with bots topping each lobby up so it never feels empty. Client-side interpolation runs decoupled from the tick so motion stays smooth at 60fps, and spatial-grid indexing reduces O(n²) proximity checks to near-constant time. Load-tested to 160 concurrent players across lobbies on a single small VM, for a few dollars a month.

Interactive 3D Portfolio

2026

The site you are looking at

A playable Sims-style house where every portfolio section is something you walk up to and use, built with no framework and no bundler.

Every prop in the lot is assembled at runtime from boxes, cylinders and lathes rather than loaded as a model, so the whole world costs two small textures and no mesh downloads. Walking is a breadth-first search across a 0.3-unit grid, smoothed by dropping any waypoint the walker can already see past. Characters are one rig driven by a gait function — hips, knees and ankles from a single stride phase, with the pelvis dropping onto the loaded leg and the shoulders counter-rotating. Nothing is streamed: the background score is built from a chord progression, a bassline and a written melody scheduled with a light swing, and every effect is a Web Audio graph assembled note by note. Plain ES modules, no framework and no bundler — a thirty-line build script copies and measures the output, and the parts that can run without a browser are covered by tests in node:test.

Custom Search Engine

2020

Crawler, index and ranked retrieval, from scratch

Built a crawler and search engine on Apache Nutch and MongoDB, ranking articles by query relevance with weighted scoring, queried through a Java desktop client.

Apache Nutch crawls and fetches, the documents land in MongoDB, and a scoring function decides what comes back first — weighting matches differently depending on where in a document they appear, because a term in a headline means something different from the same term buried in the ninth paragraph. A Java desktop client runs the queries and shows the ranked results. It is a student-era project and it looks like one, but it is on this page deliberately: the questions it forced — how do you index a corpus, how do you decide what relevance means, how do you know the ranking is any good — are the same ones behind the hybrid retrieval work six years later, and the embedding index written from scratch in Fennel after that. The tools changed completely. The problem did not.

Technical skills

LanguagesTypeScript · JavaScript · Python · SQL · Swift
AI & LLMLLM APIs (OpenAI, Anthropic) · RAG · hybrid retrieval · vector search · pgvector · embeddings · LLM tool calling · structured outputs · Whisper · MLX
FrontendReact · Next.js · React Native · Expo · Zustand · HTML5/CSS3
BackendNode.js · FastAPI · REST API design · WebSockets · GCP Cloud Functions
Data & CloudPostgreSQL · Firestore · SQLite · MySQL · GCP · Firebase · Fly.io · Docker
PracticeGit · CI/CD · Jest · Crashlytics · on-call incident response
IntegrationsStripe (Connect, Terminal) · Square (Payments, Terminal) · Apple Pay · Google Pay · Twilio · SendGrid · DoorDash Drive · Deliverect

Education

Bachelor of Science, Computer Science

June 2020

Toronto Metropolitan University (formerly Ryerson) · Toronto, ON — Distinction · Dean's List 2019 & 2020 · GPA 3.6/4.0