InkdownInkdown
Start writing

Bonkers

5 files·0 subfolders

Shared Workspace

Bonkers
BONKERS_END_TO_END_GUIDE.md

shubho-learning-bonkers

Shared from "Bonkers" on Inkdown

Bonkers — Interview Revision Sheet

Last updated: June 11, 2026 · Final pass — principal engineer review Use: Read top-to-bottom once, then §0 Cheat Sheet + §12 Scripts before interview Mental model: Bonkers = product · Wallflower = backend engine · Your work = v2→v3 rebuild


0. Cheat Sheet (60-second scan)

BONKERS_INTERVIEW_QUESTIONS.md
interview_questions.md
PROJECT_WALKTHROUGH_SCRIPT.md
shubho-learning-bonkers.md
ItemValue
ProductAI creative production — generate, edit, template, gallery (not chat-with-images)
Company / URLFoyer · getmerlin.in
Scale~50K generations/month (~1.7K/day, ~70/hr) — NOT 50K users
Impact+50% DAU · -30% latency · 10K template images month 1 (~20% of volume)
Stackbonkers/ frontend · merlin-arcane/ backend · /v1/wallflower/
Controllerunified-generation.controller.ts
StorageGCS wallflower-images/{uid}/{iid}.png · Firestore wallflower/{uid}/images/
Providers5: FAL · Replicate · OpenAI · Google Vertex · GoAPI
Models / Features / Templates20+ / 8 / 9
Killer differentiatorAbstract model mapping — Zod .transform(), zero frontend changes on provider swap
One sentenceCross-provider image engine — 5 providers, unified API, sequential failover, moderation, GCS normalization

Codenames: Cauldron = bonkers/ · Arcane = merlin-arcane/ · Wallflower = image API group


1. What & Why

What: Foyer's AI image creative production platform. Originally standalone, consolidated into Merlin monorepo. Users generate, edit (8 features), apply templates (9), browse a public gallery (likes/shares), and iterate on history via parent lineage.

Why:

  • One-shot tools (prompt → image → leave) don't retain users
  • Dedicated product with own plans (BONKERS_PRO / BONKERS_BASIC) separate from Merlin chat
  • v2 = text→image only → v3 = templates + image→image + multi-model + parallel execution

vs competitors:

vsBonkers wins because
ChatGPT/GeminiImage IS the product — 8 edit features, gallery, templates
MidjourneyMulti-provider web app, not Discord-locked
Ideogram/Flux playgroundsAbstract model IDs + cross-provider fallback
Canva/FireflyAI-native; templates = generation configs, not static files

2. Your Contribution — v2 → v3

Dimensionv2v3 (your rebuild)
Core actionText→image onceTemplate → generate → edit → remix → repeat
PipelineSeparate controllers per featureUnified unified-generation.controller.ts
InputText onlyText + image upload + mask
ModelsLimited20+ models, abstract IDs
TemplatesNone / saved promptsFirst-class Firestore configs
PerformanceSerialParallel post-processing, smart routing (-30%)
RetentionLowRepeat workflows (+50% DAU)
Routes/{lang}/old-bonkers · /image-generation/{lang}/bonkers · /unified-generation

4 pillars: (1) unified pipeline {feature, modelConfig, prompt, image?} · (2) abstract model mapping · (3) templates as product · (4) image→image + GCS presigned uploads + parent lineage + Photon mask inversion + Replicate↔FAL fallback

Hardest problems: provider format divergence (GCS normalize-once) · mask semantics (FAL mask_url vs Replicate inverted via getInvertedMaskUrl()) · unifying 8 API shapes · legacy quota keys (wallflower vs bonkers)

Shipped: weekly release train · feature flags · Vercel instant rollback · old-bonkers kept during migration

Legacy migration: monitor both → legacy delegates to unified → 308 + deprecation header → remove after 30 days zero traffic (preserve quota keys)

+50% DAU attribution (if challenged): 4-week before/after, day-of-week controlled, cohort new vs returning, checked novelty decay, feature flags isolated other launches

2-min STAR: v2 one-shot, users didn't return → rebuild creative production → unified pipeline, abstract models, templates, GCS normalization, fallback → +50% DAU, -30% latency, 10K template images month 1


3. Abstract Model Mapping (core pattern)

Users never see black-forest-labs/flux-schnell or fal-ai/ideogram/v3. They see abstract IDs. Resolution = Zod .transform() before controller runs.

User-facingAbstract IDResolves toQuery cost
Bonkers Litebonkers-liteprunaai/hidream-l1-fast10 / image
Bonkers Advancebonkers-advancefal-ai/ideogram/v3120 / image
Bonkers Magic Fillbonkers-magic-fillfal-ai/ideogram/v3/edit(inpaint tier)

Pricing override: bonkers-advance = 120 queries even though Ideogram V3 underlying cost = 75. Controller explicitly overrides usageConfig.queries = numberOfImages * 120. Intentionally decouples abstract pricing from provider cost — premium tier + rate limiter.

Benefits: provider swaps without frontend changes · model deprecation = remap one Zod map · A/B routing · business pricing independent of provider $


4. Eight Features + Nine Templates

#FeatureProvider / modelResilienceOne-liner
1GENERATEAny model✅ Replicate ↔ FAL fallback20+ models, auto-failover
2INPAINTMask fill⚠️ Photon SPOF for ReplicateCross-provider mask inversion
3UPSCALEfal-ai/clarity-upscaler❌ FAL onlyOne-click resolution boost
4ERASEfal-ai/bria/eraser❌ FAL onlyAI object removal
5EDIT_BGfal-ai/bria/background/replace❌ FAL onlyBackground swap, no subject refs
6OMNI_EDITfal-ai/flux-pro/kontext/multi❌ FAL onlyMulti-image edit
7TEMPLATEPer-template provider⚠️ Provider lockOne-click styled generation
8REMIXGPT Image 1❌ OpenAI onlyImage→image (your v3 addition)

9 templates: Ghibli · Minecraft · Simpson · Pixar · Humanize My Pet · Watermark Remover · Make Me Bald · Product Photography · Logo Wizard

  • Firestore: {id, promptTemplate, modelConfig, style, thumbnail, category, version}
  • Versioned — frontend requests latest; model deprecation = remap abstract layer only
  • 10K images month 1 = ~20% of ~50K total

User-facing extras: creations gallery (/{lang}/creations/[iid]) · public feed + likes · parent lineage · SSE progress · SEO/OG descriptions · ImageKit CDN · dual entry (Bonkers UI or Merlin chat tool)


5. Six Platform Layers

LayerMechanismInterview detail
Abstract modelsZod .transform()See §3
FallbackFALLBACK_MODELS_MAP + sequential callWithFallback()GENERATE only; inexact OK (Ideogram V2 → Flux Pro)
Magic promptMAGIC_PROMPT_SYSTEM_PROMPT + MAGIC_PROMPT_MODELSPer-feature LLM before provider
GCS normalizationgetAttachmentWithGBucketUrl()Download temp provider URL → permanent GCS
ModerationPre: checkPromptFlagged() · Post: isImageFlagged() (templates only)Pre = block-before-spend; fails open on bad JSON
Style systemPRESET_STYLES_MAP + getStyleModifiedPrompt()Provider-specific application

Magic prompt per feature:

FeatureModelOutput
GENERATEGPT-4o-mini{ enhancedPrompt } ≤1000 chars
INPAINTGPT-4o{ enhancedPrompt, isRemoveOnly } — "remove car" vs "replace with tree"
EDIT_BGGPT-4o-miniBackground only — never "the subject" / "the person"
GHIBLI / Product / LogoGPT-4o-miniHyper-detailed style system prompts
OFFDefaultse.g. isRemoveOnly: false, imageStrength: 0.8 for GHIBLI

9 style presets: Auto · Anime · Realistic · Digital Art · Vintage · Cinematic · Fantasy · Neon Noir · Minimalist

  • Ideogram → native ideogramStyle param · Recraft → recraftStyle API param · Others → append to prompt
  • Exception: Recraft V3 Realistic skips prompt append · Ideogram V2 Turbo returns prompt unmodified (native style)

6. Request Flow — Middleware + 11 Steps + SSE

Plain text

Phase 0 — Middleware: Firebase JWT (authMiddleware) → usageLimits (block over-quota / free guests on FEATURE_LIMITS.bonkers) → fail = controller never runs

StepWhatNote
1Zod validationprompt, modelConfig, feature, style, numImages, isPublic
2Auth + usage confirm—
3checkPromptFlagged()Blocking — saves provider $
4improvePrompt() magic prompt~700 tokens
5Abstract model .transform()bonkers-advance → fal-ai/ideogram/v3
6Prefix dispatch (helpers/generate.ts)See §7
7callWithFallback()2–30s — slowest step
8formatImageGenerations()See §8
9Firestore savewallflower/{uid}/images/
10SSE eventsattachments + usage
11incrementUserUsage()Charge abstract model query cost

SSE lifecycle: streamer.init → progress message → [provider 2–30s] → attachments (image) → usage (quota) → attachments (Firestore doc ID) → close

SSE event types: message (progress) · attachments (image) · usage (quota) · metadata

Why SSE not WebSockets: HTTP, no sticky sessions on Cloud Run, proxy-safe, reuses repositories/streamer/

Client: @microsoft/fetch-event-source — native EventSource can't POST or send Firebase JWT; handles parse, reconnect, AbortController + Redis STOP_GENERATING

isToolCall (Merlin chat tool): skips SSE → JSON response; skips GCS in post-processing; same provider handlers

Error gap: no explicit error SSE event — connection drops, frontend detects disconnect


7. Smart Routing & Fallback

NOT parallel providers — would 2× API cost every request.

Prefix dispatch (helpers/generate.ts):

Model prefixHandlerTry first
black-forest-labs/*, recraft-ai/*, ideogram-ai/*handleReplicateWithFalAIFallback()Replicate
fal-ai/*handleFalWithReplicateFallback()FAL
gpt-image-1-*OpenAI handlerOpenAI
gemini-*Google VertexGoogle
midjourney-*GoAPI handlerGoAPI

Fallback: sequential callWithFallback() — primary ANY error → FALLBACK_MODELS_MAP (10+ bidirectional Replicate↔FAL). Inexact mappings exist (something > nothing). Only GENERATE — 4 edit features have no equivalent.

-30% latency sources: parallel SEO (Promise.allSettled) · unified pipeline (one middleware chain) · native-provider-first · GCS normalize-once

Parallel post-processing: runs AFTER provider returns inside formatImageGenerations() — SEO + GCS per variation. 4 variations ~500ms vs ~2000ms serial. Does NOT speed provider gen (still 2–30s). SEO still blocks SSE — fix = Cloud Tasks.


8. Post-Processing & Data Model

formatImageGenerations() — 5 steps:

  1. Aspect ratio — auto-detect via Photon getDimensionsFromImage(); fallback 1024×1024 if Photon fails
  2. SEO — describeImage() GPT-4o-mini per variation, parallel via Promise.allSettled (OG tags)
  3. GCS upload — download temp provider URL → wallflower-images/{uid}/{iid}.png permanent URL
  4. Parent lineage — parentImage / parentImages for edits, remix, templates
  5. Cost calc — queryCost * numberOfImages from IMAGE_MODELS_INFO

GCS→Firestore sequencing risk: GCS first, then Firestore — if Firestore fails = orphaned image in GCS. Fix: write-ahead Firestore pending → update complete after GCS.

Firestore image doc fields: prompt · enhanced prompt · model ID · style · GCS URL · seed · aspect ratio · likes [] · visibility · metadata · parent refs

Public feed: /v1/wallflower/images · likes per image · daily questions

Photon: getDimensionsFromImage() + getInvertedMaskUrl() — if down: Replicate INPAINT/ERASE fail; dimensions fall back 1024×1024

ImageKit CDN: transformed delivery URLs · gap: 0–5s propagation race on fresh uploads (404 briefly)


9. Architecture & Scaling

Plain text
LayerDetail
Cloud Run0→N autoscale · stateless · 6GB RAM · 60min timeout · us-west1 · shares container with chat
ProvidersThey scale GPUs — Bonkers = orchestrator
FirestoreImage subcollections scale; customers/{uid} = 1 write/sec bottleneck
Redisrate-limiter-flexible · IRC pub/sub · STOP_GENERATING TTL cache

Comfortable at 50K gens/month. At 10× (~500K):

BottleneckFix
Firestore usage counterRedis-sharded distributed counters
SEO blockingAsync via Cloud Tasks
Gallery SSRISR + on-demand revalidation
Photon SPOFInline JS + circuit breaker
FAL outage5/8 features down (no fallback)
No decision loggingSentry breadcrumbs per pipeline step

Per-generation resources: 1 Cloud Run req · 1 image Firestore write · 1 usage read+write · 1 GCS upload · 0–2 LLM (mod + magic) · 0–4 LLM (SEO) · 1 provider API call

Key design decisions: express-zod-api (OpenAPI + types) · SSE over WebSockets · AsyncLocalStorage request context · Firestore schema-on-read · Rune Cloudflare Worker for LLM proxy (magic prompt/moderation)

Interview framing: "Scalable today as serverless orchestrator. Bottlenecks at 10× are documented with fixes — roadmap, not current failure."


10. Quota & Auth (one section, minimal)

Feature keyWho consumes
bonkersBONKERS_PRO / BONKERS_BASIC subscribers
merlinFree/PRO/TEAMS/ELITE using image gen via chat — 1 FLUX Pro image (140 queries) can exhaust daily chat quota
wallflowerLegacy /image-generation endpoint only

Flow: firebase.auth().getIdToken() → Axios Authorization: Bearer → authMiddleware.verifyIdToken() → load customers/{uid} → usageLimits middleware → controller


11. Known Gaps + Fixes (say proactively)

#GapFix
14/8 features die on FAL outageAdd redundant providers for edit features
2GCS orphan on Firestore failureWrite-ahead pending status
3Moderation fails open on bad JSONtry/catch → default flagged: true
4Regenerate inconsistencyMagic prompt temp > 0; fallback changes model; seed not tied to concrete modelId
5Post-gen moderation templates onlyExtend isImageFlagged() to all features
6SEO blocks response 500ms–2sAsync Cloud Tasks
7No real per-provider $ trackingIMAGE_TOKEN_TO_QUERY_RATIO is fictional
8Firestore usage hotspotRedis counter shards
9ImageKit CDN raceRetry/poll or serve GCS directly until propagated
10No error SSE eventAdd explicit error event type
11No pipeline decision loggingSentry breadcrumbs (chat has decisionLog, images don't)

12. Interview Scripts

Elevator (15 sec):

Foyer's AI image creative production platform — generate, edit, template, gallery. Multi-provider engine with abstract models and unified 8-feature pipeline.

Walk through a request (30 sec):

Firebase auth and quota middleware, then unified controller: Zod validate, block-before-spend moderation, magic prompt, abstract model resolve, prefix-based provider dispatch with sequential fallback, post-process to GCS, save Firestore, stream via SSE — progress, image, quota. SSE over WebSockets because Cloud Run autoscales without sticky sessions.

Your contribution (30 sec):

Led v2→v3 from one-shot generator to template-first creative production — unified cross-provider pipeline, abstract models, templates as product. +50% DAU, -30% latency, 10K template images month 1.

Abstract models (20 sec):

Users see bonkers-lite and bonkers-advance, not provider IDs. Zod transform resolves before the controller. Provider swap = one map update, zero frontend changes. bonkers-advance intentionally costs 120 queries — decoupled from underlying provider cost.

Scaling (25 sec):

50K generations/month, not users. Stateless Cloud Run orchestrator, providers handle inference, GCS stores, ImageKit serves from edge. Comfortable today; at 10× I'd shard Firestore usage counters via Redis.

Parallel vs routing (25 sec):

Promise.allSettled parallelizes SEO after provider returns — not parallel providers. Smart routing = prefix dispatch, native provider first, sequential fallback on error. -30% latency = post-processing + unified pipeline, not faster models.

INPAINT probe (15 sec):

GPT-4o returns isRemoveOnly boolean — distinguishes "remove the car" from "replace with tree". FAL uses mask_url; Replicate needs inverted mask via Photon getInvertedMaskUrl().

Fallback probe (15 sec):

FALLBACK_MODELS_MAP, 10+ bidirectional Replicate↔FAL equivalents, sequential only. Inexact fallbacks exist. ERASE, UPSCALE, EDIT_BG, OMNI_EDIT have zero fallback — FAL outage kills 5/8 features.

2-min walkthrough outline:

  1. Big picture — Bonkers at getmerlin.in, Wallflower backend, 50K gens/month
  2. Abstract models — why, how, pricing override
  3. 8 features — unified pipeline, GCS normalization
  4. Click Generate — 11 steps, SSE lifecycle
  5. Your v2→v3 story + impact numbers
  6. Honest gaps — FAL dependency, moderation fails open, usage hotspot

13. Probe Q&A (quick follow-ups)

They askYou say
Why not WebSockets?Sticky sessions on Cloud Run; SSE = HTTP, autoscale-friendly
Why @microsoft/fetch-event-source?EventSource can't POST or send Firebase JWT
50K users?No — 50K generations/month, ~1.7K/day
Scalable?Yes today; bottlenecks at 10× with known fixes
Promise.allSettled speed up gen?No — speeds post-processing SEO/GCS after provider returns
What if FAL goes down?GENERATE degrades via fallback; 4 edit features + templates on FAL-only models break
Regenerate gives different image?Magic prompt non-determinism + fallback may switch provider; seed tied to model
ImageKit 404 on fresh upload?CDN propagation race 0–5s — image exists in GCS
Free users?Blocked at usageLimits — never reach controller
Chat tool vs direct Bonkers?isToolCall skips SSE/GCS; same engine underneath
Templates vs saved prompts?Firestore configs with versioned model+prompt — product feature, not user saves
NDA / no code?Walk architecture and data flow; reference codenames and patterns not proprietary keys

14. Key Files

PathRole
endpoints/wallflower/unified-generation.controller.tsCentral orchestrator
unified-generation.schema.tsZod + abstract model .transform()
helpers/generate.tsPrefix routing + callWithFallback()
repositories/streamer/SSE server engine
middlewares/usageLimits/Quota gate
utilities/usage.tsincrementUserUsage()
Provider helpersreplicate/ · fal-ai/ · ideogram/ · openai-image-gen.ts · google-image-gen/

Companion services: Photon (dimensions + mask inversion) · Session Manager (JWT cookie chunking) · LlamaIndex (RAG — decoupled)


15. Skip (Merlin ecosystem, not Bonkers engine)

Chrome extension · MCP · Deep Research · Context window engine · Tool orchestrator · Monorepo/Turbo · i18n · Stripe internals · Auth deep dive · System design hypotheticals (collaborative canvas, 100K DAU feed — not built)