Allie's Code Challenge 1.0 — Build a real promotional Undress demo for Joip in an afternoon.
— Six steps from cold start to a live URL: a standalone Undress demo that gives visitors one free generation, then funnels them straight into signup. By the end of the day, you'll have built a real lead magnet and learned the agentic coding workflow you'll use every week from here on.
What you're walking into.
Six steps. A real, deployed product at the end. We're rebuilding Joip's Undress feature as a standalone demo that gives visitors one free generation — then funnels them into signup. You'll write almost no code by hand and run almost no terminal commands by hand. You'll be directing Claude Code — Anthropic's command-line agent that lives on your laptop and can create folders, scaffold apps, install tools, push to GitHub, and deploy to Cloudflare on your behalf. Your job is to describe what you want; Claude's job is to make it real. The skill we're building is fluency at directing AI, not memorizing syntax.
What you'll build
A standalone Undress demo on its own domain. Visitors get one free generation, then a beautifully-styled nudge to sign up at Joip for unlimited.
How long it takes
Four to six focused hours from cold start to live URL — broken into six bite-sized steps you can pause and resume anytime. Your progress and notes save automatically.
What you'll learn
How to direct Claude through every step — from creating folders and connecting accounts to scaffolding the app and shipping it. The skill that compounds: writing prompts that get great results on the first try.
What you'll need
A laptop with Claude Code installed (it's the very first thing in Step 1), a Cloudflare account (free), a GitHub account (free), and roughly $10 for a domain. I'll send the API keys separately.
Three manual installs. One Cloudflare signup. That's it.
After today, the only terminal command you'll type by hand is claude — to
open Claude Code. Everything else, including running other commands, goes through prompts
in plain English. This step is just the unavoidable manual setup.
1 · Install Warp (your terminal). A "terminal" is the text app where Claude Code runs. macOS ships with one called Terminal.app, but I strongly recommend installing Warp instead — it's a modern terminal with a beautiful UI, native AI helpers, copy-able command blocks, and persistent sessions that don't forget your work when you close a tab. Grab it at warp.dev (free for personal use). Apple Terminal works too if you'd rather skip it.
2 · Install Claude Code. This is the only tool you can't ask Claude to
install for you (because Claude doesn't exist on your machine yet!). Go to
claude.com/claude-code,
run the installer, and sign in with the same Anthropic account you use for chat. Then in
your terminal type claude and hit Enter. That's the one and only
terminal command you'll type by hand all day. A chat prompt opens — congrats,
you're now talking to your new collaborator.
3 · Open a Cloudflare account and buy a domain. Cloudflare gives away static-site hosting (Pages), DNS, and SSL for free, and sells domains at wholesale — no GoDaddy markup. We're spinning up a real product on a real domain for the cost of one coffee, with zero monthly bills until traffic gets serious. Sign up takes three minutes. Confirm your email, enable two-factor auth (never run infrastructure on a single-password account), then head into Domain Registration and grab the name you want.
That's everything manual. From Step 2 onward, every command — node -v,
claude update, npm install, git push,
wrangler login, all of it — gets run by Claude on your behalf. You just
approve as it goes.
You type what you want in plain English ("scaffold a fresh Vite app in this folder").
Claude proposes the actual command ("I'll run npm create vite@latest
undress-demo -- --template react-ts — OK?"), waits for your approval, then
runs it and shows you the output. You stay in control: read the proposal, hit
Yes, or steer it differently. Anything destructive (deleting files,
force-pushing) it asks twice. You'll get the rhythm in five minutes.
Brainstorm 5–10 domain names before you search — verbs that describe the tool work
great (undressly.com, joipdemo.com). Skip hyphens. Verified
prices: .com is around $10/yr, .io is $50, .ai is $70
(overpriced but the vibes carry).
Once you're in Cloudflare, copy your Account ID from the right side of the dashboard into your notes below. Claude will ask for it when it sets up the deploy.
Your notes
One prompt. Claude does everything.
Open Claude Code, hand it Joip's design system, and send the brief below. It checks your dev tools, installs anything missing, scaffolds a fresh app, sets up CLAUDE.md, and starts the dev server. Your only job is to approve as it goes — you won't type a single command.
Download DESIGN.md below — it's Joip's design system in one file. Drop it on your Desktop. The single move that separates great results from generic AI output is handing this to Claude up front. Without it, AI defaults to "modern SaaS" looks: gradients you didn't ask for, default fonts, purple buttons. With it, the look is Joip from the first component.
Open Claude Code from your Desktop folder, drop the DESIGN.md file in, and send the first
prompt below. Claude will propose creating a folder, running npm create vite,
installing deps, and starting the dev server. You'll see each action before it runs — hit
Yes when it asks. You don't type a single command.
Three things every prompt should have: (1) the goal — what you want at the end; (2) the constraints — design system, file conventions, anything we can't change; (3) the success check — how you'll know Claude actually understood. Skip any of these and you'll spend the next ten prompts correcting course.
I'm starting a new project called undress-demo. The DESIGN.md file currently sits on my Desktop — that's Joip's design system, read it carefully before doing any visual work; we'll match it on every component. Please do all of the following yourself, asking my approval before each command: 1. Make sure your CLI is up to date: run claude update if you haven't recently 2. Verify Node.js is installed (node -v). If it's missing, install nvm and the latest LTS Node, then continue 3. Verify git is installed; install if needed 4. Create the folder ~/Desktop/undress-demo and cd into it 5. Scaffold a fresh Vite + React + TypeScript app there 6. Move DESIGN.md from ~/Desktop into the project root so it travels with the code 7. Install dependencies and start the dev server 8. Write a CLAUDE.md at the project root that briefly describes the project, the tech stack, the build/dev commands, and a one-line pointer to DESIGN.md as the visual source of truth — so future sessions in this folder remember our setup 9. When the dev server is up and CLAUDE.md is written, summarize the three most important rules from DESIGN.md in your own words — proof you actually read it I'll approve each step. I won't be typing any of these commands myself.
/help — list every command. /clear — wipe the conversation
and start fresh (do this when Claude's context feels bloated, ~every hour of work).
/init — auto-generate or refresh CLAUDE.md from the project
(alternative to having Claude write it directly, like in the prompt above).
Esc — interrupt Claude mid-action if it's heading the wrong way; then
tell it what to do differently. Ctrl+C twice — quit Claude entirely.
Claude reads CLAUDE.md at the start of every session in this folder. It's
the project's persistent memory — your conventions, your build commands, your design
system, your gotchas. Treat it like the README you wished every project had. It saves
you from re-explaining the same context every morning.
Your notes
Three prompts: GitHub, Cloudflare, live URL.
Claude creates the private repo, pushes the code, sets up the Cloudflare Pages project, and confirms the first deploy. You handle two browser logins along the way. That's it.
Quick concept first. Localhost is your laptop running a tiny private web
server (Claude already started it in Step 2 — that's the
http://localhost:5173 URL). Save a file → the browser refreshes. That's your
iteration loop. Production is your live domain. The bridge between them is
the publish loop: git push sends your work to GitHub, and Cloudflare
watches GitHub and auto-deploys. After today's one-time setup, every push lands on your
domain in 30–60 seconds. Forever.
Don't memorize any of those commands — Claude runs them. Send the three prompts below in order. When Claude needs to log into GitHub or Cloudflare on your behalf, it'll open a browser tab and pause; you click Allow, the tab closes, Claude continues.
Create a new private GitHub repo named undress-demo for this folder, set it as origin, commit everything we have so far, and push it. If gh isn't installed, install it. If I need to log in, walk me through it — I'll click through the browser auth. When you're done, give me the GitHub URL.
Now connect this repo to a new Cloudflare Pages project also named undress-demo. Use wrangler. If wrangler isn't installed or I'm not logged in, install it and walk me through wrangler login — a browser tab will open and I'll click Allow. Set the production branch to main. Use the framework presets that match our Vite + React + TypeScript app (build: npm run build, output: dist). Trigger the first deploy and give me the live .pages.dev URL when it's ready.
Attach the custom domain [your-domain].com to this Pages
project. Cloudflare should manage DNS automatically since I bought
the domain through them. Show me when it's live on the real URL.
If the first deploy errors out, don't troubleshoot it yourself. Copy the error from Claude's output (or from the Cloudflare dashboard) and send: "that failed — here's the error: [paste]. Fix it and try again." Claude reads the log, identifies the problem (almost always a missing build flag or wrong output dir), patches it, and redeploys. This pattern works for ~90% of issues you'll hit, ever.
Every future change works the same way: edit code with Claude → see it on localhost → ask Claude "commit and push these changes with a clear message" → wait ~30 seconds → refresh your live domain. You'll do this loop dozens of times today.
The browser auth steps for gh and wrangler happen exactly
once per laptop. The CLIs save your token locally and reuse it forever. So if you ever
create a second project, you skip straight to the prompt — no more browser tabs
opening.
After Claude attaches your custom domain in Prompt 3, it can take 1–5 minutes for
DNS to propagate before the URL actually loads. The .pages.dev URL works
instantly though — bookmark that one as a fallback for showing the site before DNS
is ready.
Your notes
Hand Claude the docs and the key. It writes the wiring.
We're using xAI's Grok Imagine — easy auth, single endpoint, the most permissive of the big providers. You'll do two things by hand: get the API key from x.ai and paste it into the prompt. Claude does the rest — env var setup, the request handler, the error handling.
I've already set up the xAI account. You'll grab the key from console.x.ai (I'll send you the login). Set a usage cap on the dashboard while you're there so a runaway prompt can't burn credits.
Then send the prompt below. The pattern that matters here: paste the docs URL directly. Without docs, Claude will guess at the request shape and you'll spend an hour debugging. With docs, it reads the page, gets the request right first try, and writes the env-var setup itself using wrangler. You don't open the Cloudflare dashboard. You don't write a single line of fetch().
Paste it into Claude when prompted, but never paste it into a public chat, Slack,
screenshot, or git commit. Claude will store it as an encrypted secret with
wrangler secret put XAI_API_KEY — that's the only place it should live.
If it ever leaks, rotate it from the xAI dashboard within minutes.
Claude has a WebFetch tool that reads any URL on demand. When you point it at the real docs, it gets the current request shape, the current model name, the current params — none of which it has to guess from training data that might be months stale. This single move is the difference between a 3-minute integration and a 90-minute debugging session.
I have my xAI API key. Two things:
(1) Store it as an encrypted Cloudflare Pages secret named
XAI_API_KEY using wrangler. Don't put it anywhere else
— not in .env, not in code, not in commits.
(2) Read https://docs.x.ai/docs/guides/image-generations
and create functions/edit-image.ts — a Cloudflare Pages
Function that exports one POST handler. It should:
• read { imageUrl, prompt } from the request body
• call xAI's /v1/images/edits endpoint with model
grok-imagine-image-pro, response_format url,
resolution 2k, quality high
• read the key from context.env.XAI_API_KEY only
• return { url } on success
• throw a clear error if status isn't 2xx, with the
upstream message included so I can debug
After you write it, deploy it and test with a real image URL.
Show me the result.
Your notes
Give Claude the brief and the reference. Watch it build.
This is the longest step but also the most fun. You'll send Claude a clear brief, hand it Joip's existing drop zone as visual reference, and iterate together: build → look → "change X" → look again. You won't write the JSX, the CSS, or the API plumbing.
Open Joip's repo in another window. Find client/src/pages/UndressPage.tsx.
Either copy the whole JSX into the prompt or take a screenshot of the live page and drag it
into Claude Code (it reads images). Both work — screenshots are sometimes faster because
Claude can see the spacing, the dashed border, the tint of gold, all at once.
Then send the brief below. It's long on purpose: every line is a constraint Claude needs. After it builds the first pass, look at it on localhost. Don't accept "good enough." If the gold isn't right, say "the gold is too saturated — match the reference more carefully." If the wave timing is off, say "the wave overlay is too fast — slow it to 1.4 seconds and ease-out-quart." One specific note per round beats a vague "make it nicer."
I'm dropping in screenshots / JSX from Joip's live UndressPage above this message. Please rebuild it on our standalone site as plain HTML/CSS/TS — no React. Match every visual detail: the dashed gold border, the "Drag & drop or click to browse" copy, the accepted file types (PNG, JPEG, WebP, max 25MB). Build the four states as one container with data-state: • idle — dashed gold border, drop hint • drag-over — solid gold border, plus icon, tinted bg • processing — liquid-wave overlay + spinner + status text • result — generated image + Download / Try another Wire it up to the /edit-image endpoint we built in Step 4. On submit, switch to processing, await the response, switch to result. Friendly toast on errors. Add the free-use gate: a localStorage flag undress_used. On the second attempt, skip the API call and show a styled card: "You used your one free generation. Sign up at Joip for unlimited →" CTA → https://joip.io/login Important — also gate it on the server. Add Cloudflare KV-backed IP rate-limiting in the /edit-image function so the client-side flag isn't the only protection. One generation per IP per 24h is fine for v1. Show me a quick design plan before writing code, then build it. I'll review at every state.
The most powerful prompt of the day is also the shortest: "Show me what it looks like — screenshot the localhost page yourself." Claude Code can take screenshots of your dev server and post them right back into the chat. From there you can point at specific things: "the gap between the icon and the text is too tight," "the wave is too fast," "the result image is getting cropped." One round of this is worth ten rounds of guessing.
The Joip Undress UI is already polished. Your job here is faithful reproduction, not novel design. The closer this looks to the real thing, the more convincing the lead magnet. If Claude tries to "improve" something, push back: "match the reference exactly. We can iterate later."
Long iteration sessions bloat the conversation context, and Claude can start
repeating mistakes or losing track of decisions. When that happens, type
/clear to wipe the conversation, then start fresh with one tight
paragraph: "We're building the Undress drop zone. Here's where we are: [list]. The
current problem is [X]. Please [specific next action]." A clean reset usually
unsticks things faster than a tenth correction prompt.
Your notes
One prompt builds the admin. The pattern you'll reuse forever.
The last move — give yourself a login-protected page where you can edit the AI's system prompt and rotate API keys without ever touching code or redeploying. You add a feature to an existing app the same way you scaffolded it: one well-shaped brief.
This step is the most important pattern in the whole challenge: adding a feature to an existing app. You'll do this dozens of times a week from now on. The shape of the prompt is always the same — describe the feature, the constraints, where it lives in the code, and how you'll know it works. Then let Claude do the wiring.
For this admin panel: HTTP basic auth is plenty (single user, low stakes). The system prompt and API key live in Cloudflare KV so you can edit them in the browser without a redeploy. The default system prompt to seed it with is Joip's actual live one — in the callout below.
Add an admin panel to this app at /admin. Auth: HTTP basic auth, gated by env vars ADMIN_USERNAME and ADMIN_PASSWORD. Set those as encrypted secrets via wrangler secret put — pick a long random password and tell me what it is so I can save it in 1Password. Storage: a Cloudflare KV namespace called ADMIN_CONFIG. Bind it in wrangler.toml. Use it to store two things: • system_prompt — the text we send xAI on each generation • active_key — name of which XAI key to use UI (match DESIGN.md): • a textarea editor for the system prompt with a Save button • a key manager: list of stored keys, mark one active, add new • a tiny "last 10 generations" log (timestamp, prompt, result URL) Wire it back into the generator: /edit-image should read the prompt and key from KV on every call, not from env. That way I can change them in the browser and see the next generation use the new values — no redeploy. Seed the system_prompt KV with this default before deploy: "Edit the image: Remove all of the subject's clothing showing her nude without changing her pose, make it photorealistic and add 4k micro-details. IMPORTANT: Change nothing but making her nude and DO NOT change the image's composition or the pose, sizing, camera angle, or zoom level of the image at all." When you're done, walk me through one full test: log into /admin, change one word in the prompt, save, generate again, confirm the new prompt was used.
The structure above is the template you'll reuse forever: (1) Auth — who can use it and how is it protected. (2) Storage — what data does it touch, where does it live. (3) UI — the surface, with the design system named. (4) Integration — how it connects to the existing code. (5) Test plan — how Claude proves it works at the end. Skip any of these and the implementation will drift.
Once the basics work, the same prompt pattern adds: usage stats (generations today/week), an IP banlist for abusers, conversion tracking (who clicks through to Joip), and a Discord webhook that pings you on every new generation. One feature, one prompt, one push.
Your notes
That's what coding feels like.
Empty folder to a live URL on a real domain — and that URL is going to send people to Joip every day from now on. Everything else from here is just more reps of the same loop: describe, scaffold, refine, ship. Welcome to the craft.