# JobsMedical — Medical Shift Marketplace (Iran)

> A niche platform connecting **GP doctors** with **hospitals & clinics** that have open shifts.
> Replaces the chaotic hunt across Bale / Telegram channels / Divar with one structured,
> filterable view organized by **hospital, location, and weekly shift calendar**.

Date: 2026-06-02 · Market: Iran (Persian/Farsi, RTL) · Revenue: TBD

---

## 1. The problem & the bet

**Today:** A GP doctor wanting locum/extra shifts scrolls dozens of Telegram/Bale channels and
Divar posts. Listings are unstructured text, no filters, no calendar, no trust signals, expire
silently. Hospitals broadcast to the same noisy channels and get random DMs.

**Our bet:** The value isn't *more* listings — it's **structure + filtering + trust**.
"Show me open GP shifts, in Tehran, this week, paid X" should be one screen, not 40 channels.

**Why a marketplace is hard (and our answer):**
- *Cold-start problem* — empty marketplace helps no one. We solve supply first via the **mixed
  strategy**: (1) admin posts manually + (2) auto-aggregate from channels → so the site looks
  full from day one, then (3) convert hospitals to self-serve posting over time.

---

## 2. The two sides

| | Doctors (supply of labor) | Hospitals / Clinics (demand) |
|---|---|---|
| Who | GPs (پزشک عمومی) seeking shifts | Hospitals, clinics, درمانگاه‌ها |
| Want | Find shifts fast: by city, date, pay | Fill open shifts with vetted doctors |
| Onboard via | Phone OTP signup, build profile | Phase 2 self-serve; phase 1 we post for them |
| Trust signal | نظام پزشکی (medical license) number | Verified facility badge |

---

## 3. MVP scope (Phase 1 — "the structured board")

Goal: a doctor can **find and express interest in a relevant shift in under 60 seconds**.

**Must have:**
1. **Shift browse + filter** — by city, hospital, date range, specialty, shift type (day/night), pay.
2. **Weekly calendar view** per hospital — the signature feature. Jalali (Shamsi) week grid showing
   open shifts per day.
3. **Shift detail page** — hospital, location (map pin), date, hours, pay, requirements, how to apply.
4. **Doctor signup/login** — phone OTP (standard in Iran), basic profile (name, license, city, specialty).
5. **Express interest / apply** — doctor taps "interested" → handoff to facility contact (call/Bale/
   in-app message). Track applications.
6. **Admin panel** — we add/edit shifts manually, and review/normalize aggregated listings before
   they go live.
7. **Aggregation ingest (basic)** — pull text from selected Telegram/Bale channels into a "raw
   listings" queue for admin to normalize. (Start semi-manual; full automation later.)

**Explicitly NOT in MVP** (Phase 2+):
- Hospital self-serve posting & dashboards
- Payments / monetization
- Ratings & reviews
- Automated matching/recommendations, push alerts
- Full unattended scraping pipeline

---

## 4. Data model (core entities)

```
User            id, phone, full_name, role(doctor|facility_admin|admin), created_at
DoctorProfile   user_id, license_no(نظام پزشکی), specialty, city, years_exp, bio, verified
Facility        id, name, type(hospital|clinic|درمانگاه), city, address, lat,lng,
                phone, bale_id, verified, owner_user_id(nullable, phase 2)
Shift           id, facility_id, date(jalali stored as ISO), start_time, end_time,
                specialty_required, shift_type(day|night|on_call), pay_amount, pay_type,
                description, status(open|filled|expired|cancelled),
                source(direct|admin|aggregated), source_url, created_at
Application     id, shift_id, doctor_id, status(interested|accepted|rejected|withdrawn),
                message, created_at
RawListing      id, source_channel, raw_text, parsed_json, status(new|normalized|discarded),
                linked_shift_id, fetched_at      ← aggregation staging area
City            id, name, province              ← canonical city list for filters
```

Key decisions:
- **Dates stored as ISO (UTC) in DB, displayed as Jalali** in the UI. Never store Jalali strings.
- A `Shift` can originate from a `RawListing` (aggregation) or be created directly (admin/facility).
- Phone is the unique identity; OTP login, no passwords.

---

## 5. Tech architecture

Constraints that drive choices: **Iran hosting** (many global SaaS block Iranian IPs/payments →
prefer self-hostable, open-source), **SEO matters** (doctors will find shifts via Google → need
server-rendered pages), **RTL + Jalali**, **phone OTP** via Iranian SMS providers.

**Recommended stack:**
- **Frontend + backend:** Next.js (App Router) + TypeScript — SSR for SEO, one codebase, great RTL support.
- **UI:** Tailwind CSS (RTL mode) + a Persian font (Vazirmatn). Jalali via `dayjs-jalali` or `jalaali-js`.
- **DB:** PostgreSQL + Prisma ORM.
- **Auth:** Phone OTP. SMS via **Kavenegar** or **SMS.ir** (Iranian providers). Sessions via JWT/cookies.
- **Maps:** Neshan or Balad map tiles (Iranian, work without VPN) instead of Google Maps.
- **Aggregation:** A small worker (Node) using Telegram Bot API / Telethon-style reader for Bale,
  writing into `RawListing`. Runs as a separate scheduled job.
- **Hosting / CI:** Self-hosted on an Iranian VPS, deployed via your **Gitea + Nexus** pipeline
  (soroush ci/cd method). Docker Compose: web + postgres + worker.

> If you'd rather build in **.NET** (you have the Nexus/.NET pipeline set up), the equivalent is
> ASP.NET Core + Blazor/Razor + EF Core + Postgres. Same architecture, different language. ← confirm.

**Why not Google Maps / Vercel / Firebase / Stripe:** all routinely blocked or unusable from Iran.
Everything above is self-hostable or has an Iranian equivalent.

---

## 6. Key screens

1. **Home** — hero + search (city, specialty, date) + "shifts this week" + featured hospitals. SEO landing.
2. **Shift listing** — filter sidebar + result cards + map toggle.
3. **Weekly calendar** (per hospital or per city) — Shamsi week grid, open shifts as chips.
4. **Shift detail** — all info + map + "I'm interested" CTA.
5. **Doctor onboarding** — phone OTP → profile form.
6. **Doctor dashboard** — my applications, saved shifts.
7. **Admin** — shift CRUD, raw-listing normalization queue, facility management.

---

## 7. Phased roadmap

- **Phase 0 — Foundation:** repo, Docker, Postgres+Prisma schema, RTL+Jalali shell, OTP auth. 
- **Phase 1 — MVP board:** browse/filter, calendar, shift detail, doctor signup, apply, admin CRUD,
  basic raw-listing ingest. → *launch to a few hospitals + a doctor Telegram group.*
- **Phase 2 — Self-serve + trust:** hospital posting dashboards, facility/doctor verification,
  in-app messaging, saved searches + alerts (via Bale bot).
- **Phase 3 — Monetization:** pick model (likely **hospitals pay to post** or **commission per
  filled shift** — decide after we see what converts), Iranian payment gateway (Zarinpal/IDPay).
- **Phase 4 — Scale:** full automated aggregation, recommendations, expand beyond GPs to specialists.

---

## 8. Open questions to revisit

- Monetization model (deferred — validate demand first).
- Which specific Telegram/Bale channels to aggregate first?
- Start single-city (Tehran?) to concentrate liquidity, or national from day one?
- Build language: **TypeScript/Next.js** (recommended) vs **.NET** (your existing pipeline)?
```
