Grail

Drop a photo. Choose a scene. Own every platform.

The Problem

Small brands and solo creators need platform-specific marketing assets for every product and every campaign. A Shopify listing needs a clean white background. Instagram needs lifestyle photography. TikTok needs vertical editorial. Email needs a wide hero. Each format requires different dimensions, different backgrounds, different visual treatment.

Professional product photography costs thousands per shoot. Design tools require hours of manual work. AI generation tools produce backgrounds that look synthetic because they don't know your actual product.

What Grail Does

Asset Format Pipeline
Product Listing 1:1 · 1000px white e_background_removal + e_shadow + b_white,c_pad
Instagram Post 1:1 · 1080×1080 e_gen_background_replace + c_fill,ar_1:1 + text overlay
Story / TikTok 9:16 · 1080×1920 e_gen_background_replace + c_fill,ar_9:16 + text overlay
Banner Ad 16:9 · 1920×1080 e_gen_background_replace + c_fill,ar_16:9 + text overlay
Email Header 3:1 · 1800×600 e_gen_background_replace + c_fill,ar_3:1 + text overlay

How It Works

  1. User uploads a product photo via Cloudinary Upload Widget (unsigned preset). Cloudinary returns a public_id.
  2. User selects a scene preset (Luxury, Studio, Nature, Urban, Tech, Café, Fashion, Beach) or types a custom prompt.
  3. A live 380px scene preview renders immediately via e_gen_background_replace — users see the AI result before committing to all 5 assets.
  4. On "Generate", Grail constructs 5 Cloudinary transformation URLs in the browser. No server call. No job queue.
  5. Each URL encodes the full AI pipeline. Cloudinary processes and caches on its CDN. Cards render as each image loads.
  6. Users download via fl_attachment or copy the CDN URL for use anywhere.

What Makes It Different

Everything is a URL. The entire transformation pipeline — AI background replacement, aspect-ratio cropping, text overlay, smart delivery — is encoded in a single Cloudinary URL computed client-side. There is no backend, no storage beyond what Cloudinary handles, and no batch job. Share a URL, embed it, use it in any CMS — it just works.

Live scene preview. Other tools make you wait for a full generation before you see results. Grail shows a live preview tile that updates every time you change scenes — so you know what the AI chose before clicking Generate.

Real product, any world. e_gen_background_replace detects the subject and rebuilds only the background from the prompt. The product stays real. The scene is AI-generated. The result looks like a shoot that cost $3,000.

Tech Stack

  • React 19 + Vite + TypeScript
  • Cloudinary — Upload Widget, AI Background Removal add-on, Generative AI (e_gen_background_replace)
  • Zero backend. Zero database. Zero servers.

Challenges

  • Encoding Cloudinary generative AI prompts in URL-safe format (spaces → underscores, stripping special characters) while preserving enough semantic content for quality generation.
  • Managing loading state for the live scene preview: using key={previewUrl} on a self-contained ScenePreview component to remount and reset loaded state on every scene change without layout flicker.
  • Designing text overlay positioning that works across all 5 aspect ratios from a single source image, without knowing where in the frame the AI will place the product.
  • The fl_attachment download trick to force browser download instead of opening the CDN URL in a new tab.

What's Next

  • ** Connect and Upload directly to platforms**
  • Regenerate per-card — re-request a new AI variation by appending a random seed to the transformation
  • uu*brand kit* — user uploads a logo, grail overlays it on every asset at a consistent position
  • video support — extend to reels/tiktok clips with motion using cloudinary-video-player
  • Batch mode — upload a CSV of public IDs, get a ZIP of all assets for every SKU

Built With

Share this project:

Updates