# Architecture ## Overview Meme Jockey is a two-part system: a **FastAPI** backend that does image/GIF processing + auth + storage, and a **React Native** mobile app. ``` ┌─────────────────────┐ HTTPS / JSON · form-encoded ┌──────────────────────────┐ │ Mobile app (RN) │ ───────────────────────────────────────▶ │ FastAPI backend │ │ Android (0.80) │ Bearer JWT on every protected call │ (Hugging Face Space, │ │ │ ◀─────────────────────────────────────── │ Docker, port 8000) │ └─────────────────────┘ └────────────┬─────────────┘ │ ┌───────────────────────┬──────────────┼───────────────┐ ▼ ▼ ▼ ▼ ┌────────────┐ ┌──────────────┐ ┌───────────┐ ┌────────────┐ │ PostgreSQL │ │ Object store │ │ OpenAI │ │ Giphy │ │ (Neon) │ │ (Backblaze │ │ (captions)│ │ (GIF search)│ │ users, │ │ B2 / MinIO) │ └───────────┘ └────────────┘ │ otps, │ │ uploads + │ │ media, │ │ generated │ │ subs │ │ memes │ └────────────┘ └──────────────┘ ``` ## Backend layout (`backend/`) | Path | Responsibility | |---|---| | `main.py` | App wiring, middleware, meme/media/profile/admin endpoints | | `routers/auth.py` | OTP, PIN, refresh, Google login, profile (`/auth/*`) | | `routers/subscriptions.py` | Razorpay order/verify/status, receipts, history, PDF, config-check (`/subscriptions/*`) | | `utils/receipt.py` | Renders a payment receipt as a PDF (Pillow-only) | | `auth/security.py` | JWT mint/verify, phone normalize, hashing, guest config | | `auth/deps.py` | `current_user_id` dependency (Bearer → user id) | | `auth/sms_provider.py`, `utils/sms_fast2sms.py` | OTP delivery (Fast2SMS, or log) | | `utils/ai_overlay.py` | OpenAI suggestions + Giphy/Tenor search | | `utils/storage_minio.py` | S3-compatible put/get/presign | | `db/postgres_client.py` | All DB access (asyncpg + SQLAlchemy), per-request session | | `db/database.py` | Engine/driver selection from env | | `db/models.py` | SQLAlchemy models (users, otps, media_assets, …) | | `db/init.sql` | Schema bootstrap (run in Neon SQL editor) | > `db/supabase_client.py` is legacy/unused — the app uses `postgres_client`. ## Data model (key tables) - **users** — `id`, `phone_e164` (unique key; Google users keyed `google:`), `name`, `email`, `avatar_url`, `pin_hash`, `is_active`, `is_guest`, `account_type`, and subscription fields: `subscription_plan` (default `free`), `subscription_status` (default `inactive`), `subscription_expires_at`. - **otps** — hashed OTPs with `expires_at` / `consumed`. - **media_assets** — `object_key`, `content_type`, `kind` (`upload` | `meme`), owner. - **memes** — links input→output assets + `format`; drives daily-quota counts. - **payments** — one row per successful Razorpay payment (`plan`, `amount` paise, `currency`, `status`, `method`, `razorpay_order_id`, `razorpay_payment_id`, `expires_at`). Powers the receipt PDF and transaction history. ## Request auth flow 1. App calls `/auth/request-otp` → `/auth/verify-otp` → gets `access` + `refresh`. 2. App stores tokens; an axios interceptor adds `Authorization: Bearer `. 3. On `401`, the interceptor calls `/auth/refresh` once and retries; if that fails, the session-expired handler logs the user out. 4. Returning users can `/auth/set-pin` then `/auth/login-pin` to skip OTP. 5. Guests (`GUEST_MODE_ENABLED`) get a short-lived guest session and skip PIN. ## Meme generation flow 1. `POST /upload` (image) → stored in object storage + initial suggestions. 2. App opens the editor; user places GIF/image overlays. 3. `POST /compose/layout` with the JSON layout → server renders the meme, stores it (`kind=meme`), returns `object_key` + URL. 4. `GET /memes` lists creations; `GET /memes/{object_key}` serves them via a permanent cached proxy URL. ## Deployment - **Backend** → Hugging Face Space (Docker, `app_port: 8000`). Push to the Space repo to rebuild. Secrets/Variables set in Space settings. - **Database** → Neon (run `db/init.sql` once; re-run after schema changes — it's idempotent `add column if not exists`). - **Object storage** → Backblaze B2 (S3-compatible) with a bucket-scoped Read+Write app key. - See [DEPLOYMENT.md](../DEPLOYMENT.md) and [ACCOUNTS_AND_SERVICES.md](ACCOUNTS_AND_SERVICES.md).