Skip to content
Aqib Javed.

Case study

Spectoria

One prompt, one credit ledger, whichever video model fits.

Role
Co-founder and Lead Engineer
Spectoria LLC, Qatar
When
Aug 2025 to present
FlutterNext.jsReactTypeScriptfal.aiRunway SDKGeminiStripeRevenueCatFirestoreFirebase StorageFCMnext-intl
Spectoria marketing card showing the generation dashboard

The problem

What made this hard

A new video model ships every few weeks, and each one lives behind its own subscription and its own API shape. People who make content do not want five accounts. Spectoria routes one prompt to whichever model fits, settles everything into a single credit ledger, and works the same on web and mobile.

What shipped

Built, wired, released

  • A generation pipeline that is fire-and-forget. The server submits the job with a webhook URL, and when fal.ai calls back, the result is pulled into Firebase Storage, the status doc flips, and FCM tells the phone the render landed.

  • Eight model families behind one router. Seedance, Kling, Veo 3, Sora 2, Wan 2.5, Luma Ray-2 and the Nano Banana image models through fal.ai, with Runway integrated directly through its own SDK.

  • A scene generator for short films. It chains 2 to 8 linked cinematic scenes with shot types and transitions, plus lip sync and upscaling.

  • Dual-rail billing into one ledger. Stripe checkout and subscriptions on web, RevenueCat on mobile, both writing credits to the same Firestore transactions with idempotent, deterministic doc ids.

  • Gemini for the unglamorous glue. Prompt enhancement, translation, and person-detection before generation.

  • One backend, two clients. A REST surface of about 70 endpoints mirrors the web server actions for the Flutter client, plus English and Arabic localization on both.

Architecture

How it holds together

  1. L0Next.js App Router app is both the web client and the backend: server actions for web, an /api/flutter-app REST surface for mobile.

  2. L1Generation jobs run through provider webhooks, so nothing blocks a request thread waiting on a two-minute render.

  3. L2Credits are a Firestore ledger with a shared cost table; Stripe and RevenueCat webhooks both settle into it idempotently.

  4. L3The Flutter client is GetX plus RevenueCat, with FCM push when a creation is ready.

Screens

Every frame is a real capture unless labeled otherwise. Tap any screen to open it.

Outcome

Where it landed

  • Web app live at spectoria.cc with English and Arabic locales.
  • Flutter mobile client with RevenueCat billing against the same credit ledger as Stripe on web.
  • Eight model families routed through one pipeline, so adding the next one is a config problem, not a rewrite.