Soltreya · System Architecture

A production system that finds its own leads.

Soltreya sources manufacturers, drafts outreach in my voice, runs the live quality product, and keeps itself running across 17 background jobs behind a four-gate security model. Built and operated end to end by one engineer.

3
core systems
17
background jobs
4
security gates
10
system diagrams
1
engineer
Part One

The plain-English tour

How the whole thing fits together, no jargon. Good for anyone evaluating what I've built.

Think of Soltreya as a small business with three working parts and a brain. Everything writes to one shared database, and I'm always the human in the loop. Nothing important goes out without approval.

01

The big picture

click any box
The strategy brain
Decides who to sell to and why: small auto-parts factories
A written plan that defines exactly which factories to target and why, so the Lead Engine aims at the right kind of company instead of wasting effort.
aims the engine
Public website
soltreya.com, where visitors book a call
soltreya.com, where prospects learn what Soltreya does and book a discovery call. Those bookings flow into the Lead Engine.
1 · Find leads
Lead Engine finds factories and drafts intros; Nick approves and sends
Software that discovers qualified factories, drafts a personal intro email for each, and queues it for Nick to approve before anything sends.
2 · The product
Quality Hub (soltreya.com/hub), the customer-facing product
The Quality Hub product, live at soltreya.com/hub. Users record quality problems and the system helps assign, fix, and document each one before the deadline.
3 · Behind the scenes
17 scheduled jobs keep all three parts fed and fresh
Seventeen jobs that run on timers, refreshing the website, sending reminders, and pulling in new leads, so the business keeps moving without anyone clicking a button.
everything writes to
One shared database
Supabase: leads, emails, customers, quality events, all in sync
A single secure database (Supabase) storing everything (leads, emails, customers, quality events) so every part of the system stays in sync.
The strategy points the Lead Engine at the right factories. Website visitors can book a call. The Quality Hub is the product itself. The scheduled jobs keep all three fed and fresh. Everything shares one database.
02

The product: Quality Hub

the customer-facing product
Intake
A problem comes in: email, PDF, or typed by hand
A quality problem enters by pasting an email, uploading a PDF/Excel, or typing it in. No special format required.
AI reads it
Fills in the structured details automatically
Claude reads the raw text and automatically fills in the structured details: what happened, how severe, and the part and supplier involved.
Human check
A person fixes anything the AI got wrong
A person confirms or corrects the AI's draft before saving. Their corrections are recorded so the AI keeps improving.
Assign + suggest
Auto-assigns an owner, proposes steps + due dates
Routing rules pick the right owner, and the system proposes corrective steps with due dates (containment, corrective, verification).
Track to done
Dashboard counts down the 90-day deadline
A dashboard shows every open action and what's overdue, counting down to the 90-day deadline carmakers enforce.
Reminders + exports
Daily nudges · audit-ready PDF / Excel
Daily email/Telegram reminders keep actions from slipping, and one click produces an audit-ready PDF or Excel for inspectors.
These factories get penalized by carmakers if a fix slips past a 90-day deadline. The Hub's whole job is to make sure nothing falls through the cracks, and to produce the paperwork an auditor wants.
03

The Lead Engine

how leads get found
Find factories
Search Midwest + Huntsville metros
Searches Google Places for manufacturers across the Midwest IATF belt and the Huntsville corridor.
Filter wrong-fit
Drops aerospace / defense / medical
Automatically drops aerospace, defense, and medical companies (a hard rule while Nick works at Boeing) before anyone is contacted.
Score 0–100
Industry, cert, size, location
Ranks each surviving company on industry, certification (e.g. IATF 16949), size, and location, so Nick works the best fits first.
Find a contact
Hunter.io + the company website
Uses Hunter.io plus the company's own website to find a real contact email.
AI writes the email
Short, honest intro in Nick's voice
Claude writes a short, honest intro in Nick's voice using a verified fact about the company. It can also write follow-ups or re-engagement notes.
Nick approves
Edit / approve / skip; AI never sends alone
Every draft waits in a queue. Nick edits, approves, or skips; the AI never sends on its own.
Send from Gmail
Goes out from Nick's own inbox
Approved emails go out from Nick's own Gmail so they read as personal, not automated.
Track replies
Texts back are auto-sorted by AI
Replies (including text messages) are logged and automatically sorted by AI into interested / not / needs-info.
feeds the top of the funnel
⟲ Runs on a schedule
Weekly: auto-find ~15 new factories · Daily: nudge quiet leads
Every week it finds ~15 new factories automatically; every day it nudges leads that went quiet.
Two key guardrails: the filter automatically drops aerospace/defense companies (a hard rule while Nick works at Boeing), and the approval step means the AI never emails anyone on its own. It drafts, Nick decides.
04

Behind the scenes

the scheduled jobs
17 scheduled jobs
Run on timers via Trigger.dev + Vercel Cron
Seventeen small automated jobs running on timers (via Trigger.dev and Vercel), grouped by what they keep running.
grouped by job
Keep the website fresh
Daily
Refresh industry news
Weekly
Refresh demo data
Feed the Lead Engine
Weekly
Pull ~15 new leads
Daily
Follow-ups + re-engage
Daily sweeps draft follow-ups for leads with no reply and re-engagement notes for ones that went quiet.
Help the product
Daily
Overdue-action reminders
Run the business
Weekly
Monday brief + client reports
Daily
Uptime + churn checks
Pings the live site daily and runs account-health checks so any at-risk account gets attention early.
Monthly
Money snapshot
⌨ On demand via Telegram
Nick texts a bot to trigger any job immediately
Nick can text a Telegram bot a plain-language instruction and the system runs the matching job immediately.
Seventeen small jobs run on a schedule: some keep the public site current, some feed the Lead Engine, one sends reminders about overdue work, and others handle weekly reporting and health checks.
·

Who's in control

the safety net
Human gate

A person approves every outbound email. The AI drafts; Nick edits and sends.

Auto-reject

Wrong-fit companies (aerospace/defense, medical) are dropped before anyone is contacted.

Spend caps

Built-in limits stop the AI tools from ever running up a surprise bill.

Isolation

Each customer's data is walled off so one company can never see another's.

Secret scanning

Passwords and keys are scanned automatically so they can't leak into the code.

Monitoring

Errors and downtime are tracked in real time, with alerts straight to my phone.

·

How a full cycle is designed to work

Monday, automatic: a job finds 15 machine shops in Ohio, drops a defense contractor (guardrail), scores the rest, and saves them.

I open the Lead Engine: I pick a high-scoring shop. The AI has already found a contact email and drafted a short, honest intro in my voice using a real fact from their website.

I edit one line and hit send. It goes from my Gmail; a reply (email or text) is logged and auto-sorted.

A shop books a discovery call from the website, and a pilot follows.

Once they're a customer: their quality manager logs a supplier defect into the Quality Hub by pasting an email. The AI fills in the details and suggests an owner plus a corrective action with a due date.

A daily reminder keeps the action from slipping. When it's done, the Hub exports an audit-ready PDF.

To be clear about where this stands: everything above the discovery call is built and running. Soltreya is pre-revenue with no pilots or customers yet, so the last two steps describe the path the system was built for, not traffic it has handled. I paused outbound while I focus on engineering roles.
Part Two

The technical deep-dive

The same system at engineering depth: the WAT framework underneath it, then stack, topology, the request security model, the lead pipeline, and the data model.

·

The WAT framework

workflows · agents · tools
Instruction in
Telegram · email · cron
plain-language or scheduled
Work enters as a plain-language instruction over Telegram or email, or fires on a schedule.
Claude orchestrator
classifies and routes
A Claude orchestrator classifies each instruction and routes it to the specialist agent that owns that kind of work.
Agents · judgment only
7 specialist agents
research · sales · marketing · delivery · client success · ops · content
Seven agents, each scoped to one domain. An agent decides what should happen and which tools to call; it does not execute the work itself.
Workflows
SOPs written in Markdown
Each procedure is a Markdown SOP, so changing how the business works is an edit to a document rather than a code change.
Tools · execution only
40+ Python tools
deterministic, testable
Every side effect (API calls, file writes, sends) happens in deterministic Python I wrote, so the same input always produces the same result.
Result
logged, human-gated where it matters
Results are logged, and anything customer-facing waits for my approval before it goes out.
The split: AI decides · Python does
Why it is built this way: chained AI steps decay. Five steps at ~90% accuracy each land around 59% end to end, which is useless for anything unattended. So judgment stays with the model and every side effect runs in deterministic code. That is the whole reason this can run without me watching it.
·

Stack at a glance

Web app
Next.js 15 on Vercel
App Router; server actions + route handlers; site, Hub, and Lead Engine
Database
Supabase Postgres + Drizzle ORM
Shared instance; hub_* and leadgen tables
File storage
Supabase Storage
hub-attachments bucket, signed URLs (1h)
AI
Anthropic Claude haiku-4.5 · sonnet-4.6
Haiku for classification and most agent execution; Sonnet for heavier reasoning (Hub extraction, voice drafting)
Lead sourcing
Google Places API
The source for discovering target companies
Contact email
Hunter.io + site scraper
Domain lookup, name-matched
Outbound email
Gmail API (OAuth, send-as)
Approved drafts only
Inbound replies
Twilio SMS webhook
HMAC-verified; AI-classified
Hub auth
Clerk (email allowlist)
Allowlisted sign-in; a local-only bypass in development
Rate-limit store
In-memory, per instance
Per-IP counters held by the serving instance
Background jobs
Trigger.dev (17) + Vercel Cron (2)
Two separate schedulers
Site refresh
Trigger.dev → GitHub → Vercel
Commits data files; Vercel auto-redeploys
Notifications
Telegram · SMTP · Twilio SMS
Owner alerts + customer reminders
Monitoring
Sentry · gitleaks + GitHub Actions
Error tracking; secret scanning in CI + pre-commit
05

Where it runs

code → compute
Code
Soltreya monorepo
Python tools + Trigger.dev tasks
The monorepo holding the Python tools and the Trigger.dev background tasks (TypeScript).
soltreya-web
Next.js 15 app
soltreya-web: the Next.js 15 app (site + Quality Hub + Lead Engine), deployed to Vercel on every git push.
Vercel: the web app
App surfaces
Marketing site · /hub · /internal/leadgen
The three user-facing parts of the app: the public marketing site, the /hub Quality Hub, and the internal /internal/leadgen Lead Engine.
API + server actions
/api/*, every request routed first
All backend endpoints and server actions; every data request is routed through the security layer first.
Security layer
rate-limit · auth · tenant-scope · cost-cap
Shared checks every data request passes: rate limiting, authentication, tenant scoping, and cost caps, plus a guard on outbound fetches.
Vercel Cron ×2
Hub reminders + weekly lead pull → API
Two scheduled routes (the Hub's daily reminders and the weekly lead pull) guarded by a shared secret.
Trigger.dev cloud
17 background tasks
Deployed separately · call back into the app API
Runs 17 scheduled and webhook background tasks, deployed separately from the web app; they call back into the app's internal API.
Two deploy targets: git push → Vercel · deploy → Trigger.dev
Two deploy targets: the Next.js app on Vercel and the background tasks on Trigger.dev. Inside the app, every surface funnels through the API and the shared security layer.
06

Data & services

what the app talks to
Security layer
The single chokepoint on every data request
The single chokepoint every read or write passes through before touching data or paid services.
Data stores
Supabase Postgres
hub_* + leadgen tables
The primary database holding both the hub_* tables and the leadgen tables.
Supabase Storage
hub-attachments, signed URLs
Uploaded PDFs/spreadsheets (hub-attachments), served via short-lived signed URLs.
In-memory store
Rate-limit counters
Per-IP rate-limit counters held in memory by the serving instance.
Google Sheets
Lightweight reporting surface
A lightweight data surface some reporting tasks read from and write to.
Notion
Tasks, priorities, financials
Tasks, priorities, and financial snapshots the automation reads and updates.
AI + sourcing
Anthropic Claude
Extraction, drafting, classifying
Haiku 4.5 handles classification and most agent execution; Sonnet 4.6 handles heavier reasoning like Hub extraction and voice drafting.
Google Places
Discovers target companies
The source for discovering manufacturer companies to target.
Hunter.io
Finds + enriches contact email
Finds and enriches a contact email for each sourced company.
Comms + ops
Gmail
Sends approved outreach
Sends approved outreach from Nick's account via OAuth.
Twilio SMS
Inbound replies → verified webhook
Sends and receives texts; inbound replies arrive as a signature-verified webhook.
Clerk auth
Hub login, email allowlist
Handles Quality Hub login with an email allowlist.
Sentry
Error + performance tracking
Captures errors and performance issues in production.
GitHub API
Commits data → auto-redeploy
Background tasks commit fresh data files here, which triggers an automatic Vercel redeploy.
↩ inbound Twilio SMS → security layer · Trigger.dev syncs Sheets, Notion & commits to GitHub
The security layer is the single chokepoint to data and paid services. Background tasks also sync to Google Sheets and Notion, and commit fresh data to GitHub, which triggers an automatic redeploy.
07

Request security model

four gates
Incoming request
browser · cron · webhook
Any request: a browser action, a scheduled cron, or an external webhook.
1 · Rate limit
per-IP, in-memory counters
Caps how many requests an IP can make against public forms and auth routes, to stop abuse and runaway loops.
2 · Authenticate
session · bearer · webhook HMAC
Proves who's calling: a logged-in session, an internal service token, or a cryptographic webhook signature.
3 · Tenant scope
every query filtered by tenant
Filters every database query to the caller's own tenant, so one customer can never read another's data.
4 · Cost-cap
paid calls blocked over budget
Before any paid AI or enrichment call, checks today's spend against a budget and blocks if it's over.
all four gates pass
Data / action
only now does the request read or change data
Only after all four gates pass does the request read or change data.
✕ Rejected: fail any gate
429 too-many · 401 unauthorized · 403 forbidden
Failing any gate returns a clean error (429 too-many, 401 unauthorized, or 403 forbidden) and never touches data.
Plus a guard on the one place the server fetches external URLs (the lead website scraper): it resolves all A/AAAA records and refuses private, loopback, reserved, and cloud-metadata addresses.

What protects what

  • Rate limit: per-IP caps on public forms and auth routes; client IP read from trusted proxy headers
  • Auth: timing-safe signature checks for service calls; Clerk-managed sessions for the Hub
  • Tenant scope: session required, then every query filtered to the caller's own tenant
  • Cost cap: daily spend checked before any paid AI or enrichment call, and logged
  • Webhooks: cryptographic signature verification, fail-closed on mismatch
  • Outbound fetches: external-URL fetches resolve DNS and refuse private, loopback, reserved, and cloud-metadata addresses

Operational hardening

  • Automated secret scanning on every commit and in CI
  • Dependency advisories tracked and patched on a regular cadence
  • Documented security runbook and incident process
08

Lead Engine pipeline

source → approve → send → learn
1 · Source + screen
Google Places
metros × keywords
Queries manufacturer keywords across target metros to discover companies.
Website scrape
private-IP guarded
Fetches the company site for personalization facts, but first blocks private and internal IP addresses.
Guardrail
exclusions.ts drops wrong-fit
exclusions.ts rejects aerospace/defense, medical, and dead-era industries before any spend.
Fit score 0–100
sector, cert, headcount, geo, OEM
fit-score.ts ranks by sector, certification, headcount, geography, and named OEM customers.
2 · Enrich
Hunter.io email
by domain
Hunter.io finds a contact email by domain.
Cost-cap preflight
logs to daily_costs
Guards the paid Hunter and Claude calls and logs spend to the daily_costs table.
3 · Draft + approve
Claude drafter
first_touch / follow_up / reactivation
Generates the email in Nick's voice; the draft kind is first_touch, follow_up, or reactivation.
Approval queue
pending_approval worklist
Drafts land as pending_approval in a daily worklist for review.
Nick
edit / approve / skip
Nick edits, approves, or skips each draft.
4 · Send + learn
Gmail send
store messageId, sentAt
Approved drafts send via OAuth; the Gmail message id and send time are stored.
Inbound SMS
Twilio webhook, HMAC verified
Replies arrive via Twilio with a verified HMAC signature.
Reply classifier
AI updates lead.status
AI reads the reply and updates the lead's status automatically.
⟲ crons pull (weekly) · enrich · follow-up-sweep · churn-sweep (daily). Stuck / no-reply loops back to re-engage
Sourcing is fully automatic up to the approval queue; sending is gated on Nick. Replies feed a classifier that updates lead status, and quiet leads are swept back into follow-up / reactivation drafts.
09

Core data model

multi-tenant
TENANTS
a customer account
The top of the tree: each tenant is an isolated customer account. Every record below is SQL-scoped to its tenant on every read.
owns
PROJECTS
a workspace under a tenant
A tenant owns one or more projects; leads, pull-runs and daily-costs all hang off a project.
contains · logs · tracks
LEADS
status: new → won / lost
The sourced companies. leads.status flows new → drafted → contacted → replied → conversation → won / lost / churned, with stuckSince for re-engagement.
PULL_RUNS
logs each sourcing run
A record of each sourcing run for a project: what was pulled, when, and how many leads resulted.
DAILY_COSTS
tracks per-day spend
Tracks paid-API spend per project per day, enforced by the cost-cap preflight.
each lead has
DRAFTS
has outreach
Outreach drafts generated for a lead (first_touch / follow_up / reactivation), each pending Nick's approval before send.
REPLIES
receives
Inbound replies received for a lead, classified by AI to update the lead's status.
Parallel Hub set: hub_events · hub_actions · hub_routing_rules · hub_members · hub_audit_log · hub_ai_feedback
Multi-tenant by design: a tenant owns projects; leads, drafts, replies, pull-runs and daily-costs all hang off a project and are SQL-scoped to the tenant on every read. leads.status: new → drafted → contacted → replied → conversation → won / lost / churned (with stuckSince for re-engagement). The Quality Hub uses a parallel set: hub_events, hub_actions, hub_routing_rules, hub_members, hub_audit_log, hub_ai_feedback.
·

Scheduling & the self-refresh loop

Two schedulers

  • Vercel Cron (2): Hub reminders (daily 12:00 UTC) and the weekly lead pull (Mon 13:00 UTC); route handlers guarded by a shared secret.
  • Trigger.dev (17): everything else: refresh-signals, refresh-demo, weekly-report, daily-risk-check, monthly-financials, leadgen pulls / sheet-sync / follow-up-sweep / churn-sweep, telegram-agent (webhook), and more.

Site stays fresh without a deploy

  • A Trigger.dev task generates data (industry signals, demo events) with Claude.
  • It commits the JSON to the site repo via the GitHub API using a scoped token.
  • Vercel's git integration sees the commit and redeploys automatically.
  • Idempotent: identical content is skipped (no redeploy churn).