I found your job with software I wrote.

You are probably here because I applied to one of your postings. It did not reach me through a job board or a recruiter — it came out of an index of the job market that I built and run myself.

mike@forn.al · Marlborough, Massachusetts · forward deployed / applied AI engineer

The index rebuilt 2026-08-13

Postings collected, then resolved to distinct jobs
collected
4,542,649
distinct
2,193,724

Slightly more than half of what I collect is the same job posted to several boards at once. Collapsing those into one record — and giving it a key that survives the next rebuild — is most of the work. It is string comparison, not similarity: the key is parsed out of the apply URL, so the same posting keeps the same identity every time.

Job boards found, by vendor · 39,041 across 25 vendors
Greenhouse
8,441
Personio
6,352
Welcome to the Jungle
4,647
Y Combinator
4,260
Ashby
3,659
Lever
2,847
Rippling
2,308
Workday
1,570
Notion
970
Getro
838
ADP
825
iCIMS
509

13 more vendors · 1,815 boards

Six of these vendors publish no documentation and no list of the companies using them. There is no directory to download, so the boards have to be found: enumerated out of archived URLs, mined from the apply links inside postings already collected, and probed against endpoints their own interfaces never expose in bulk.

Reading a board is the easy half. Knowing which boards are still alive is the hard half.

GET https://acme.jobs.personio.de/search.json 307 → https://personio.com 429 Too Many Requests read as: upstream is throttling us, back off and retry actually: this tenant was retired. the 429 is the marketing site, not the vendor. we backed off forever.

A retired tenant does not answer 404. Three of my crawlers read that redirect as polite backpressure and throttled themselves into the ground — nothing errored, nothing alerted, the counts just quietly stopped growing. Teaching them to tell a dead tenant from a busy one took one pipeline from 68 hours to 14 minutes.

A number on my résumé is wrong found 2026-08-14

It says 227 Supabase edge functions. It is 225 — the other two are _shared and a node_modules directory, and neither deploys. I had published the method next to the number, which is the only reason it was findable.

ls supabase/functions | wc -l228
find supabase/functions -maxdepth 1 -mindepth 1 -type d | wc -l227
find supabase/functions -maxdepth 2 -mindepth 2 -name index.ts | wc -l225

The arithmetic was fine; the method was wrong, and a wrong method reports a clean result forever. Every number on this page is produced by a command, and the command is printed with it.

What else I build

teeprompt

An AI-native commerce platform, built and operated alone: a customer types a prompt, a multi-model pipeline produces a print-ready asset, Stripe takes the payment, Printful prints and ships, a Stripe Connect payout goes to the creator. Two storefronts on one backend, launched 34 days apart — gp-tee.com and gpett.com, both answering 200 when I checked them on 2026-08-14.

edge functions, deployable225
database migrations207
React components579
commits on main2,835

Two of the four bugs I am proudest of finding are on that payment path. One was six weeks of successful payments writing zero orders, behind a 200 on every delivery. The other was row-level security that was switched on and inert, because auth.uid() returns null under a third-party token.

The honest limit: the constraint turned out to be demand, not engineering. I proved the build and under-invested in distribution.

Experience

Solo Engineer — GPTee / GPett2026 – Present
US Sales & Business Development — Bridge Fund Finance2025 – 2026

First US commercial hire at a UK-founded fund finance marketplace, between a UK engineering team and US institutional buyers.

Blockchain Capital Markets Consultant — Capgemini2022 – 2024

Technical due diligence and solution design on tokenized private markets for global banks and asset managers.

Data Science Intern — Lyndra Therapeutics2020 – 2021