Private product · sanitized case study · in active iteration
Ecom Image · E-commerce AI asset workbench
A full-pipeline workbench for e-commerce assets — collect → reference → generate → review → deliver — hardening from a local tool into a multi-tenant service with a controlled public trial.
- Role
- Solo developer
- Period
- 2026.07 – present (active iteration)
- Scale
- Private repo · 52 commits
- Status
- Release-gate driven · not public yet
The problem
E-commerce asset production has three real pain points: version explosion — the same product needs different styles per country / platform, and manual prompt-and-output management quickly spirals; reference-driven — good images are not conjured from nothing, operators first study what hot products are shipping and distill best-sellers into reference assets; cost & quality must close the loop — every generation costs compute, delivery needs QA, and opening to external users demands identity, isolation, quotas and a ledger.
Benchmarked for feature parity against an overseas e-commerce design SaaS, but with fully self-owned branding, backend, model routing and billing. Currently in active iteration — not a one-off demo.
System boundary
Runtime shape: Next.js web UI + unified Python API (single process) + Postgres / Redis / MinIO.
| Layer | Responsibility |
|---|---|
| Web (Next.js) | Inspiration feed, main workbench, AI tool workbench (in-canvas inline editing); same-origin /api/* proxy only — the browser never talks to any model SDK directly |
| Unified API (single Python package, domain modules) | projects (main pipeline + job executor), prompts (templates + style profiles), model_gateway (channel routing), billing (quote → ledger), qa, assets (storage proxy), crawler (collection scheduling), auth (identity & tenancy), brand_profiles |
| Infrastructure | Postgres (metadata), Redis (queues), MinIO (image objects, private bucket + signed URLs) |
- Main chain: Project → MarketVersion → GenerationJob → DeliveryAsset — one product one project, one market one version, delivery assets carry full lineage.
Key decisions
- 1
Dropped n8n and multi-service splits for a single modular FastAPI package
An orchestration engine is a liability for solo iteration — types, tests and deployment all converge into one Python package organized by domain, with a single uvicorn entrypoint. The early n8n orchestration was fully removed from the runtime (archived JSON only, never loaded).
- 2
Model Channel abstraction, not single-provider lock-in
A Channel = one upstream connection (auth, endpoint, model list, capability tags, priority); supports OpenAI-compatible / Gemini / Alibaba Bailian / Volcano Ark providers with capability-based routing and automatic fallback; keys stored as reference names only (api_key_ref), never plaintext; MOCK mode is dev-only and explicitly not an acceptance capability.
- 3
Hot-product collection → reference-image asset governance
Embedded APScheduler scheduling (business-friendly cron config), two-layer idempotent dedup (source+external ID, source URL), separate stores and tags for hot-product vs reference images, explicit "add to reference set" promotion; references + locale/platform style profiles + versioned templates assemble prompts.
- 4
No mock placeholders — as a hard rule
Core backend paths must be real implementations; faking projects, jobs, assets or billing with mocks is forbidden by repository rules.
- 5
Supabase issues identity only; authorization always in our API
FastAPI verifies JWKS asymmetric signatures (signature / issuer / audience / expiry / kid, with one bounded refresh for unknown kids); browser-claimed email / role are never trusted; local storage keeps subject mapping only, never passwords.
- 6
Invite-based controlled trial: harden first, open later
Invite codes stored as HMAC-SHA256 fingerprints, replay-protected, with persistent rate limiting and same-transaction consumption; if upstream account creation succeeds but local persistence fails, a compensating deletion fires, escalating to critical alerts; operator password resets require a reason and write redacted audit events.
- 7
Release-gate-driven rollout
Before any public trial, six gate categories must pass item by item — identity & access, tenant isolation & storage, credits & execution (quote / reserve / deduct / release all idempotent + immutable ledger), operator console, production runtime (config validated at boot, no exposed ports, backup/restore drill), staging demo evidence (including cross-tenant negative tests). Every item requires evidence; no gate, no open.
View sanitized architecture (Mermaid source) ›
The diagram uses generic role labels only — no competitor names, credentials or tenant data.
%% Ecom Image 脱敏架构图(公开版 · 2026-07 现役运行时)
%% 不含竞品名、真实域名、密钥、供应商内部细节
flowchart TB
User([运营 / 设计者])
Operator([平台运营者])
subgraph Web["Web UI · Next.js"]
Insp["灵感流首页<br/>热卖参考"]
Bench["主工作台<br/>Project → MarketVersion → Job → DeliveryAsset"]
Tools["AI 工具工作台<br/>画布内联 AI 编辑"]
Web2["同源 /api/* 代理<br/>浏览器不直连模型 SDK"]
end
subgraph API["统一 Python API · FastAPI 单进程(ecom 包)"]
Auth["auth<br/>JWT 验签(JWKS) · 邀请激活<br/>租户隔离 · 审计"]
Projects["projects<br/>主链路 + 任务执行器"]
Prompts["prompts<br/>模板 + 地区风格档案组装"]
Gateway["model_gateway<br/>Channel 抽象 · 能力路由 · fallback<br/>密钥只存引用"]
Billing["billing<br/>估价 → 报价/预占/扣减/释放 → 账本"]
QA["qa<br/>质量检查"]
Assets["assets<br/>资产 CRUD · 存储代理"]
Crawler["crawler<br/>内嵌调度 · 两层幂等去重<br/>爆款图 → 参考集升格"]
end
subgraph Infra["基础设施"]
DB[("Postgres<br/>元数据 / 租户 / 账本")]
Redis[("Redis<br/>队列支持")]
S3[("MinIO<br/>私有桶 + 签名 URL")]
end
IdP["身份提供方<br/>仅签发身份 · 授权在自有 API"]
Models["外部模型服务(多 provider)<br/>OpenAI 兼容 / Gemini / 百炼 / 方舟<br/>按能力路由"]
Sources["电商平台公开数据<br/>热卖榜 / 店铺 / 关键词"]
User --> Web
Web -->|同源| Auth
Auth --> IdP
Web --> Projects
Projects --> Prompts --> Gateway
Projects --> QA
Projects --> Assets
Gateway --> Billing
Crawler --> Sources
Crawler --> Assets
API --> DB
API --> Redis
Assets --> S3
Gateway --> Models
Operator -->|"console · 邀请 / 配额 / 通道管理<br/>敏感操作写脱敏审计"| Auth
Verification
- 37 pytest test files covering auth / assets / billing / brand_profiles / crawler / model_gateway / projects / prompts / shared; every commit ships its verification command and result (latest round: 27 passed);
- Web-side tsc --noEmit zero errors as a pre-commit gate;
- Production runtime boot validation: missing Supabase / Postgres / MinIO / migrations / model-channel config refuses to start;
- Known risks publicly recorded: some settings / log routes are marked as release blockers until tenant isolation completes.
Public artifacts
- Status: the product is still iterating; the public-trial release gates are not all passed yet (multi-tenant isolation in progress), so there is no public URL
- Test evidence maintained in-repo; screenshots and demos will be recorded with synthetic brand assets after gates pass
Redaction boundary
The following are intentionally excluded from this case study:
- Benchmarked competitor name, static assets and crawled data;
- Model-provider credentials and raw provider responses;
- Real merchant assets and unauthorized brand elements;
- Real invite codes, audit data, tenant data;
- Screenshots / demos always use synthetic brands and synthetic products.