- Platform
- Web App
- Duration
- 9 months (ongoing)
- Industry
- MarTech
- Read time
- 9 min
The short answer
RaftLabs built Brux Smile Makeover, a dental marketing SaaS where patients upload a selfie and receive a photorealistic AI-generated smile preview and before/after video in 30-40 seconds. Patient photos arrive through four channels (webform, chairside staff upload, external webhook, inbound SMS/MMS), and results sync automatically into GoHighLevel with contacts, tags, custom fields, and an SMS reply to the patient. Built on AWS Amplify Lambda, Hasura/PostgreSQL, Google Gemini 2.5 Flash, and Stripe, the platform went live in April 2026 with Basic ($99/mo), Advanced ($199/mo), and Enterprise ($299/mo) tiers for US dental offices.
Jake Efstration knew the gap. Dental offices spend real money bringing prospective patients in for consultations. Most of those consultations end without a booking because the patient cannot visualize the result. A printed before/after from a stock photo library does not work. A simulation built on the patient's own face does.
He had a prototype of that idea: an AI smile preview tool that ran inside a webform and demoed well. But nobody could buy it. No billing, no multi-tenant office management, no CRM connection. AI output was inconsistent enough that a dental brand could not put it in front of real patients. He came to us to turn it into something real.
We built Brux Smile Makeover: a dental marketing SaaS where a patient uploads a selfie and receives a photorealistic new-smile image in 30-40 seconds, along with a before/after reveal video. Patient photos arrive through four capture channels (public webform, chairside staff upload, external webhook, and inbound SMS/MMS from the office's GoHighLevel number) and all route through the same AI pipeline. Results sync back into GoHighLevel automatically: the patient becomes a contact, treatment tags are applied, and an SMS with the image lands on their phone.
Phase 1 went live in April 2026. June 2026 brought self-serve office claim codes via printed QR flyers and an enterprise bring-your-own-AI-key tier. A third phase is in scoping.

before & after
What changed
- A no-code AI prototype that demoed the idea but could not handle real offices past a handful of accounts
- Every new dental office required Brux staff to manually provision the account and configure the webform
- No billing system, so there was no way to convert interested offices into paying customers
- Patient photos arrived through a single webform with no CRM connection
- GoHighLevel operated independently, requiring manual data entry and creating operational errors when staff accidentally sent SMS messages to patients
- A production SaaS live at app.bruxsmilemakeover.com serving US dental offices on three paid plans
- Offices claim their own account from a printed QR code and 9-digit claim code with no staff involvement from Brux
- Basic ($99/mo), Advanced ($199/mo), and Enterprise ($299/mo) tiers accept real payments via Stripe with trials, coupons, and auto-reload
- Patient photos arrive through four distinct capture channels and all converge on the same AI pipeline and credit system
- GoHighLevel sync creates the patient contact, applies treatment tags, writes before/after image and video URLs into custom fields, and sends the SMS automatically on every successful transformation
What we had to solve
- 01
Making a non-deterministic AI produce reliable, natural-looking smiles every time
The whole product lives or dies on whether the generated smile looks believable. A dental brand cannot put a transformation in front of a patient that looks AI-generated or distorts their face. The challenge was that image models are non-deterministic: the same prompt produces different output each time, and early testing showed quality varied enough to be a problem at production volume. The fix required real R&D: iterating across Gemini models and providers until the prompt "only change the teeth, not the face" held consistently, and adding a face-validation gate that rejected unusable photos before spending a credit. Three parallel variants go back to each patient so they pick the result that best fits their expectation. The platform ultimately settled on Gemini 2.5 Flash Image, hitting 30-40 seconds per transformation at approximately $0.034 each.
- 02
A credit system that stays correct when dozens of offices submit simultaneously
Every AI render costs real money. Dental offices buy credits and must be blocked the moment they cannot afford the next job, across four entry points, with async AI jobs that can fail partway through. An early optimistic-lock implementation failed the concurrency case exactly: two simultaneous submissions from the same office both read the same balance and both passed through, even when only one should have. We replaced it with an atomic database cap check: each lock increments "locked credits" only where the total is still within the allowed maximum, as a single conditional update. All concurrent submissions run until the office is actually out of budget; none are wrongly rejected while capacity remains. Credits are committed only for transformations that complete successfully; the unused locked portion is released on failure.
- 03
Running the entire AI pipeline on the dental office's own API key
The Enterprise tier routes all AI through the office's own OpenRouter key instead of the Brux-managed account. That required hunting down every part of the pipeline that silently used Brux's credentials: face validation, image variants, the video start frame, and the video all had to route through the customer's key with no fallback to ours. The execution mode (managed vs. enterprise) is resolved once per submission by a single gate function and threaded through every downstream call. When a key runs out of budget, the platform surfaces the specific reason; it never silently falls back and charges the Brux account. OpenRouter returns a 401 (not a 402) when a key exceeds its spend cap, which initially caused us to tell admins their key was invalid when it simply needed a top-up. Classifying that error correctly was a specific fix.
outcomes
What we achieved
The earlier prototype produced inconsistent output with no quality control. Getting to a result a dental brand could show real patients required significant model selection and prompt R&D, not just picking a fast model.
The prototype accepted photos only through a single webform. Dental offices also need chairside uploads during consultations, external webhook integrations with other tools, and patients who text a photo directly to the office number.
Without connection pooling, async AI processing, and a concurrent-safe credit system, scaling beyond a handful of offices would have required manual infrastructure management and would have produced billing errors under real load.
Every new office required Brux staff to manually set up the account, configure the webform, and walk the practice through the product. The go-to-market motion was capped by staff hours, not by the number of offices interested.
Building an AI product that needs payments, CRM sync, and real patient data all working together?
the build
What we built
The engagement ran on weekly demo cycles with Jake and his team. A working prototype of the core AI transform flow was live in the first month. The full billing system, CRM integration, and multi-channel pipeline followed across 4-week delivery cycles for nine months and counting.
AI generates a photorealistic new smile from a patient selfie in 30-40 seconds, with three parallel variants
A patient uploads a front-facing photo. A face-validation gate (Gemini 2.5 Flash, vision-in / JSON-out) checks the image is usable before spending any credits: non-human, cropped, blurry, or multi-face photos are rejected with a specific explanation. If valid, the pipeline generates three side-by-side variants in parallel (Subtle, Vibrant, Maximum) using Gemini 2.5 Flash Image via OpenRouter. The patient picks a favorite and can request a before/after reveal video: the platform synthesizes a closed-mouth starting frame with a second AI pass, then Veo 3.1 animates the smile opening. Total image generation: 30-40 seconds.

Patient results flow into GoHighLevel as contacts with tags, custom fields, and an SMS reply, automatically
GoHighLevel is what Jake calls the product's core market differentiator. When a transformation completes, the platform creates or updates the patient's GHL contact by phone number, applies treatment-type and success tags, writes the before/after image and video URLs into GHL custom fields, and sends an SMS with the transformed image to the patient. The sync is bidirectional: when a patient texts a photo to the office's GHL number, a webhook fires, the full transform pipeline runs, and the result is texted back. Every submission, from whichever of the four channels it arrived on, is linked to the GHL contact record so staff can open it directly from the Brux dashboard.

Offices claim their account and start a trial from a printed QR flyer, with no setup from Brux staff
Brux's go-to-market motion is physical: printed flyers mailed to dental offices, each with a unique QR code and a 9-digit claim code. When a dentist scans the code, they land on a claim flow, verify their phone number via SMS OTP, and activate a trial account pre-configured with their webforms. No Brux staff involvement after the flyer is mailed. The claim code is HMAC-hashed for lookup and stored encrypted for admin display. The activation uses a two-phase database transaction with row locks to prevent duplicate claims, with Cognito user creation rolled back best-effort if the database activation fails.

Full Stripe billing with credits, trials, coupons, auto-reload, and an enterprise tier that skips the credit system entirely
Offices subscribe to Basic ($99/mo, 100 credits), Advanced ($199/mo, 300 credits), or Enterprise ($299/mo, no credits). Credits gate every AI generation; each image costs 1 credit, a 3-variant submission costs 3, and a video costs 4 (billed separately when the patient requests it). Stripe SetupIntent collects the card during trial and charges automatically when the trial ends. The Enterprise tier skips the credit system entirely and runs AI through the office's own OpenRouter key. Plan changes, coupon redemptions, and 3-D Secure charges on auto-reload all go through Stripe without custom reconciliation code.

Engagement
How we worked together
- 01Weeks 1–2
Discovery and scoping
We map the problem before writing code. Two weeks of technical audit, stakeholder interviews, and prototype — so both teams align on scope and risk before sprint one. - 02Ongoing
Two-week Agile sprints
Each sprint ends with working software, not a status update. You review a real build, request changes, and approve before we move forward. No surprises at handover. - 03Ongoing
Daily async updates
Slack for daily progress, Asana for task visibility, weekly video calls for decisions. You have full visibility without needing to attend every meeting. - 04Final
Handover and warranty
Full code handover with deployment runbooks and documentation. Thirty-day warranty period for production issues at no extra cost.
stack
Why we chose this stack
- 01React 19 concurrent features gave us a smooth multi-step webform and transformation result UI without page reloads. Vite kept the local development cycle fast during a 9-month build with frequent UI iteration from the client's Figma designs.React 19 + Vite
- 02Amplify's CDK-based backend let us provision Lambdas per domain (billing, AI transforms, GoHighLevel, webhooks, auth, cron) without managing an application server. Each transformation runs as an isolated Lambda invocation, so 1,000 concurrent offices running simultaneous transforms don't share state or compete for threads.AWS Amplify + Lambda
- 03Hasura event triggers drive the async AI pipeline: a new image upload row fires the transform trigger, which handles credit locking and fans out to the AI models. The GraphQL layer generates a typed SDK from the schema, so every Lambda reads and writes through the same type-safe interface. The atomic credit cap check is a conditional Hasura mutation, not application-level logic.Hasura + PostgreSQL
- 04Gemini 2.5 Flash Image produces photorealistic smile results at the quality a dental brand requires, in 30-40 seconds at approximately $0.034 per transformation. Gemini 2.5 Flash handles face validation and video start-frame synthesis. Veo 3.1 generates the before/after reveal video. We evaluated multiple models and providers; this combination cleared the quality bar while keeping latency and unit cost inside the product's economics.Google Gemini via Vertex AI
- 05Stripe Subscription Schedules handle plan downgrades without losing access mid-period. SetupIntent collects the card during trial and auto-charges at trial end. Coupons are Stripe-managed with per-office credit ledgers that renew, expire, and transfer correctly across plan changes. The subscription lifecycle (trial conversion, coupon switch, 3DS on off-session auto-reload charges, enterprise tier with zero credits) has enough edge cases that using a lower-level payments API would have added months of reconciliation logic.Stripe
Common questions about Brux Smile Makeover
Off-the-shelf AI transformation tools handle the image and nothing else. Brux covers the full workflow: output quality tuned for dental use, GoHighLevel sync that creates the lead and sends the SMS automatically, per-office credit metering, and a claim flow that takes a practice from printed flyer to active account without setup help from Brux. Those pieces have to work together as one system. Adapting a generic tool would have meant rebuilding most of that anyway, without the clean architecture that comes from designing it as a single product from the start.
Dental brands are precise about what they will show patients. The hard constraint is that only the teeth change, not the facial structure. A result that distorts the face or produces uncanny-looking teeth damages the office's brand rather than helping it. We got there through three levers. Model selection: Gemini 2.5 Flash Image, tested against multiple Gemini versions and providers. Prompt engineering: specific constraints on shade, structure, and what the model cannot change. And three variants per submission so patients choose the result that best fits. The Subtle, Vibrant, and Maximum framing was a deliberate product decision: it lets the patient self-select into the intensity rather than having the office guess.
The integration runs both ways. On the inbound side: when a patient texts a photo to the office's GHL number, a webhook fires, the platform runs the full AI pipeline, and the result is texted back to the patient. On the outbound side: when a transformation completes from any of the four capture channels, the platform creates or updates the GHL contact by phone number, applies tags for the treatment type and outcome, writes the before/after image and video URLs into custom fields, and sends the patient an SMS with the transformed image attached. The platform also pulls contacts, custom fields, and tags from GHL at account connection so defaults are pre-populated. Every submission, from whichever channel it arrived on, is linked to the corresponding GHL contact record.
The credit lock is an atomic database operation rather than a read-then-write. When a submission arrives, the platform checks whether adding the cost of this job to the office's current locked-credits total would exceed the allowed balance, and if not, increments locked credits in a single conditional database update. If the update returns zero affected rows, the lock failed (the office is over budget) and the submission is blocked immediately. If it succeeds, the job runs. Credits are committed only for transformations that complete successfully; unused locked credits are released on failure. This means all concurrent submissions run until the office actually runs out of budget, and none are wrongly blocked by concurrent locks that were already released.
The core architecture transfers: multi-tenant SaaS, AI generation pipeline with face or object validation, credit-based metering with concurrent-safe locks, CRM integration with bidirectional sync, and self-serve onboarding via claim codes. Jake himself identified hair color, aesthetics, interior design, and house repainting as natural extensions of the same pattern. The variable parts are the AI models and prompts (which need tuning per output type), the specific CRM integration (GoHighLevel is common in US dental and medical; the pattern works with any CRM that exposes a webhook API), and the compliance posture (HIPAA for healthcare, different requirements for other industries). Contact us to discuss your specific use case.








