SaaS · payments
Garsha گرشا
A paid AI-tools platform with phone sign-in, a wallet and tiered plans.
Stack
- Backend
- Django REST JWT Phone OTP
- Frontend
- React Vite
- Data & ML
- PostgreSQL
- Integrations
- ZarinPal
01 The problem
Selling AI tools to people in Iran means international cards and subscriptions are off the table, and a phone number is the identity people actually use.
The product needed local sign-in, local payments and a way to charge for usage without sending every request through a payment gateway.
02 What I built
Designed, built and run by one developer.
A SaaS that sells access to AI tools. Users sign in with a one-time code sent to their phone, top up an internal wallet through ZarinPal, and use tools according to their plan tier. Backend, frontend and the entire payment flow designed and built alone: Django REST with JWT, React + Vite.
- Sign-in with a one-time code sent to the user's phone, issuing JWTs for the API.
- An internal wallet that users top up through ZarinPal and spend down as they use tools.
- Tiered plans that decide which tools a user can open.
- The full payment flow — checkout, gateway callback, verification and wallet credit — designed and built alone.
- A React + Vite front end on a Django REST API with PostgreSQL.
03 Screens
The live product.
01 / 03
The tools catalogue. ArchPan and Pico are sold through it.
Tiered plans priced in toman, for individuals and businesses.

The landing page on a phone.
04 Architecture
How Garsha fits together.
- Component
- Third party
- Request
Connections
- Browser to React + Vite
- React + Vite to Django REST · JWT , JSON · JWT
- Django REST · JWT to OTP auth
- OTP auth to SMS provider , one-time code
- Django REST · JWT to Wallet & plans
- Wallet & plans to ZarinPal , pay · verify
- OTP auth to PostgreSQL
- Wallet & plans to PostgreSQL , ledger
05 Key decisions
What I chose, why, and what it cost.
-
Decision
Phone OTP instead of email and password
Why
Users already identify themselves by phone number everywhere else, so sign-up is one field and a code, with no password to forget.
Trade-off
A dependency on an SMS provider, and codes need expiry and rate limits so the endpoint can't be abused.
-
Decision
A wallet between the user and the payment gateway
Why
A gateway round trip for every use would be slow and expensive. Users top up once and each use is a deduction from their balance.
Trade-off
I own a ledger. Every credit and deduction has to be atomic and traceable, because the balance is real money.
-
Decision
Trust the server's verification, not the redirect
Why
ZarinPal sends the user back with a result, but that redirect can be replayed or faked. The API verifies each transaction with ZarinPal before crediting the wallet, and a payment can only be credited once.
Trade-off
More states to model — pending, verified, failed, abandoned — and each needs a clear screen for the user.
06 Try it yourself
Garsha is running. Go and use it.
There is no shared demo account: sign-in sends a one-time code to your own phone number.