E-Commerce

TITAN

Tier: Internal build — our own store, not a client engagementTimeline: 2026-07-07 – 2026-07-10 · 12 sessions
React Router 7Cloudflare WorkersD1KVR2Claude (Sonnet)Kavenegar SMS
Payment path
NoneCard-to-card live; Zarinpal gateway built and held behind a flag pending Enamad approval
Cron agents wired in
010 — abandoned-cart recovery, c2c sentinel, restock alerts, quote triage, ticket drafts, daily ops digest, content agent, housekeeping, payment reaper, order-status notifier
Build status
Feature-complete through session 12 · not yet deployed (domain + Enamad pending)

Where this stands right now

TITAN is our own e-commerce business, not a client's. We're building it on the exact stack we sell — React Router 7 on Cloudflare Workers, D1/KV/R2, and a cron-driven agent roster — because the strongest proof we can offer isn't a slide deck, it's a store we run ourselves. As of this writing TITAN is feature-complete through session 12 but not live: the domain isn't attached, Enamad approval hasn't landed, and no real order has shipped. Everything below describes what's actually built, not what we expect it to do. When TITAN launches, this page gets a numbers section pulled from its own agent observability — not before.

Twelve sessions, in order

TITAN was built in twelve focused sessions over four days: platform foundation and catalog (sessions 1–2), cart/checkout and card-to-card payment (session 3), phone-based auth (session 4), order lifecycle and notifications (session 5), support ticketing and an AI chat agent (session 6), the admin command center (session 7), the automation engine — the ten cron agents (session 8) — security hardening (session 9), the content and SEO engine (session 10), analytics and performance (session 11), and launch content plus the showcase page (session 12). Each session shipped against a written acceptance list, not a vibe check.

Card-to-card, built for how Iranian commerce actually works

Iran doesn't have access to international card gateways, so "card-to-card" bank transfer is a first-class payment method here, not a fallback. At order creation, TITAN adds a random 1–99 Toman offset to the transfer amount — a small, deliberate detail that makes every pending transfer's exact amount unique, so an admin can match an incoming bank transfer to an order by amount alone instead of chasing reference numbers by hand. The customer uploads a receipt or enters a reference code and the last four digits of their card; receipt images get their EXIF/GPS data stripped before storage. The order sits awaiting_verification for up to 24 hours while a cron agent (the "c2c sentinel") watches the queue and pings the owner once a pending order crosses a business-hours threshold. Approve and reject both go through a 10-second undo window instead of a confirm dialog — the real database write only fires if the undo window elapses untouched.

The Zarinpal gateway integration is fully built too — it's just held behind a flag until Enamad merchant approval lands, so card-to-card is deliberately the only live payment path for now, not a temporary gap we forgot to close.

SMS-OTP: verifying the phone at checkout IS the login

TITAN's core auth decision, made in session 4: verifying a phone number at checkout is the same act as logging in. There's no separate signup form. A guest who verifies their phone to place an order simultaneously creates their account, because that's the only phone verification most Iranian shoppers will ever willingly sit through.

Underneath, OTP requests pass through three independent rate limits, cheapest-first — a per-IP hourly cap, then a per-phone daily cap, then a tight per-phone 10-minute window — so an abusive request gets rejected before TITAN pays for a rate-limit lookup it doesn't need to make. The 5-digit code is stored with an absolute expiry timestamp kept deliberately separate from the storage layer's own TTL, because a naive relative TTL would silently slide forward every time a wrong-guess counter gets re-saved. A hard lockout kicks in after 5 wrong attempts — and stays locked even if the next guess happens to be the correct code. SMS delivery goes through Kavenegar's template-based transactional send, which is exempt from Iran's nightly blackout on promotional SMS — a detail that matters because a customer trying to check out at 11pm shouldn't have to wait until morning for their code.

The cron agent engine

Every 15 minutes, one Cloudflare Cron Trigger fans out to ten independent jobs, each wrapped in its own try/catch so one agent's failure can't take down the others: cart recovery reminders, the card-to-card sentinel, restock and wishlist alerts, a Claude- drafted feasibility note on new custom-order requests (price stays a deterministic formula — the model never sets it), pre-drafted replies for untouched support tickets, a daily Telegram ops digest at 07:30 Tehran time, a weekly blog-and-social draft agent that writes but never publishes on its own, and nightly housekeeping — a D1 export to R2 and a 90-day purge of card-to-card receipt images. A payment reaper runs alongside them, expiring stale unpaid orders and releasing the stock and discount codes they were holding.

What actually went wrong (and got caught)

A few real bugs, not smoothed over: an admin dashboard route was originally registered using a routing helper that has no path of its own to attach to on a layout with no parent segment — it silently matched / instead of /admin, and only a real browser navigation caught it, not typecheck, build, or lint, all of which had already passed. Separately, the invoice PDF generator was initially fed web-font files that are valid in a browser but not valid as an embedded PDF font program — the build looked fine until the actual rendered PDF page came out blank, which only a real PDF renderer (not a visual inspection of the code) surfaced. Both are the kind of bug that only shows up when you actually run the thing.

Live metrics land here at launch

TITAN's own agent observability already tracks the real numbers this section will one day show — carts recovered, average card-to-card verification time, SMS volumes, time-to-ship — because the schema was built for it from session 3 onward. Today those counters correctly read zero: no real order has been placed yet. We're not publishing projected numbers dressed up as results. This section gets filled in with real data after TITAN is live and has run for a full month, not before.

What's still ahead

The domain isn't purchased or attached, Enamad approval hasn't landed, and the Worker has never been deployed to production — every deploy attempt so far has been deliberately held as an unrequested production push. A handful of products are still missing real photography. None of that is hidden here; it's the actual state of the build.

Want this outcome for your business?

If you want a store that runs itself the same way — real agents doing real work, not a plugin marketplace bolted onto a template — talk to us about e-commerce development or get in touch.

Want an outcome like this?

Tell us what you're building and we'll respond with an architecture sketch within 48 hours.