I build real software with AI, and AI that does real work.
I designed and shipped the platform my company runs on, 33,585 lines across three live sites and a CRM. AI coding agents do most of the typing; I write the spec, read and review the code, catch the errors and research the right way to build it. Four AI agents now run parts of the business, and I use open-weight LLMs just as much as cloud ones. Before software, I drove $10M+ in TikTok Shop GMV and led teams of up to 50.
~/syndicate $ node tools/repo-stats.mjs lines 33,585 across 5 languages functions 772 in PHP migrations 37 schema versions npm deps 0~/syndicate $ curl -sX POST crm.stusyn.com/build-api.php?a=next -H "Authorization: Bearer $AGENT_KEY"{"ok":true,"job":null,"note":"Nothing to build right now."}~/syndicate $ git push origin main# Deploy to cPanel: build 3 sites → upload over FTPS# open-weight models: Ollama + LM Studio · Qwen (local), Kimi (cloud)
Numbers are counted from the source each time this page builds. The API line is the agent endpoint’s real reply when the queue is empty. Click to skip.
33klines of code across three live sites and a CRM
772PHP functions, plain and framework-free
37database migrations that run themselves on deploy
152end-to-end browser checks across four test suites
4AI agent jobs running on schedules
0npm dependencies. No frameworks, no libraries
Counted from the source by tools/repo-stats.mjs when this page was built.All live in production as of October 2026.
01 How I work with AI
Cloud agents and open-weight models.
I use both every day, about equally. Cloud agents for the heavy building and the jobs that run the business; open-weight models through Ollama and LM Studio for coding, agents and file work.
In the cloud
AI coding agents & scheduled agents
I build with Claude Code and read the code it writes. I also run AI agents on schedules that do real work for the business.
Built the whole platform below, 33,585 lines, with AI coding agents: I write the spec, read and review the code, catch the bugs and research the standards it has to meet
4 agent jobs on schedules: prospect research and outreach writing, reply handling, website first drafts and weekly blog drafts
Designed the key-protected APIs they call, with every rule and limit enforced in code
Built a short-form video agent with its own render engine (paused to save usage)
Claude Code
Code review
Scheduled agents
Agent APIs
Human review gates
Ollama & LM Studio
Local & open-weight LLMs
I use open-weight models just as much as cloud agents: Qwen running on my own Mac, so private work stays on the machine, and Kimi in the cloud when a job needs a bigger model.
Runtimes
Ollama · LM Studio
Models
Qwen (local) · Kimi (cloud)
Hardware
Mac · 16 GB RAM
Coding: a second model for writing and checking code next to the cloud agents
File management: sorting, renaming and organizing files with a local model
Running locally in 16 GB means picking model sizes that actually fit
The model proposes. Code enforces.
Agents do the judgment work: research, writing, building. Anything with a rule, like send limits, opt-outs, link allow-lists, job claims and who can see what, lives in plain, tested code an agent can’t talk its way past. And anything a client sees passes a human first.
02 Agents in production
AI that does real work.
Each agent is a scheduled job with one narrow task, an API I designed, rules it can’t bend and a human gate where it matters. Pick one to see how it runs.
Website builder
Running · Twice a day
Every paid website order becomes a first draft without me opening an editor. The agent claims a job, builds the site to our client-site rules and uploads it for my review.
Trigger
A paid order or won quote creates a build. The client’s kickoff form (or call) marks it ready.
Claim
POST build-api.php?a=next claims the next job (change requests first) in one guarded update, so two runs can never take the same one.
Build
Reads the brief, kickoff answers, approved contact details and the client’s files, then builds to templates/CLAUDE.md.
Guardrails
Paths sanitized, file types allow-listed, 800 files / 60 MB per draft. Stale claims return to the queue after 8 hours; 3 failures and it stops.
Review
Drafts open in a sandboxed preview: no network, forms can’t post, no cookies. I approve before the client sees anything.
Outreach writer
Running · Weekly · Mon & Thu
Researches local trades and gaming studios, runs a free website checkup or makes a homepage preview where it helps, and writes a personal first email plus two follow-ups.
Trigger
Monday covers local trades in Upstate SC; Thursday covers gaming studios, creators, esports and gaming businesses.
Research & write
Finds businesses with published business emails, checks their site and writes the emails.
Check
out_blocked() skips do-not-contact, existing prospects and contacts. out_links_error() refuses outside links and leftover placeholders.
Send
The CRM sends, not the agent: weekdays 9–5, a warm-up cap from 8 a day up to 30, threaded follow-ups, one-click unsubscribe.
Circuit breaker
Replies stop the sequence. Bounces over 8% in 14 days switch outreach off and email me.
Reply handler
Running · Twice a day
Reads replies to outreach and decides what happens next, from a fixed set of actions.
Sort
Code sorts the mail first: bounces, spam blocks, auto-replies and opt-outs never reach the model.
Read & decide
Reads real replies and picks one action: reply, interested, decline, handoff or resume.
Enforce
Only conversations waiting on a reply can be answered, once. Replies count toward the daily send cap.
Record
interested creates the contact, a qualified deal at the product’s price and a task.
Hand-off
Unsure? handoff parks it for me with a suggested reply. If I answer myself, the agent steps back.
Blog writer
Running · Weekly · Wednesday
Writes one post a week for syndicatemarketing.co as a draft and sends me the link.
Trigger
The Wednesday run of the weekly growth task.
Write
Writes to the blog’s house rules: prices from catalog tags, no made-up stats, clients or results.
Draft build
Drafts build at their own address with a Draft bar and noindex, and stay off the index, feed and sitemap.
Fail-safe
The build fails on any unfilled template tag, so a broken post can’t ship.
Publish
I approve every post. Publishing is one instruction: drop the draft flag, date it, build, push.
Video producer
Paused · Paused Oct 23, 2026
Made two short videos a day for TikTok with our own engine and sent each one to my phone, ready to post. Paused to save plan usage; one switch turns it back on.
Trigger
Scheduled for about 6:45 AM and 5:45 PM.
Script
Picks the next topic from a rotation and writes a brief that follows a playbook of hard rules.
Render
tools/video/ checks the brief, then renders a 1080×1920 video with an original soundtrack.
Deliver
Sends the video, caption, hashtags and first comment to my phone.
Post
I post it myself: The TikTok API only allows private posts until an app passes its audit.
The model decidesCode enforcesA person approves
03 What I’ve shipped
One person, a whole platform.
Everything here is live and runs Syndicate today. Read the case study for how the pieces fit together. Anything built for a made-up business is labelled as a concept.
Back office
CRM, client portal and billing
One PHP and SQLite app runs every brand: pipeline, contacts, tasks, quotes with online deposits, invoices, bookings, a shared inbox, projects and a client portal.
37 schema migrations that apply themselves on the next page load
A paid Stripe order creates the contact, won deal, paid invoice, project, portal access and tasks on its own
A demo portal on separate sample data, rebuilt daily, where every form is read-only
Five excerpts copied as-is from the live codebase, with the reason each one exists. I can walk you through any of them line by line. The highlighting is a few dozen lines of JavaScript on this page.
stripe-webhook.php
$ev = stripe_verify($payload, (string)($_SERVER['HTTP_STRIPE_SIGNATURE'] ?? ''), stripe_key('stripe_webhook_secret'));
if (!$ev || empty($ev['id'])) { http_response_code(400); exit('{"ok":false,"error":"Signature check failed"}'); }
// Each event is handled once, even when Stripe sends it again.
try { q('INSERT INTO stripe_events (id, type, created_at) VALUES (?,?,?)', [$ev['id'], (string)($ev['type'] ?? ''), now()]); }
catch (PDOException $e) { exit('{"ok":true,"result":"already handled"}'); }
try {
$result = shop_handle_event($ev);
q('DELETE FROM stripe_events WHERE created_at < ?', [date('Y-m-d H:i:s', time() - 60 * 86400)]);
echo json_encode(['ok' => true, 'result' => $result]);
} catch (Throwable $e) {
q('DELETE FROM stripe_events WHERE id = ?', [$ev['id']]); // let Stripe retry
error_log('Stripe webhook ' . ($ev['type'] ?? '') . ' failed: ' . $e->getMessage());
http_response_code(500);
echo '{"ok":false}';
crm/stripe-webhook.php · lines 9–23
Handling a payment exactly once
Stripe can send the same event more than once. The handler verifies the signature, then lets the database decide whether it has seen the event: the primary key does the de-duplicating, with no race.
HMAC-SHA256 signature with a 5-minute replay window
Insert-first de-duplication on the event ID
If handling fails, the row is removed so Stripe’s retry gets processed
checkup.php
function ck_ip_public(string $ip): bool {
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) return false;
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
$n = ip2long($ip);
foreach ([['100.64.0.0', 10], ['192.0.0.0', 24], ['198.18.0.0', 15], ['192.88.99.0', 24], ['224.0.0.0', 4], ['240.0.0.0', 4]] as [$net, $bits]) // shared, protocol, benchmark, relay, multicast, reserved
if (($n & (-1 << (32 - $bits))) === (ip2long($net) & (-1 << (32 - $bits)))) return false;
return true;
}
$l = strtolower($ip);
return !preg_match('/^(fc|fd|fe[89ab]|ff|::ffff:|64:ff9b:|2001:db8:|2002:)/', $l);
}
// The address to connect to: an IP, '' (not found) or '!' (points somewhere private). Every address the name has must be public.
function ck_ip(string $host): string {
static $cache = [];
if (isset($cache[$host])) return $cache[$host];
$ips = gethostbynamel($host) ?: [];
if (function_exists('dns_get_record')) foreach ((array)@dns_get_record($host, DNS_AAAA) as $r) if (!empty($r['ipv6'])) $ips[] = $r['ipv6'];
if (!$ips) return $cache[$host] = '';
foreach ($ips as $ip) if (!ck_ip_public($ip)) return $cache[$host] = '!';
return $cache[$host] = $ips[0];
}
crm/app/checkup.php · lines 43–63
Scanning strangers’ websites safely
The free checkup fetches any URL a visitor types, which is a classic way to trick a server into probing its own network. Every address a host resolves to must be public, or the scan refuses.
Private, reserved, shared, benchmark and multicast ranges refused, IPv4 and IPv6
Every DNS answer must pass, not just the first
The checked IP is then pinned for the actual request
outreach.php
function out_links_error(string $text, string $website): string {
$own = out_site_domain($website);
preg_match_all('#https?://[^\s<>()"\']+#i', $text, $m);
foreach ($m[0] as $u) {
$h = strtolower(preg_replace('/^www\./', '', (string)parse_url($u, PHP_URL_HOST)));
$ok = $h !== '' && ($h === $own || in_array($h, OUT_LINK_HOSTS, true));
if (!$ok) return "Link to $h isn’t allowed. Only our sites and the business’s own website.";
}
if (preg_match('/\{\{|\[(MAILING ADDRESS|NAME|BUSINESS|FIRST ?NAME)[^\]]*\]/i', $text)) return 'The email still has a placeholder in it.';
return '';
}
crm/app/outreach.php · lines 49–59
A guardrail an agent can’t argue with
The outreach agent writes the emails, but this function decides whether they can be sent. An email with a link to anywhere but our sites or the prospect’s own site, or with a leftover placeholder, is refused.
Runs on every email the agent submits, before anything is queued
Allow-list, not block-list
Returns a plain reason the agent can act on
builds.php
function build_claim(): ?array {
if (!build_on()) return null;
$b = one("SELECT * FROM builds WHERE status IN ('ready','changes') ORDER BY CASE status WHEN 'changes' THEN 0 ELSE 1 END, updated_at LIMIT 1");
if (!$b) return null;
$claim = q("UPDATE builds SET status = 'building', claimed_at = ?, attempts = attempts + 1, updated_at = ? WHERE id = ? AND status IN ('ready','changes')", [time(), time(), $b['id']]);
if ($claim->rowCount() === 0) return null;
return build_job(build_row((int)$b['id']));
}
crm/app/builds.php · lines 124–131
Claiming a job exactly once
Two scheduled runs could ask for work at the same moment. The claim is a conditional update: only the run whose update actually changes the row gets the job.
Change requests jump ahead of new builds
No locks needed: rowCount() settles the race
Each claim counts an attempt, so a stuck job stops after three
New staff passwords are checked against Have I Been Pwned using k-anonymity: only the first 5 characters of the hash leave the server, and padded responses hide which range was asked for.
Constant-time comparison with hash_equals
If the service is down, the password is allowed and the outage is logged
The same loop for every change, whether it’s a typo or a payment flow.
Spec
I research how it should be built first (OWASP, NIST, the RFCs, the vendor’s docs), then write it into CLAUDE.md: 1,225 lines the agents read before they touch anything.
Build
AI coding agents write most of the code from that spec, one scoped task at a time, so I can follow every change.
Review
I read the code. I catch the errors, security holes and shortcuts, send them back, and make the calls on architecture and what we promise customers.
Test
Playwright runs the real flows against a local copy with a mock Stripe server and fake mail: 152 checks across store, quotes, booking and security.
Ship
A push to main builds three sites and deploys them over FTPS. Database migrations run themselves on the next page load.
How I actually work
AI does most of the typing; the engineering is mine. I read and understand the code, spot bugs and bad patterns before they ship, and research best practices instead of taking an agent’s word for it. That isn’t vibe coding: it’s specifying, reviewing, testing and owning what goes live.
06 This page
The page is the demo.
Plain HTML, CSS and JavaScript with nothing borrowed. It reads fully with JavaScript off, respects reduced motion and works by keyboard. Here’s what it’s made of and what it weighs, measured live.
The codebase, by language
33,585 lines
Counted from 312 source files when this page was built, leaving out demo sites, fonts and content.
PHP18,67056%
HTML6,50919%
CSS4,36313%
JavaScript3,64211%
Python249<1%
This page, right now
Measured in your browser
Read from the Performance API after the page loaded.
Transferred
—
JavaScript
—
Requests
—
Page elements
—
DOM ready
—
Frameworks
0
Cached files can show as small or zero. With JavaScript off, the dashes stay and everything else still works.
07 Experience
Where I’ve worked.
Building my own businesses since 2019, after nine years of running stores, teams and partner accounts. Customer-facing experience is what makes the technical work land.
2019 — PRESENTSpartanburg, SC · Remote
Founder & Builder
Syndicate Holdings Group LLC · Syndicate Marketing · Creator Ops Media
Designed and shipped the software the company runs on, building with AI coding agents and reading and reviewing the code myself: three live sites, a CRM, a client portal, a store with Stripe subscriptions, analytics, monitoring and a help center (33,585 lines).
Built and run 4 scheduled AI agent jobs for outreach, reply handling, website drafts and blog drafts, behind APIs with rules enforced in code and human review gates.
Use open-weight LLMs through Ollama and LM Studio (Qwen locally, Kimi in the cloud) for coding, agents and file management.
Delivered client sites like Kirby’s Home Improvement, live with calls and quote requests tracked in our own analytics.
FOUNDERTikTok Shop · consulting since late 2026
Founder & Lead TikTok Shop Strategist
Creator Ops Media
Drove more than $10M in TikTok Shop GMV for brands including Intake Breathing and Rap Snacks.
2024–25: led classes and coached smaller agencies; among the first to test new TikTok Shop features.
2016 — 2025Upstate South Carolina
Before software: operations & partners
Nine years running stores, teams and partner accounts
General Manager7-Eleven · Spartanburg2023–2025
Manager, Dealer RelationsAmerican Credit Acceptance · network +10% in a year2022–2023
Security SupervisorSecuritas · team of 502021–2022
PM Assistant ManagerCircle K · team of 252018–2021
Shift LeadDollar General · team of 92016–2018
08 What I’m looking for
Roles where I fit.
AI work that sits between the people with the problem and the system that solves it. Remote, or based from Spartanburg, SC.
AI solutions & implementation
Take a business problem, design the agent workflow, build it and get it running. I did exactly that for my own company.
AI automation & agent operations
Run agents on schedules with real guardrails, watch what they do and tighten the rules when they drift.
Solutions or sales engineering
B2B sales and partner work (a dealer network up 10% in a year), and I can build the demo myself.
Forward-deployed engineering
Sit with the customer, learn the workflow, ship the fix. Nine years of operations taught me the first two.
Technical PM for AI products
I write specs that agents build from, and I own the result end to end: tests, launch and the promises it makes.
AI education & enablement
I’ve led classes for other agencies. I’d like to teach teams to build with AI next.
09 Skills
The stack I ship in.
Everything in the codebase above, plus the local setup on my own machine.
AI & agents Cloud
Claude Code
Code review
Debugging
Agent workflow design
Agent APIs
Guardrails in code
Human-in-the-loop review
Spec writing
Best-practice research
Local & open-weight LLMs
Ollama
LM Studio
Qwen (local)
Kimi (cloud)
Local coding
Local agents
File management
Backend
PHP
SQLite
JSON APIs
Webhooks
Cron jobs
Schema migrations
IMAP/SMTP
Frontend
HTML
CSS
JavaScript, no frameworks
WebGL
Accessibility
Performance
Security
WebAuthn passkeys
TOTP
Argon2id
CSP & headers
SSRF protection
HMAC signatures
OWASP
Ship & integrate
Git & GitHub
GitHub Actions
Playwright
Node build scripts
Stripe API
PageSpeed API
Apache & LiteSpeed
SPF/DKIM/DMARC
Open to AI roles
Let’s build.
Email me and I’ll reply within one business day. References on request.
Cookies on stusyn.com. We only use cookies that keep this site working, like keeping application forms secure. We count visits with our own cookie-free analytics. No advertising or cross-site tracking. Cookie policy
Cookie settings
Choose which cookies stusyn.com may use. Your choice is saved on this device for 12 months. Learn more
Strictly necessarySecurity and form features. These can’t be turned off.
ALWAYS ON
Your browser sends a Global Privacy Control signal, so analytics and marketing stay off.