Spaces:
Running
Running
| # 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:<sub>`), | |
| `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 <access>`. | |
| 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). | |