Atelier
On site A|B testing for unsure frontend designs
Created on 24th April 2026
•
Atelier
On site A|B testing for unsure frontend designs
The problem your project solves
The broken internal loop
Every design team has the same workflow problem: feedback on landing pages is lost between a screenshot, a paragraph, and a guess.
- A PM scribbles "make it more premium" on a Figma comment.
- A designer tries three things in parallel, loses two of them.
- A dev implements one, and the stakeholder says "no, more like Aesop."
The iteration loop is serial, lossy, and opinion-driven. Current AI tools make it worse — one-shot regeneration means every variant overwrites the last, and the "more premium palette" suggestion comes back as generic AI slop: "use a modern color scheme", "refine the typography". Specifically what? Nobody knows.
Atelier fixes the loop. Every critique becomes a branch on an infinite canvas you can see, compare, and keep. Every suggestion is grounded in real landing pages crawled from the open web — so "make it premium" lands as "swap Inter for Cormorant Garamond 700 italic, use Aesop's #EDE5D8 parchment, ghost outlined CTA."
How you are solving it
Every round of feedback is a branch, not an overwrite
Atelier is an infinite canvas (React Flow) where every variant is a live node with an iframe thumbnail. Seed from a URL, paste HTML, or pick one of 6 curated aesthetic templates.
From there, three AI primitives:
- Fork with Claude — prompt ("make the hero warmer"), choose Haiku/Sonnet/Opus, get a new child node with full HTML rewritten. Streams in via SSE so users see progress, not a 30s spinner.
- Grounded Critics — name a target vibe ("premium luxury"). Genspark pulls 3 real landing pages matching that vibe, Claude reads them, and returns 4–8 concrete, severity-tagged suggestions that cite the real pages. Users approve which to apply; one rewrite ships them all.
- Drag-to-combine (Opus) — drag one variant onto another and Opus synthesizes them into a new branch with dashed edges showing which parent donated what.
And a zero-loss viewer: click Compare on any two nodes, both full pages render side-by-side with desktop/tablet/mobile viewports. Nothing is lost between branches.
Stack: FastAPI + SQLAlchemy backend, Vite + React + Tailwind + React Flow frontend, Supabase (Postgres + object storage), Render for deploy. All source at github.com/bchuazw/atelier.
Use of Genspark
Genspark turns Claude's critics from "AI slop" into "cite-your-sources"
The problem with AI critiques: ask an LLM "make this more premium" and it responds with "use a more refined palette, modernize the typography." Useless.
Our solution uses the Genspark CLI (@genspark/cli) as a grounded research layer for the Critics feature:
- User enables "Ground with Genspark research" in the Critics dialog and specifies a target theme ("premium luxury").
- Backend (
apps/api/atelier_api/providers/genspark.py) shells out togsk web_search→ pulls 3 real landing pages matching the theme (Aesop, Awwwards luxury category winners, Dribbble e-commerce). - Parallel
gsk crawlercalls on each URL → returns full page markdown. - That markdown is injected into Claude's critique prompt as "REAL-WORLD REFERENCES" context.
- Claude now returns suggestions like "Swap Inter for Cormorant Garamond 700 italic — every Awwwards luxury winner uses editorial serifs" and "Replace terracotta #c87050 with burnished gold #B89A5A, matching Dribbble's luxury category consensus."
- The UI renders the reference URLs as clickable chips so judges / users can verify the citations.
Architecture note: we initially tried batch_crawl_url_and_answer (one call, per-URL Q&A) but it returned "No content found" on the free plan for every URL we tested (including aesop.com and stripe.com). Fanning out N parallel crawler calls worked reliably and is still fast — ~10s for 3 sites on top of Claude's ~25s.
Windows subprocess fix: asyncio.create_subprocess_exec can't execute gsk.CMD (WinError 193). Switched to asyncio.to_thread(subprocess.run) which handles .CMD wrappers transparently.
Feature-flagged gracefully: if GENSPARK_API_KEY is missing or the gsk binary isn't on PATH, grounded critics silently degrades to Claude-only. Users see a "Genspark returned no references" notice; nothing breaks. On Render's Python runtime (no Node) this fallback kicks in, so the deployed demo runs Claude-only while the 2-minute video showcases the full Genspark pipeline.
Provider module: apps/api/atelier_api/providers/genspark.py
Wired into: apps/api/atelier_api/routes/critics.py
Use of Claude
Claude is the brain of every generative moment in Atelier
Four distinct Claude integrations, each picking the right model for the job:
- Fork rewrites (Haiku 4.5 / Sonnet 4.6 / Opus 4.7). Every "make the hero warmer" prompt calls Claude with the full current HTML + the user's instruction + project context. Streams back via SSE. Users pick the model from a compact picker — Haiku for 6-second drafts, Sonnet for production rewrites, Opus when they want the highest fidelity.
- Design Critics (Sonnet, default). Given target theme + optional Genspark grounding + current HTML, returns strict-JSON suggestions with category / severity / rationale tags. Users approve a subset; one composed prompt re-enters Claude to apply them all coherently.
- Drag-to-combine (Opus). Merging two sibling variants needs high fidelity reasoning about which stylistic choices to donate vs keep. Opus reads both HTMLs + the chosen aspects (typography / palette / layout / copy) and synthesizes a new variant that preserves the target's structure while importing only the listed aspects from the source.
- Feedback decomposition (AutoReason-style, Sonnet). Paste a stakeholder's multi-point paragraph; Claude extracts atomic change items with individual rationales. Users approve the checklist; one fork applies them all.
Prompt caching on the long system prompts (critic rubric, merge rubric) via cache_control: ephemeral — costs drop ~90% on follow-up calls within the same 5-minute window.
BYOK + fallback: users can POST their own key to /settings/api-key at runtime, or rely on the server-side ANTHROPIC_API_KEY. The /settings/status endpoint reports source-of-truth so the UI can warn "no key set."
Core call site: apps/api/atelier_api/providers/claude.py
System prompts: in apps/api/atelier_api/routes/ (fork, critics, merge, feedback — each has a cached system prompt).
What is the deployed URL for this project?
https://atelier-web.onrender.com
Tracks Applied (1)
