The problem
A studio headshot costs €100–300 and a booking you'll postpone twice. Most people don't need a photoshoot — they need one good, professional photo for a CV or LinkedIn, today. Generic AI filters exist, but their output tends to fail the only test that matters: would a recruiter believe this is a photograph?
What I built
Upload any selfie, optionally describe what you want, pick a background — get a CV-ready portrait back in roughly twenty seconds.
- Optional plain-text editing instruction plus background presets: solid color, gradient, office, outdoor
- Free to try with a watermark; Stripe credit packs unlock full-resolution downloads
- A credit system with validity windows per pack, tracked in a ledger
- Private gallery with 60-day retention and permanent delete at any time
- Google sign-in, and GA4 funnels to see exactly where users drop off
How it works
- Selfie upload
- Prompt compiler merges instruction + background + guardrails
- AI image model renders (~20 s)
- Post-process & watermark on the free tier
- Saved to the private gallery (60-day retention)
- Stripe credits unlock the full-resolution download
The differentiator is the prompt-engineering layer. Raw model output on arbitrary selfies is inconsistent — lighting, angles and framing vary wildly. So every request is compiled into a structured prompt: the user's instruction, the chosen background, and a set of guardrails that preserve the person's identity and enforce professional-portrait conventions. Consistency is designed, not lucky.
Payments run through Stripe Checkout, with webhooks feeding a credit ledger in SQL Server — handled idempotently, so a retried webhook can never double-credit an account. The app itself is Blazor Server on .NET.
Distribution
This is the product where I did real marketing, not just engineering. It carries the most serious SEO of the three — content pages, clean structure, proper metadata — and I ran paid-acquisition experiments on both Google Ads and Reddit Ads to test channels against organic traffic.
Hard problems
- Consistent quality across uncontrolled inputs — any phone, any lighting, any angle. The guardrail prompt evolved constantly against real-world selfies.
- Holding roughly 20 seconds per render as usage grows, so the experience feels instant rather than "submitted to a queue."
- Billing correctness: expiring credits plus asynchronous webhooks is a small distributed system, and the ledger must never disagree with Stripe.
Results & lessons
Over 2,000 photos generated for 500+ users so far. The biggest lesson: distribution beats features. A few weeks of SEO and ads experiments taught me more about what this product really is than a month of building did.