Work ← 2026 ● Primary focus

Product contentCatalog to Shopify

Built end to end

Sirv AI Studio

I started Sirv Studio in December 2025. Sirv now uses it to scan catalogs, run AI batches, review supplier uploads, and publish to Shopify.

Studio / createLive product
Sirv Studio AI batch creation interface
  1. 01Catalog scan
  2. 02AI batch
  3. 03Human review
  4. 04Safe publish

Ownership

Who owns what

Igor Varyvoda

Creator, product lead, architect and principal engineer. Conceived Studio and built and shipped the product end to end.

Max Wish

Major contributor across the internal design system and virtualized data grid, working alongside Igor across those systems.

Veniamin Krachun

Owns QA, including the testing and verification infrastructure.

It started over a beer

Some coworkers were visiting me in Herceg Novi. Over a beer, we started talking about what current AI models could build. I said I would build the first version in a day.

The next morning I started at six. Initial commit from Create Next App landed at 6:35 on 2 December 2025. Background replacement worked by 8:00, virtual try-on by 8:23, and multi-angle product shots by 8:45. Auth, billing, rate limits, and Sirv storage landed before the 12:05 MVP merge. The afternoon added batch processing and side-by-side comparison. The repository records 31 commits that day.

day one timeline Dec 2, 2025 · git log timestamps
  1. Create Next Appthe empty repo becomes a product bet
  2. first AI toolbackground replacement and model selection
  3. virtual try-onsecond tool family is already live
  4. product-shot toolsangles, lighting removal, more image work
  5. MVP mergeauth, billing, rate limits, Sirv storage
  6. cleanup passbatch mode and compare mode were already in
Six of the 31 first-day commits, with timestamps from the repository.

Six days later, the workflow canvas existed. Durable Inngest jobs followed after twelve days, an MCP server after eighteen, and the embedded Shopify app after twenty-five. December closed at 602 commits. The main product areas were already visible.

I took Studio from that first commit to the production platform described here. Max Wish owns major work across the design system and virtualized data grid. Veniamin Krachun owns QA and its verification infrastructure. The separate build record has 48 dated milestones and the commands behind its repository counts.

what shipped, in order Dec 2, 2025 → Jul 2026 · condensed from 48 milestones
  1. A product before lunchImage tools, auth, billing, rate limits, Sirv storage, batch mode, and compare mode all land on day one.
  2. Durable jobs and the first MCP serverLong runs move to Inngest and stream progress. Agents get a dedicated tool surface.
  3. Five entry surfaces in four daysShopify, Zapier, n8n, MCP OAuth, and the OpenAI Apps SDK can start the same work.
  4. The asset library lands in a dayAssets, tags, filters, R2 storage, product links, and operation history form the DAM.
  5. Multi-org, roles, and share linksNested collections, role-based access, and subfolder share navigation turn the library into a team product.
  6. The first supplier portalScoped upload links, an approval queue, and before-and-after autofix review turn intake into a defined process.
  7. SFTP, SAP, catalog import, live Shopify syncSupplier delivery and product edits flow in through retry-safe GraphQL handling.
  8. A real supplier spec, proven end to endThe Alkosto pipeline drives reusable validation, product assignment, autofix, review, and delivery.
  9. Imports and side-effects go durableCancellable background jobs and an event outbox, so a retry can't casually duplicate work.
  10. Next.js replaced in 72 hours, liveThe billing, multi-tenant application moves route by route to TanStack Start while users remain on it.
  11. Workflows gain real triggersUploads, schedules, product changes, and authenticated webhooks start runs, with dry-runs and attempt history.
  12. One product-content data pathA documented path from org to source, product, variant, assignment, asset, publish projection, and readiness.
  13. Workflows learn DAM and PIM operationsThe orchestrator reads from and writes into the content system through a typed Effect-based operation kernel.
  14. Risk-tiered quality gatesEdit, session, and release gates are joined by an analytics dashboard and a coverage matrix checked by tooling.
  15. The catalog-health loop becomes executableA detected product gap connects to a controlled action: AI fix, supplier request, Shopify sync, or channel export.
  16. The product points at activationCatalog health leads the dashboard. Workflow recipes and drift-aware publishing run on selected products.
Sixteen of the 48 milestones on the build record, which dates each one to its commits. Tools became workflows, workflows grew a DAM and PIM, and supplier intake gained review and publishing.

What it does

The product is organized around one loop: ingest → fix → validate → review → publish → track.

  • 30+ AI tools for background work, upscaling, lifestyle images, ghost mannequin, virtual try-on, alt text, descriptions, translation, 3D, and video. The snapshot contains 57 registered models routed through fal.ai, OpenAI, and OpenRouter.
  • A visual workflow orchestrator: a drag-and-drop DAG builder with 40 registered step types, so a merchant can chain “remove background → generate lifestyle shot → write alt text → human review → push to Shopify” and run it across an entire catalog. Workflows execute on durable background jobs with pause/resume, review gates, and live progress, and can be triggered from the UI, the API, webhooks, or an AI agent.
  • A supplier portal gives brands a scoped upload link or SFTP drop. Files are checked against filename, SKU, and image rules, sent through AI autofix, and held for review before they can reach the catalog.
  • Marketplace checks validate dimensions, backgrounds, watermarks, and frame fill against Amazon, eBay, Walmart, and Shopify rules. Autofix can repair some failures.
  • Asset and product management adds search by image, duplicate detection, auto-tagging, and licence tracking that can block a publish. Integrations include Shopify, Zapier, n8n, a REST API, and MCP.
the toolbox 34 tool routes · 57 models · counted from the code
create image generationSVG generationvideo generation · up to 4Kimage → 3D · GLB/OBJ/FBX/USDZAI fashion modelfashion video
edit background removalbackground replaceobject removalprompt-based editingupscaling · up to 8×smart cropshadowsghost mannequincolor variantsdepth mapsGLB optimizer
product content lifestyle scenes · 44 presetsvirtual try-on · image & videoalt textdescriptions · 12+ languagesimage translationPDF translationdocument summarybundle composervideo captions
automate & review batch · every tool, catalog-scaleorchestrator · 40 step typesAI routingreview gates & autofix loopsmarketplace optimizerimage review · Amazon/eBay/Walmartwebhooks · API · Zapier · n8n · MCP
asset intelligence search by imagesemantic searchfind similarduplicate detectionauto-taggingsmart collectionssaved viewslicense tracking · publish gateslicense alertswatermark templatesasset & search analytics
Every chip is a shipped route or workflow capability. Models are routed through fal.ai, OpenAI, and OpenRouter. The interface uses the design system and virtualized data grid built by Max Wish.
Sirv AI Studio products view with per-product readiness scores

The products view: every product scored for content readiness against its channel’s requirements.

How it’s built

The app is a TanStack Start + React 19 application (migrated off Next.js, running the React Compiler) built with Vite and deployed on Vercel. Data lives in PostgreSQL 17 behind Drizzle ORM, with 286 committed migrations in the July 24 snapshot. Background work runs on Inngest across sync, publishing, billing, imports, repair jobs, and workflow execution, self-hosted on Hetzner with a Patroni HA Postgres cluster behind it. Redis handles rate limiting, Sentry/PostHog/Grafana handle observability, and the repo contains 5,244 tracked test and spec files across unit, integration, contract, Storybook, and browser layers. Capacitor shells package it for iOS and Android. The infrastructure bill for all of this, at current capacity, is about $70 a month.

system map product surfaces → governed execution → external systems
SURFACESCORE & DATAEXTERNAL SYSTEMSTanStack appmerchant UISupplier portalintake + reviewMCP + APIagent operationsPostgresproducts · assets · jobsInngestdurable workflowsAI providersimage + text modelsShopifydrift-safe publishingSirv storageassets + rollbackStudio coreauth · creditsreview gatesobservability across every hopSentry · PostHog · Grafana
The important boundary is in the middle: UI, supplier uploads, API calls, and AI agents all enter the same governed core before jobs, providers, storage, or Shopify writes happen.

Max Wish built the internal design system and custom virtualized data grid behind the asset and product tables. Veniamin Krachun built the E2E and QA systems used to verify releases.

Sirv AI Studio asset grid rendering hundreds of assets in a virtualized table

The assets table uses Max Wish’s virtualized data grid for live thumbnails, sortable metadata, and large result sets.

Three problems were harder than the rest.

Publishing to someone else’s store, safely

Studio writes to live Shopify catalogs. A publish must not overwrite a newer merchant edit.

Before writing, Studio compares the last sync with changes in Shopify and Studio. Each product is classified as in_sync, shopify_newer, or studio_newer. If Shopify is newer, Studio surfaces the conflict instead of overwriting it. Reconciliation also catches a source image that was deleted or replaced after the last sync.

Writes themselves are versioned and idempotent: publishes go through explicit strategies (add alongside the original, replace, set featured, alt-text-only), every published asset keeps its version history with rollback, and an event outbox guarantees that a retried job can’t double-publish. “Publish safely, roll back instantly” is the promise the whole layer is built to keep.

Supplier uploads without the chaos

Supplier files often arrive by email or shared drive with wrong names, dimensions, or missing SKUs. Somebody then has to prepare them for the store.

Each supplier gets a scoped upload portal, chunked batch upload, or SFTP drop. Studio checks filename patterns, SKU matches, gallery slots, and image rules. AI autofix repairs supported failures. A reviewer sees the product, shot list, and failed checks before accepting or rejecting the submission. Database guards stop supplier content from skipping review on its way to a live store.

This supplier workflow is in production with an enterprise customer.

Sirv AI Studio review queue with automated checks and AI autofix

The review queue holds supplier files before publication. Automated checks flag problems, autofix repairs supported failures, and a reviewer approves the result.

Making it operable by AI agents

Studio ships a production MCP server with stdio and hosted HTTP transports. The snapshot exposes 47 tools for AI processing, asset management, product changes, Shopify sync, and supplier review. A published OpenAPI surface contains 64 operations.

Agents receive the same permissions, approvals, budgets, and rollback rules as the UI. Authentication uses OAuth 2.0 with PKCE or API keys. Mutating and credit-spending tools check authorisation on the server. Every call validates organisation membership, and MCP annotations identify read-only, destructive, and idempotent operations. An agent can run a batch or workflow, but it cannot skip a required review.

What the code had to survive

The repository count is large, but commits alone say little about quality. The stronger evidence is in the failure cases. More than 900 written plans now record why a change matters, how it should work, and how it will be checked. The earlier record lives in the git log and changelog. These are examples from both.

Money, where the tolerance is zero.

  • A two-phase charge that deducted nothing. Tool jobs bill in two steps: reserve, then top up once the real cost is known. Both used an idempotency key derived from the job ID, so the credit layer treated the top-up as a replay and debited zero. The wallet and ledger agreed on the wrong number.
  • A ledger that could not rebuild a balance. The credit transactions table allowed the same type to be positive, negative, or zero. REFUND also mapped to both signs. A disputed balance could not be reconstructed. A signed journal now enforces the direction of every entry and will run beside the old system for a full billing cycle before cutover.
  • A free extra month on every upgrade. A mid-cycle proration invoice fell through to the renewal path and granted a full month of credits. Full refills now run only on true renewals.

Writing into a store you don’t own.

  • Day 25, before there were users to lose. The embedded Shopify app shipped its security with the MVP: HMAC-verified OAuth callbacks, an AES-256-GCM-encrypted state cookie, and mandatory session-token verification on the x-shopify-shop header, so nobody can pass someone else’s store and act on it. (fix: Shopify integration security hardening, Dec 27, 2025.)
  • Out-of-order webhooks restored deleted products. Per-event idempotency handles a repeated event, but it does not order two different events. An older products/update arriving after products/delete re-created assets. Per-product keys, staleness checks, and a delete tombstone fixed it.
  • A batch push reported failure as success. A partial failure still fired the success path and removed the failed items from view. A retry then duplicated catalog images because Shopify’s media API has no idempotency key. Every item now finishes as pushed, retryable failure, pushed with warning, or indeterminate and unsafe to retry.

The failures that raise no error.

  • A dead letter reported success. An outbox event exhausted ten retries, returned success to the queue, and alerted nobody. A customer endpoint that stayed down for a day lost every delivery. The missing error was the bug.
  • The 1,000-step limit. Inngest caps a run at 1,000 durable steps. One step per item worked in development, then failed on large production jobs. The fan-out now uses two steps per 100-item chunk. A 42,000-item job takes 840 steps.
  • Unconfirmed uploads escaped quota. A direct R2 upload that was never confirmed left an untracked object billed to the organisation. A bucket expiry rule would also have deleted live assets sharing the prefix, so the cleanup uses application-level bookkeeping.

Tenant isolation and agent permissions.

  • A cross-tenant store hijack appeared across two changes. One change reused an account after an email collision. Another left a synthetic store address available through public signup. Together, they let an attacker bind a merchant’s store to the wrong organisation. Review of the combined changes caught it.
  • A bulk delete checked ownership too late. The R2 delete used client-posted asset IDs before the organisation-scoped database delete ran. A user in one organisation could delete another organisation’s version history.
  • An idempotentHint misled agents. Several credit-charging tools claimed retries were safe. A transport timeout could therefore charge again and create duplicate outputs across batches of up to 100 images.
  • A dangerous account-linking default. allowDangerousEmailAccountLinking merged an OAuth login into an existing account with the same email. It was disabled in the first security pass, together with an IDOR fix that scoped payment queries by user_id.

Checks that caught bad code.

  • Isolation tests that proved nothing. The tests asserting cross-tenant isolation stubbed db.execute, so the org WHERE clauses that actually enforce it had never once run in CI. Rewritten to execute the real SQL against two seeded orgs, including the case where org A asks for org B’s asset and must get nothing back.
  • The money gate had no real coverage. The out-of-credits check used a hardcoded funded user, so the branch that blocks a paid run never executed in the test.
  • A type guard never ran. A satisfies AppSession annotation sat outside the typechecked project. Storybook had been rendering a connected user as disconnected without failing CI.

This is normal production work for software that touches money, stores, and customer data. The git log measures output. These incidents show some of the correctness work behind it.

Replacing the framework in production

By spring, Studio had outgrown Next.js. I moved the production application to TanStack Start while users remained on it.

The supplier portal shipped on 2 April. The first TanStack Start slice landed on 8 April. On 9 April, a compatibility shim kept old imports working while routes moved one by one. The final Next.js runtime dependencies were removed on 10 April. The migration took about 72 hours without freezing other work.

April migration close-up Apr 6–13 · commits per day
72-HOUR MIGRATION WINDOW 50100150 1554918276831950 Apr 6Apr 7Apr 8Apr 9Apr 10Apr 11Apr 12Apr 13
The live Next.js to TanStack Start migration began on 8 April and removed the final Next runtime dependencies on 10 April.

The migration depended on broad tests, route-by-route checks, and review gates. Fast edits would not have been enough without them.

How three people and a fleet ship this fast

February was the quietest month. It focused on billing, supplier intake, permissions, and other production work, and still contained 316 of my commits. In the first 235 calendar days, five had no commit.

cumulative commits Dec 2, 2025 → Jul 24, 2026 · my commits, cumulative
02k4k6k8kDecJanFebMarAprMayJunJulMVP dayMCP serversupplier portalteam joinsmigration8,317
My 8,317 commits from the first day to the 24 July snapshot. The build record maps the same period to 48 dated milestones.
repository snapshot dev @ 86a69aac · Jul 24, 2026
11,950commits in the repo
8,317under my primary author identity
230 / 235calendar days with a commit
5,244tracked test and spec files
286Drizzle migrations
47tools in the MCP server
A moving snapshot, not decorative numerology. The build record includes the exact command behind each count.

At the 24 July snapshot, the core three account for 11,792 commits: 8,317 mine, 2,748 from Veniamin, 727 from Max, and 158 from other contributors, bots, and alternate identities. Commit volume is not value. The relevant observation is that output increased after the agent workflow became more structured.

  • VibeQ holds human and agent tasks. Agents claim work through MCP, check for duplicates, and update the task as they work.
  • The Clanker Army turns reviewed plans into isolated worktrees and runs them in supervised batches.
  • Agent roles such as QA lead, security lead, and performance reviewer have written instructions in the repository.
  • Sirvant accepts a Slack request and can dispatch a disposable worker to investigate or implement it.
VibeQueue dashboard showing who's working on what, the bug pipeline, and the coverage-matrix quality gate

VibeQ shows active work, stalled reviews, bug priority, product hotspots, and the coverage gate used before release.

My work in that loop is to set scope, approve plans, use the product, review evidence, and decide what ships. Behaviour changes need tests, and every release passes a blocking quality gate.

One person owns the development branch each day and pushes to it directly. A short morning sync and handoff replace an internal pull-request queue. This works because branch ownership is explicit and the automated checks are blocking.

I wrote the broader argument behind this operating model in Two theories of a programmer. This page keeps the claim grounded in the Studio evidence.

When Veniamin joined QA, his weekly output was near twenty commits while he built the coverage matrix, anti-forgery checks, and agent workflows. Two months later, the weekly counts were 277, 309, and 188. The increase followed the QA system, not a change in typing speed.

The correction

Most numbers on this page measure what was built. The supplier portal running with an enterprise customer is the clearest evidence of real demand.

The repo’s own July assessment is blunt: we have shipped more than we have proved.

Fast implementation created more features than the team had proved it needed. Every feature adds documentation, support, billing cases, browser checks, and migration work. Agents can produce code, but they do not create demand or decide what should be removed.

Q3 therefore froze new tools, channels, and workflow steps unless approved explicitly. Work moved to activation, onboarding, rollback proof, and helping merchants reach a first approved publish.

Building quickly is no longer the main problem. Choosing what to build is.

So is it any good?

I also ran a structured self-audit. Ten reviewer agents, one per domain, inspected the code, schema, migrations, tests, and CI configuration. The repository then contained roughly 512,000 lines of handwritten TypeScript, 7,800 files, 162 database tables, and 4,751 test and spec files. Claude Fable combined the reports and rechecked the largest findings at file level. The scoring guide treated 5 as typical startup quality, 7 as solid production quality, and 9 or above as exceptional.

The verdict: 8.25 out of 10.

These were ten passes from one model family, not ten independent opinions. The result is a self-audit, not an external benchmark. Larger findings were checked again against the files before scoring.

the scorecard Jul 9, 2026 · 10 parallel reviewers
5 · typical startup7 · solid production9 · exceptional Overall 8.25 DOMAINS Testing & qualityData modelFrontend & design systemArchitectureSecurity 8.58.58.588 FEATURES Supplier portalIntegrations & APIOrchestratorAI toolsDAMBillingMarketing & SEOPIM 8.58.58.588887 057910
The 9 July self-audit on its stated scale. Hover or focus a bar to read the supporting note.

The strongest areas use executable checks. Import-safety tests protect architecture boundaries. The E2E coverage matrix requires a signed result from a real run. Static analysis checks organisation scoping, and the schema prevents cross-tenant links.

The audit also identified unfinished variant editing, limited channel sync beyond Shopify, storage quotas still in warning mode, several 2,000-line components, and circular imports in the library layer. Each confirmed finding received an implementation plan.

Rechecking reduced several findings. One suspected legacy billing path had no production callers. The reviewers also estimated that comparable scope would require more than 200 engineer-months in a conventional team. That estimate is directional, but it gives context for the roughly ten months spent here.


Studio also has exponential-backoff retries with jitter, per-operation circuit breakers on AI providers, content-based idempotency keys, Redis-backed rate limits, and restore-drilled database backups. They have no screenshots, but the product depends on them.

Try Sirv AI Studio → · Check the build record →

What users changed

A real supplier workflow turned the portal from a simple upload link into intake, review, and publishing.

What remains imperfect

I have shipped more than I have proved. Activation, onboarding, rollback evidence, and the unfinished PIM work matter more now than another tool.