← Back to demo
1. System Architecture (Production)
Cloudflare edge + serverless GPU + Shopify storefront. Green = Foxetales side, orange = Vendor (em build), blue = 3rd party.
🟢 Foxetales
🟠 Vendor (Paul/Weaverse build)
🔵 3rd party
graph TB
subgraph Foxetales["🟢 Foxetales (Customer-facing)"]
ST[Shopify Storefront
foxetales.com]
ADMIN[Foxetales Admin
order management]
end
subgraph Vendor["🟠 Vendor — Paul/Weaverse"]
WORKER[Cloudflare Worker
/api/generate-page
/api/preview]
QUEUE[Cloudflare Queue
job orchestration]
R2[(Cloudflare R2
customer photos
rendered pages)]
KV[(Workers KV
job status
session state)]
end
subgraph GPU["🟠 GPU Worker"]
RUNPOD[RunPod Serverless
A100 80GB
FLUX+PuLID+LoRA]
end
subgraph ThirdParty["🔵 3rd party"]
STRIPE[Stripe
payments]
SENTRY[Sentry
error tracking]
PRINT[Print fulfillment
vendor TBD]
end
CUST([👤 Customer]) -->|upload photo| ST
ST -->|POST /preview| WORKER
WORKER -->|enqueue| QUEUE
WORKER -->|store| R2
QUEUE -->|invoke| RUNPOD
RUNPOD -->|read assets| R2
RUNPOD -->|write result| R2
RUNPOD -->|update status| KV
WORKER -->|poll status| KV
WORKER -->|return URL| ST
ST -->|preview shown| CUST
CUST -->|checkout| STRIPE
STRIPE -->|webhook| WORKER
WORKER -->|trigger full book| QUEUE
WORKER -->|order fulfilled| PRINT
PRINT -->|ship| CUST
WORKER -.->|errors| SENTRY
ADMIN -->|regen / approve| WORKER
classDef fox fill:#d3f9d8,stroke:#2f9e44,stroke-width:2px
classDef vendor fill:#ffe8cc,stroke:#e8590c,stroke-width:2px
classDef gpu fill:#fff3bf,stroke:#f59f00,stroke-width:2px
classDef third fill:#e7f5ff,stroke:#1971c2,stroke-width:2px
class ST,ADMIN fox
class WORKER,QUEUE,R2,KV vendor
class RUNPOD gpu
class STRIPE,SENTRY,PRINT third
2. End-to-End Sequence (Customer Journey)
Từ lúc customer upload đến khi nhận sách in: chia 2 giai đoạn — preview (immediate ~20s) và full book gen (background ~10 min) sau khi thanh toán.
sequenceDiagram
actor C as Customer
participant SF as Shopify Storefront
participant W as CF Worker API
participant Q as CF Queue
participant GPU as RunPod GPU
participant R2 as R2 Storage
participant S as Stripe
participant P as Print Vendor
Note over C,SF: Phase 1 — Preview (live, ~20s)
C->>SF: Upload kid photo
SF->>W: POST /preview {photo, book_id}
W->>R2: Store photo
W->>Q: Enqueue preview job (3 pages)
Q->>GPU: Run pipeline × 3
GPU->>R2: Read template assets
GPU->>R2: Write 3 preview pages
GPU-->>W: Job done (status callback)
W-->>SF: Preview URLs
SF-->>C: Show 3 personalized pages
Note over C,P: Phase 2 — Order fulfillment (background, ~10 min)
C->>SF: Approve preview, checkout
SF->>S: Process payment
S-->>W: Webhook: order paid
W->>Q: Enqueue full book (35 pages)
Q->>GPU: Render all 35 pages
GPU->>R2: Write all pages
GPU-->>W: All done
W->>P: Send book PDF + ship address
P-->>C: Ship printed book (5-7 days)
3. AI Pipeline Detail (Iter 7 — Per Page)
Bước-by-bước xử lý 1 page cho 1 customer. Đây là pipeline đã validated trong iter 7, khác đáng kể với planning ban đầu (không còn ControlNet, có thêm skin shift postproc).
flowchart TB
INPUT_PHOTO[📷 Customer Photo
kid face JPG/PNG]
INPUT_TPL[🎨 Template Assets
background.png
character.png
person_mask.png]
INPUT_PROMPT[📝 Ethnicity prompt
vd: 'Vietnamese Asian']
PULID[🎭 PuLID Identity Extraction
InsightFace + EVA-CLIP
→ identity embedding]
MASK[🎯 Mask Prep
GrowMask +2
FeatherMask 12px]
COND[🧠 Conditioning
CLIP-L + T5-xxl
+ ethnicity prompt
+ skin anchor]
KS[⚡ FLUX KSampler
FLUX.1-dev 23GB
+ Foxetales LoRA v4 0.7
+ PuLID inject
denoise 0.55, steps 25]
VAE[🔄 VAE Decode
latent → RGB 1024×1024]
COMPOSITE[🖼️ Composite
blend char + background
via feathered person mask]
DECISION{Black/dark
ethnicity?}
SKIN[🌓 Skin Shift Postproc
YCbCr detection × person mask
RGB multiply per preset]
OUTPUT[📤 Final Page
1024×1024 PNG ~1MB]
INPUT_PHOTO --> PULID
INPUT_TPL --> MASK
INPUT_PROMPT --> COND
PULID --> KS
MASK --> KS
COND --> KS
INPUT_TPL --> KS
KS --> VAE
VAE --> COMPOSITE
INPUT_TPL --> COMPOSITE
COMPOSITE --> DECISION
DECISION -->|yes| SKIN
DECISION -->|no, Asian/Blonde| OUTPUT
SKIN --> OUTPUT
classDef input fill:#e7f5ff,stroke:#1971c2
classDef process fill:#fff3bf,stroke:#f59f00
classDef output fill:#d3f9d8,stroke:#2f9e44
classDef decision fill:#ffe8cc,stroke:#e8590c
class INPUT_PHOTO,INPUT_TPL,INPUT_PROMPT input
class PULID,MASK,COND,KS,VAE,COMPOSITE,SKIN process
class OUTPUT output
class DECISION decision
4. Tech Stack Layers
Component breakdown theo layer: UI → API → Orchestration → AI → Storage → External services. Layer thấp phục vụ layer cao hơn.
graph LR
subgraph UI["UI Layer"]
SHOPIFY[Shopify Theme
Hydrogen/Weaverse]
DEMO[Demo page
Next.js]
end
subgraph API["API Layer (CF Workers)"]
REST[REST endpoints]
WS[WebSocket status]
AUTH[Auth/JWT]
end
subgraph ORCH["Orchestration"]
Q[CF Queue]
SCHED[Cron triggers]
end
subgraph AI["AI Layer (RunPod)"]
CFY[ComfyUI runtime]
FLUX[FLUX.1-dev]
PUL[PuLID-Flux]
LORA[FoxeTales LoRA v4]
POST[skin_shift.py]
end
subgraph DATA["Storage"]
R2D[R2 — files]
KVD[KV — state]
D1[D1 — orders]
end
subgraph EXT["External"]
STR[Stripe]
PRT[Print vendor]
MON[Sentry/PostHog]
end
UI --> API
API --> ORCH
ORCH --> AI
AI --> DATA
API --> DATA
API --> EXT
AI --> POST
5. Data Flow (Storage View)
Lifecycle của 1 file từ upload đến delivery.
flowchart LR
UP[Customer upload
~5MB JPG] -->|store| RA[(R2: photos/
customer_id/
original.jpg)]
RA -->|read| GPU1[GPU: PuLID extract]
GPU1 -->|cache| KV1[(KV: pulid_emb/
customer_id
TTL 24h)]
KV1 -->|reuse| GPU2[GPU: render N pages]
GPU2 -->|store result| RB[(R2: pages/
order_id/
page_NN.png
~1MB each)]
RB -->|read for PDF| PDF[PDF assembler]
PDF -->|store| RC[(R2: books/
order_id/
full_book.pdf)]
RC -->|download URL| PRT[Print vendor]
RB -->|preview URL| ST[Shopify storefront]
6. Iter Evolution (How we got here)
timeline
title FoxeTales AI Pipeline — Iter History
section Phase 1 — Style training
Iter 1-3 (2026-04) : Foxetales style LoRA v1-v3 : ~75 watercolor match
Iter 4 (2026-05-15) : LoRA v4 (1000 steps) : 93 watercolor match : PRODUCTION
section Phase 1 — Face swap
Iter 5 (2026-05-20) : PuLID-Flux integration : zero-shot identity transfer
Iter 6 (2026-05-25) : Face mask workflow : Halo + style fixed
section Phase 1 — Polish
Iter 7a (2026-05-26) : Polish tuning : Halo 68→82, Style 63→78
Iter 7b (2026-05-27) : Chi feedback : Full-character mask
Iter 7c (2026-05-28) : Skin shift postproc : Black ethnicity workaround
section Phase 2 — Production
Phase 2 : ControlNet pose preservation
: LoRA v5 diverse skin retrain
: Worker API + demo storefront
: RunPod serverless deploy