- Published on
Build an AI Image Generator with Replicate API, Firebase Auth & Stripe (2025 Guide)
- Authors
- Name
- Ahmed Farid
- @
TIP
Looking to monetize generative AI? This stack lets you ship fast without running GPUs yourself.
This guide shows how to build a production-ready AI image generator that charges users per render:
- Firebase Auth — email / social login & JWT.
- Stripe — Checkout + webhook to top-up image credits.
- Replicate API — call Stable Diffusion (or SDXL) to generate images.
- Cloud Functions — secure backend, queues & usage metering.
- React + Vite front-end (can swap for Next.js or Expo).
We’ll implement a pay-as-you-go credit model: 1 credit = 1 image. Users buy credits via Stripe, stored in Firestore; Cloud Function deducts on each Replicate call.
Table of Contents
- Table of Contents
- 1. Prerequisites & Terminology
- 2. Firebase Project Setup
- 3. Design the Firestore Schema
- 4. Implement Stripe Checkout & Webhook
- 5. Queue Image Generation Jobs
- 6. Call Replicate inside a Background Function
- 7. React Front-End
- 8. Pricing, Quotas & Cost Control
- 9. Deployment via Firebase Hosting + GitHub Actions
- 10. Security & Compliance Checklist
- 11. Further Reading & Resources
- 12. Conclusion
1. Prerequisites & Terminology
- Node.js 20 LTS.
- Firebase CLI 13+ (
npm i -g firebase-tools
). - Stripe account & secret key.
- Replicate account & API token.
Term | Meaning |
---|---|
Replicate | Cloud platform to run ML models via REST |
Stripe Checkout | Pre-built payment page |
Cloud Tasks | Managed job queue to prevent timeout |
2. Firebase Project Setup
firebase login
firebase init functions hosting firestore
# choose TypeScript, ESLint, deploy with GitHub CI later
Add env vars:
firebase functions:config:set stripe.secret="sk_live_..." replicate.token="r8_..."
3. Design the Firestore Schema
users/{uid}
credits: number
createdAt, lastLogin
jobs/{jobId}
uid, prompt, status(pending|done|error), url, cost, ts
4. Implement Stripe Checkout & Webhook
// functions/src/stripe.ts
import * as functions from 'firebase-functions'
import Stripe from 'stripe'
const stripe = new Stripe(functions.config().stripe.secret, { apiVersion: '2023-10-16' })
export const createCheckout = functions.https.onCall(async (data, ctx) => {
if (!ctx.auth) throw new functions.https.HttpsError('unauthenticated', 'Login first')
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
mode: 'payment',
line_items: [
{
price_data: {
currency: 'usd',
unit_amount: 100,
product_data: { name: 'Image Credits (10)' },
},
quantity: 1,
},
],
success_url: 'https://yourapp.web.app/success',
cancel_url: 'https://yourapp.web.app',
metadata: { uid: ctx.auth.uid, credits: 10 },
})
return { id: session.id }
})
export const stripeWebhook = functions.https.onRequest(async (req, res) => {
const sig = req.headers['stripe-signature'] as string
let event: Stripe.Event
try {
event = stripe.webhooks.constructEvent(req.rawBody, sig, 'whsec_...')
} catch (err) {
return res.status(400).send(`Webhook Error: ${(err as Error).message}`)
}
if (event.type === 'checkout.session.completed') {
const { uid, credits } = event.data.object.metadata as any
await admin
.firestore()
.doc(`users/${uid}`)
.set({ credits: admin.firestore.FieldValue.increment(+credits) }, { merge: true })
}
res.json({ received: true })
})
5. Queue Image Generation Jobs
export const generateImage = functions.https.onCall(async (data, ctx) => {
const { prompt } = data
const uid = ctx.auth?.uid
if (!uid) throw new functions.https.HttpsError('unauthenticated', 'Login')
const userRef = admin.firestore().doc(`users/${uid}`)
const userSnap = await userRef.get()
if ((userSnap.data()?.credits || 0) < 1)
throw new functions.https.HttpsError('resource-exhausted', 'Buy credits')
const jobRef = admin.firestore().collection('jobs').doc()
await jobRef.set({
uid,
prompt,
status: 'pending',
ts: admin.firestore.FieldValue.serverTimestamp(),
})
await cloudTasks.createTask({
url: `https://REGION-PROJECT.cloudfunctions.net/runReplicate`,
scheduleTime: Date.now() / 1000 + 5,
body: Buffer.from(JSON.stringify({ jobId: jobRef.id })).toString('base64'),
})
await userRef.update({ credits: admin.firestore.FieldValue.increment(-1) })
return { jobId: jobRef.id }
})
6. Call Replicate inside a Background Function
export const runReplicate = functions.region('us-central1').https.onRequest(async (req, res) => {
const { jobId } = req.body
const jobRef = admin.firestore().doc(`jobs/${jobId}`)
const { prompt } = (await jobRef.get()).data()!
try {
const resp = await fetch('https://api.replicate.com/v1/predictions', {
method: 'POST',
headers: {
Authorization: `Token ${functions.config().replicate.token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ version: 'stability-ai/sdxl:latest', input: { prompt } }),
}).then((r) => r.json())
// poll until completed … omitted for brevity
await jobRef.update({ status: 'done', url: resp.output[0] })
} catch (e) {
await jobRef.update({ status: 'error' })
}
res.end()
})
7. React Front-End
- Firebase Web v10 for auth & callable functions.
- Use
react-query
to polljobs/{jobId}
untilstatus==='done'
then display image. - Show credit balance from
users/{uid}
snapshot.
const buy = httpsCallable(functions, 'createCheckout')
const { id } = await buy()
window.location.href = `https://checkout.stripe.com/pay/${id}`
8. Pricing, Quotas & Cost Control
- Stable Diffusion XL ~ $0.016 / image (Replicate January 2025).
- Charge users $0.05 → 3× margin.
- Use Firestore rules:
allow read: if request.auth.uid == resource.data.uid
.
9. Deployment via Firebase Hosting + GitHub Actions
actions/checkout@v4
setup-node@v4
run: firebase deploy --only hosting,functions
10. Security & Compliance Checklist
✅ Store API keys in functions:config.
✅ Verify Stripe webhook signature.
✅ Log Replicate request IDs for audits.
✅ Delete user data on account deletion (GDPR).
✅ Rate-limit generateImage
cloud function.
11. Further Reading & Resources
- Replicate docs: replicate.com/docs.
- Firebase Cloud Functions.
- Stripe Docs: Checkout & Webhooks.
12. Conclusion
You now have a scalable image-generation SaaS with secure auth, payments, and serverless AI inference—no GPU headaches required. Time to ship! 🚀