Short answer
RaftLabs built Brux Smile Makeover, a dental marketing SaaS where patients upload a selfie and receive a realistic AI-generated smile preview in 30-40 seconds, with an optional before/after reveal video. Patient photos arrive through four channels (webform, in-office 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.
Engagement
The engagement
- Client
- Brux Dental Solutions, founded by Jake Efstration
- Sector
- Dental marketing
- Market
- United States
- Timeline
- 9-month build, ongoing; Phase 1 live April 2026
- What shipped
- AI smile-preview SaaS with GoHighLevel two-way sync, credit billing, and self-serve office onboarding
- Pricing
- Basic $99/mo, Advanced $199/mo, Enterprise $299/mo
The situation
Jake Efstration, founder of Brux Dental Solutions, saw where dental marketing actually leaks. Most practices do not have a lead-generation problem. They have a conversion capture problem: a patient gets curious about cosmetic work, cannot picture the result, says "let me think about it," and never books. Show them their own face with a new smile, and the conversation changes. And no smile preview tool on the market plugged straight into GoHighLevel, the CRM his dental office customers already ran on.
He had a prototype of the idea: a no-code AI smile tool that demoed well. But it could not be sold. It had no billing, no way to run many offices on one platform, and its output was too inconsistent to put in front of real patients. He asked us to turn it into a real product.
We built Brux Smile Makeover, a dental marketing SaaS where a patient uploads a selfie and gets a lifelike new-smile image in 30-40 seconds, plus an optional before/after reveal video. Patient photos come in through four channels — a public webform, in-office upload by staff, an external webhook, and photos texted to the office's GoHighLevel number — and all four run through the same AI pipeline. Results flow back into GoHighLevel on their own: the patient becomes a contact, treatment tags are applied, and a text with their new smile lands on their phone.
Phase 1 went live in April 2026. In June 2026 we added self-serve office sign-up from printed QR flyers and an Enterprise tier where offices bring their own AI key. A third phase is under discussion.

Before and after
What changed
- A no-code AI prototype that demoed well but had no path to real, paying offices
- Brux staff set up every new dental office by hand, from the account to the webform
- No billing, so there was no way to turn interested offices into paying customers
- No GoHighLevel integration, the very thing Jake saw as the product's edge
- AI output too inconsistent to show real 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 help from Brux staff
- Basic ($99/mo), Advanced ($199/mo), and Enterprise ($299/mo) plans take real payments through Stripe, with trials, coupons, and auto-reload
- Patient photos arrive through four channels (web form, in-office upload, external webhook, and text message), all sharing one AI pipeline and one credit system
- Every successful result creates the patient in GoHighLevel, applies treatment tags, saves the before/after image and video links, and texts the patient automatically
What we had to solve
Getting an unpredictable AI model to produce natural-looking smiles every time
The whole product depends on one question: does the new smile look real? Instant selfie apps get treated as filters, and a preview that looks fake loses the patient's trust instead of winning a booking. Image models make this hard, because the same prompt gives a different result every time. The quick route was to take a fast model and ship it. We pushed back, because fast output that looks wrong would sink the product. Instead, we compared several image models and AI providers, reworked the prompts until "change only the teeth, never the face" held up on real patient photos, and added a check that rejects unusable photos before any credit is spent. With that groundwork in place, the fast model became good enough. The platform runs on Gemini 2.5 Flash Image at 30-40 seconds and about $0.034 per transformation, and each patient gets three results to choose from.
A credit system that stays correct when a busy office submits many photos at once
Every AI render costs real money, so offices pay in credits, and a job has to stop the moment an office can't cover it. That check runs across four entry points, on AI jobs that finish in the background and can fail halfway. Our first version used a standard optimistic lock, and it broke on busy offices: when two submissions landed at the same moment, one was rejected even though the office had plenty of credits. For a clinic running several previews during a consult, that's a patient turned away for no reason. We replaced it with a single database update that reserves credits only if the office stays within its limit. Now every submission goes through while credits remain, and only a job that would actually go over the limit is stopped. Credits are charged only when a result comes back. If a job fails, its reserved credits are released.
Running the entire AI pipeline on the dental office's own API key
Enterprise offices run every AI call on their own OpenRouter key instead of Brux's. That meant finding every step that quietly used Brux's key: photo validation, the image variants, the video start frame, and the video itself. One function now decides, for each submission, whose key it runs on, and every later step follows that decision. If the office's key runs out of budget, the platform says so clearly and never falls back to charging Brux. One surprise along the way: OpenRouter returns a 401 error, which normally means "invalid key", when a key hits its spending cap. At first, admins were told their key was broken when it only needed a top-up. We now read the error details to tell the two apart.
the build
What we built
Every week, we demoed working software to Jake and his team, and their feedback shaped the next week's work. Over nine months, that rhythm delivered the AI pipeline, the GoHighLevel integration, full billing, and all four photo channels.
AI turns a patient selfie into a lifelike new smile in 30-40 seconds, with three results to choose from
A patient uploads a front-facing photo. Before any credit is spent, Gemini 2.5 Flash checks the photo is usable. Photos that are not of a person, cropped too tight, too blurry, or show more than one face are rejected with a clear reason. If the photo passes, the pipeline generates a base result and variants with stronger correction in parallel, using Gemini 2.5 Flash Image. By default, a webform submission shows three results side by side. The patient picks a favorite and can ask for a before/after reveal video: a second AI pass creates a closed-mouth starting frame, then Veo 3.1 animates the smile opening.

Patient results land in GoHighLevel as contacts with tags, custom fields, and a text message, automatically
Jake saw GoHighLevel integration as the product's edge in the market. When a transformation finishes, the platform finds or creates the patient's GHL contact by phone number, applies treatment tags, saves the before/after image and video links into GHL custom fields, and texts the new smile to the patient. It works in both directions: when a patient texts a photo to the office's GHL number, the platform picks it up, runs the full pipeline, and texts the result back. Every submission, whichever channel it came from, links to its GHL contact, so staff can jump to it straight from the Brux dashboard.

Offices claim their account and start a trial from a printed QR flyer, with no setup from Brux staff
Brux finds new offices with printed flyers, mailed to each practice with a unique QR code and a 9-digit claim code. When a dentist scans the code, they verify their email and phone number and activate a trial account that already has their webforms set up. Once the flyer is in the mail, Brux staff don't need to do anything. Claim codes are stored hashed for lookup and encrypted for admin display. Activation runs as a two-step database transaction with row locks, so the same office can never be claimed twice. If activation fails, the login account created for it is rolled back.

Full Stripe billing with credits, trials, coupons, auto-reload, and an Enterprise tier that skips credits entirely
Offices subscribe to Basic ($99/mo, 100 credits), Advanced ($199/mo, 300 credits), or Enterprise ($299/mo, no credits). Each generated image costs 1 credit, so a three-result submission costs 3, and a video costs 4, charged only when the patient asks for one. The card is saved during the trial and charged automatically when the trial ends. The Enterprise tier skips credits entirely and runs AI on the office's own OpenRouter key. Plan changes, coupons, and 3-D Secure checks on auto-reload payments all run through Stripe, with a webhook handler keeping each office's plan, credits, and coupon balance in sync.

Proof
What the build delivered, and what this page can't claim
Product-recorded delivery and design facts. No patient-outcome or revenue figures were on record for this review.
| Result | What changed | Period or context | Evidence and limitation |
|---|---|---|---|
| Speed | 30-40 seconds per AI smile transformation, from photo upload to result | Early output was not consistent enough to show real patients. Getting there took model comparisons and careful prompt work, not just picking the fastest model. | Product-recorded |
| Channels | 4 photo intake channels on one AI pipeline and one credit system | Web form, in-office upload, external webhook, and text message. Offices collect photos during consults, connect other tools by webhook, and receive photos texted straight to the office number. | Product-recorded |
| Scale | 1,000 concurrent offices as the design target | Load tested at 100-200 simultaneous submissions with 2.8-7.1s responses and no credit errors. Connection pooling, background AI processing, and a credit system that holds up under concurrent load. | Engineering record |
| Onboarding | Self-serve office onboarding from a printed QR flyer and 9-digit claim code, live June 2026 | Brux staff previously set up every new office by hand. Growth was capped by staff hours, not by how many offices were interested. | Product-recorded |
The lesson
Ship the quality bar first, then make it fast
The quick route was to take the fastest image model and ship it. We pushed back, because a preview that looks fake loses the patient's trust instead of winning a booking, and no speed number fixes that. So the quality bar came first: model comparisons, prompt limits that held up on real patient photos, and a validation gate that rejects unusable photos before any credit is spent. Only then did the fast model become good enough, at 30-40 seconds and about $0.034 per transformation. Speed is the last thing you optimize, not the first.
How it runs
- React 19 + Vite
- We built the UI from the client's Figma Make designs, and feedback came in every week. React 19 with Vite let us turn each design into production screens quickly and ship UI changes without slowing the backend work.
- AWS Amplify + Lambda
- Amplify let us define a Lambda function for each area (billing, AI transforms, GoHighLevel, webhooks, auth, scheduled jobs) without running an application server. Each transformation runs as its own Lambda call, so a rush of submissions from one office doesn't slow down another.
- Hasura + PostgreSQL
- Hasura event triggers drive the AI pipeline: each new photo upload starts the transform job, which reserves credits and calls the AI models. We generate a typed SDK from the GraphQL schema, so every Lambda reads and writes data the same type-safe way. The credit limit check is a single conditional database update, so it stays correct under concurrent load.
- Google Gemini and Veo
- Gemini 2.5 Flash Image produces smiles good enough for a dental brand, in 30-40 seconds at about $0.034 per transformation. It also creates the closed-mouth start frame for videos, while Gemini 2.5 Flash checks each photo first. Veo 3.1 creates the before/after reveal video. Enterprise offices run the same models through OpenRouter on their own key, and can pick Gemini 3 Pro Image or Veo 3.1 Fast to trade speed for detail. We compared several models and providers, and this combination met the quality bar while keeping speed and cost within the product's budget.
- Stripe
- Stripe Subscription Schedules let offices downgrade without losing access mid-period. A SetupIntent saves the card during the trial and charges it when the trial ends. Coupons live in Stripe, with a credit balance per office that renews, expires, and follows the office through plan changes. Trial conversions, coupon switches, 3-D Secure on auto-reload, and an Enterprise tier with zero credits all run on Stripe's billing tools, so we only wrote the logic specific to Brux's credits.
Common questions
Off-the-shelf AI tools handle the image and nothing else. Brux covers the whole workflow. Output quality tuned for dental use, GoHighLevel sync that creates the lead and texts the patient automatically, credit billing per office, and a claim flow that takes a practice from printed flyer to active account without help from Brux. Those pieces have to work as one system. Adapting a generic tool would have meant rebuilding most of it anyway.
A dental office won't show a patient a preview that looks fake. Instant selfie apps get treated as filters; a preview tied to the office's real workflow has to earn more trust than that. The rule was simple: change the teeth, never the face. Each submission returns three results, from subtle to stronger correction, so the patient picks the look they like instead of arguing with one render.
It works in both directions. When a patient texts a photo to the office's GHL number, the platform runs the full pipeline and texts the result back. When a transformation finishes from any channel, the platform finds or creates the GHL contact by phone number, applies treatment tags, saves the before/after links into custom fields, and texts the patient their new smile.
Reserving credits is one atomic database update, not a read followed by a write. The update adds the job's cost to the office's reserved credits, but only if the total stays within what the office can spend. Credits are charged only for results that come back, and credits reserved for failed jobs are released. So a busy office can run many submissions at once, and only a job that would actually go over the limit is stopped.
The core architecture carries over: a multi-tenant SaaS, an AI generation pipeline with input checks, credit billing that stays correct under concurrent load, two-way CRM sync, and self-serve onboarding with claim codes. Jake himself named cosmetics, hair color, landscaping, and house repainting as natural next markets for the same pattern. What changes is the AI models and prompts (each output type needs its own tuning), the CRM integration (the same pattern works with other CRMs that have an API), and compliance (HIPAA for healthcare, different rules elsewhere). Contact us to talk through your use case.
Related work
More of our work
Makeover generates natural-looking before-and-after previews
Makeover generates natural-looking before-and-after previews that convert more consultations to bookings
AI before-and-after SaaS for dental, aesthetics, and hair service businesses.
Perceptional replaces static surveys with
Perceptional replaces static surveys with AI-led interviews that adapt in real time
Conversational AI chatbot SaaS that turns static forms into meaningful conversations.
Draftly reaches 500+ active users
Draftly reaches 500+ active users in 60 days by removing the blank-page barrier to LinkedIn posting
AI LinkedIn content tool with collaborative drafting and scheduling queue.