Skip to content
Tehran

SaaS · payments

Garsha گرشا

A paid AI-tools platform with phone sign-in, a wallet and tiered plans.

Role
Sole developer
Year
2025
Kind
SaaS · payments
Hosting
Own server, Tehran
Status
88 ms
http:// 45.159.150.193:3000
Garsha: the live product

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.

  1. Sign-in with a one-time code sent to the user's phone, issuing JWTs for the API.
  2. An internal wallet that users top up through ZarinPal and spend down as they use tools.
  3. Tiered plans that decide which tools a user can open.
  4. The full payment flow — checkout, gateway callback, verification and wallet credit — designed and built alone.
  5. A React + Vite front end on a Django REST API with PostgreSQL.

03 Screens

The live product.

01 / 04

04 Architecture

How Garsha fits together.

  • Component
  • Third party
  • Request
Garsha’s components, grouped left to right by layer: Client, App, Data, External.

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.

  1. 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.

  2. 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.

  3. 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.

esc
Top of the page
Proof in numbers
Selected work
Also shipped
How I ship
Experience
Stack
Work with me
Pico — case study
ArchPan — case study
Garsha — case study
Fenderesky — case study
MirOffice — case study
Copy email address
Download CV
Open GitHub
Open LinkedIn
Open live demo: Pico
Open live demo: ArchPan
Open live demo: Garsha
Open live demo: Fenderesky
Open live demo: MirOffice