Hustler Engine
Contract — Full-Stack Engineer Aug 2022 — Apr 2023 hustlerengine.com

Hustler Engine

AI-assisted brand discovery and cold outreach with the entire pipeline running on the device in your pocket — in 2022.

SwiftUI · Combine OpenAI Next.js Node.js PostgreSQL MailCore2 · SMTP/IMAP Core Data Firebase

Built across three runtimes at once — an iOS and macOS client, a Next.js web surface and a Node backend — with a lead pipeline that fuses six data sources and three separate model passes into a single record, all orchestrated on the device.

18KLines of Swift
123Files, layered MVVM
8Enrichment passes
100Beta users
01

Doing AI product work before it was a category

Hustler Engine was a lead-generation and cold-outreach platform for people looking for brand partnerships — and its interesting property is the date. This was built through 2022 and early 2023, when using a language model as a structured extractor and a scorer rather than a chat box was not yet the obvious move.

The client was iOS and macOS in SwiftUI with Combine, roughly 18,000 lines across 123 files in layered MVVM. Behind it, a Next.js web surface and a Node.js backend — REST API design, JWT auth, the PostgreSQL schema, and the model-driven email personalisation.

Locations · Minsk, Michigan City Industries · Advertising, Marketing Revenue · $1M–$10M Monthly visitors · under-10k Employees · 50-200
Generate Visibility-based brand generation
deep search
SpurIT
spur-i-t.com · Minsk
Sorted industries advertising, apps +29  ·  revenue under $1M  ·  monthly vis. under 10k  ·  employees 50-200
Rubyroid Labs
rubyroidlabs.com · Minsk
Sorted industries advertising, back-end  ·  revenue $1M–$10M  ·  monthly vis. under 10k  ·  employees 10-50
Лайм медиа
lmedia.by · Minsk
Sorted industries advertising, communicat…  ·  revenue under $1M  ·  monthly vis. under 10k  ·  employees 1-10
Returned
12 brands
Fields per brand
24
Source
Companies API + Places

02 — Discovery

Five filters, twenty-four fields back.

The generate screen is a filter set over a company database — locations, industries, revenue band, monthly visitor band and headcount band, the last three as fixed enums (under-10k, $1M–$10M, 50-200) rather than free numbers, because that is how the source data is bucketed.

Each result comes back as a full record: domain, city and country, industry list and primary industry, revenue, monthly visitors, headcount, social profiles, technologies, year founded, phone. Everything the outreach step later needs to write a sentence that sounds like it was written by someone who looked.

  • Five filter dimensions, three of them bucketed enums
  • One record carries 24 fields — not just a name and a domain
  • Social profiles resolved so the brand can be verified, not guessed
  • Results sortable and selectable before anything is written
Storage Engine is generating personalized e-mails
running
38% Emails generated: 22 out of total 57
Metric Media Solutions
drafted from description + rating + followers
Ready
Conquer Agency
queued — throttled to one call per second
Writing
Throttle
1 req / s
Cached
Core Data
Per brand
one draft

03 — Generation

Fifty-seven drafts, one at a time.

Once brands are selected, the engine writes a personalised email for each one from what enrichment found — the description, the Google rating and review count, the Instagram following — measured against the user’s own company profile.

The rate limit is the interesting part. Model calls had to be throttled to roughly one per second, and the codebase ended up with three separate limiters built on three different primitives — a reactive one on a DispatchQueue, a thread-safe one using NSLock for an atomic test-and-set, and a blocking one on a DispatchSemaphore.

  • Progress is per-brand and resumable, not a spinner
  • Drafts cached in Core Data so a re-open costs nothing
  • Three interchangeable throttles, one per concurrency primitive
  • Fit scoring and copy come from separate passes
Outreach MailCore2 on device
no mail server
partnerships@brand.com
picked first — ranked above info@ and hello@
Primary
info@brand.com
generic inbox — ranked lower
Fallback
IMAP — inbox & sent
UID-based, sorted by received date
Synced
SMTP — HTML + inline signature
remote image downloaded, attached inline
Sent
Prefix rules
22
Protocols
SMTP + IMAP
Credentials
user’s own

04 — Outreach

A mail client inside the app.

There is no sending service behind this. The app holds the user’s own SMTP and IMAP credentials and talks to their mailbox directly through MailCore2 — fetching inbox and sent mail by UID, and sending plain, HTML, attachment and inline-signature variants, including downloading a remote signature image and attaching it properly.

And a small piece of judgement that mattered more than it looks: when scraping turns up several addresses for one company, a 22-prefix ranking decides which one a human should actually receive it at.

  • User’s own mailbox — no sending infrastructure to run
  • IMAP inbox and sent sync, UID-based
  • Four send paths including true inline signatures
  • 22-prefix heuristic picks the right recipient
05

Three rate limiters, on purpose

Model calls had to be throttled, and the codebase ended up with three different limiters built on three different concurrency primitives — one reactive on a DispatchQueue with a subject, one thread-safe with NSLock doing an atomic test-and-set, and one blocking on a DispatchSemaphore.

Underneath sits a generic Combine networking layer: publisher-returning requests, a custom operator for response validation, typed error mapping that separates unauthorised from server from decoding failures, and connection pooling tuned per endpoint — the email-search path gets a much higher concurrent limit than the rest.

06

Stack

Client

  • SwiftUI · UIKit bridges
  • Combine
  • Layered MVVM
  • Core Data
  • Firebase Auth · Firestore

Web & API

  • Next.js
  • Node.js
  • REST architecture
  • JWT auth
  • PostgreSQL

AI & data

  • OpenAI API
  • Structured JSON extraction
  • Google Places · Photos
  • Instagram profile data

Mail

  • MailCore2
  • SMTP · IMAP
  • Template engine
  • Inline signatures
07

Outcome

Ran with 100 beta users. More importantly it is the direct ancestor of Rawly — the same problem (turn a sales motion into software) attacked three years earlier with hand-rolled concurrency instead of a queue, and on a phone instead of a worker fleet.

Same problem, three years earlier, one toolchain harder.