Muse AI docs
v2.0.0
Live demoConsole demo Get help
● Start · How it fits together

Architecture
who talks to whom.

One picture of the three parts you deploy (the app, the Firebase backend and the operator console) and the outside services they call. You do not need to understand code to read it. Most setup problems are one broken arrow in this picture, so read it once before you start.

App → API → providersKeys only on the serverChats stay on the device

01The diagram

Boxes with a solid border are parts of this package. Boxes with a dashed border are outside services you open accounts for. Arrows point in the direction of the request.

Muse AI architecture The operator console writes config/public and config/private to Cloud Firestore. The Cloud Functions API reads both documents, calls the AI chat, image, video and voice providers with the keys from config/private, verifies store purchases, stores generated images and videos in Cloud Storage, fetches the Discover feeds and sends push campaigns through Firebase Cloud Messaging. The mobile app calls only the API over HTTPS, signs in with Firebase Authentication, downloads images and videos through signed URLs, loads ads from ad network SDKs and buys through the stores. Conversations are stored on the device. Operator console admin/ · Node 22 · your host you open /admin in a browser own data: SQLite or Postgres keys encrypted (ADMIN_SECRET_KEY) Cloud Firestore config/public · app settings config/private · keys, server only users · usage · stats · images reports · purchases · revenueEvents AI providers (your accounts) chat: Anthropic · OpenAI · Gemini or any OpenAI-compatible endpoint images: OpenAI · Imagen · fal.ai Stability AI · video: fal.ai, Replicate voices: OpenAI · ElevenLabs · Gemini transcription: + Deepgram moderation (optional) Cloud Functions (backend) firebase/ · Node 22 · 2nd gen api: the /v1 HTTP API (Hono) gating · moderation · limits credits and refunds jobs: push · cleanup · Discover feeds stores no message text Cloud Storage generated images and videos rules deny every client Store server APIs Google Play · App Store Firebase Cloud Messaging push (APNs on iOS) Mobile app app/ · Flutter · Android, iOS, web built with API_BASE_URL no provider, ad or store key chats stored on the device sqflite (phone) · browser storage optional backup, user's choice: Firestore users/{uid}/sync Firebase Authentication anonymous · Google · Apple · e-mail Ad network SDKs (optional) AdMob · Unity Ads · LevelPlay Store billing (optional) Google Play Billing · StoreKit writes config/* reads users reports reads config/* writes usage, stats AI calls your key verify campaigns images HTTPS /v1 · chat streams (SSE) Bearer: Firebase ID token GET /v1/config = config/public signed URL download push to the device part of this package outside service, your account
Muse AI 2.0 · request directions

02The parts in plain words

  • Mobile app (app/). Knows one address: your API (API_BASE_URL, set when you build). It never talks to an AI provider directly and carries no secret. It keeps the user's chats on the phone and edits videos on the phone itself.
  • Backend (firebase/). The api Cloud Function answers every request of the app. It reads your settings from Firestore, checks the user's plan and allowance, runs moderation, forwards the request to the provider with your key, streams the answer back and counts usage. Three scheduled functions send push campaigns (every 5 minutes), fetch the Discover feeds (every 10 minutes, only while Discover is on) and clean up old data (daily at 03:30 UTC).
  • Operator console (admin/). A small Node server you host. You set everything there; on every save it writes two Firestore documents: config/public (what the app may see, served by GET /v1/config) and config/private (keys, feed addresses and caps, read only by the backend).
  • Outside services (dashed boxes). Each one is an account you open and pay yourself: AI providers, Firebase, the stores, ad networks. The Discover feeds come from the publishers whose RSS / Atom feeds you enable.

03config/public and config/private

config/publicconfig/private
ContainsBrand, legal texts, features, sign-in methods, chat settings, model, image, voice, video, image-edit and caption-style catalogs, styles, assistants, prompts, plans, paywall, limits, Discover categories, store product ids, ad settings and ad unit ids, push topicAI, image, voice and video keys, compatible endpoints, daily caps, Discover feed addresses, image tool model ids, moderation settings, store verification credentials, ad reporting tokens, AdMob SSV switch
Written byThe console onlyThe console only
Read byThe backend, which serves it to the app as GET /v1/config (cached 60 s), without your prices, provider model ids and unusable modelsThe backend only
App or browser accessNever directly (Firestore rules deny it)Never

Until the console has saved once, the backend uses the built-in defaults: every model disabled, every paid module off, ads, plans and purchases off.

04What happens when a user sends a message

  1. The app sendsthe last messages of the chat (at most Messages sent as context, default 30) to POST /v1/chat with the user's Firebase ID token.
  2. The backend checksthat the model is enabled, that the user's plan rank reaches the model's tier, that attachments fit the model, and that the user has allowance, credits or a rewarded unlock. Failing checks answer with a plain error before anything is charged.
  3. Moderationruns on the server: your blocked words, then the optional moderation endpoint. A blocked prompt is never sent to the provider and its text is not stored.
  4. The provider answersand the backend streams the text back as Server-Sent Events. The allowance or credit is charged when the stream starts; if the provider fails before the first word, it is refunded.
  5. Counting, not storingThe backend adds the token counts the provider reported to the daily statistics. It stores no message text. The app saves the conversation on the device.

Images, image edits, AI video, natural voices and transcription follow the same pattern: check, moderate where it applies, charge, call the provider, refund on failure. AI video runs as a job: the app polls it until the provider has finished, and the finished file is copied into your Storage.

05The public demo

The same API code also runs without Firebase, with an in-memory store and the sample configuration: that is npm run dev:api on your computer and the public web demo. In this mode it uses no key unless the host sets DEMO_AI_* environment variables, and labels every demo reply and sample: sample picture, "Sample headline — demo", "Sample clip — demo", "Sample captions — demo", "Sample transcript — demo". Natural voices are not available there; the app reads aloud with the device voice.