MoMo Own It is a mini app that turns layby and pay-as-you-go two things people across Africa already do, on paper into one automated payment plan running on MoMo.
# MoMo Own It — backend
Layby and pay-as-you-go, running as one payment engine on MTN MoMo.
Two modes, one codebase:
| | **Reserve** (layby) | **Take It Now** (pay-as-you-go) |
|---|---|---|
| Who holds the item | Supplier | Customer, from day one |
| If payments stop | Plan pauses, nothing is lost | Device locks until payments resume |
| Supplier is paid | Once, on completion | Upfront or progressively |
| Legal shape | Deposit arrangement (CPA) | Instalment credit agreement (NCA) |
The mode is a flag, not a second codebase. It forks the logic in exactly two
places, both in `src/domain/plan.ts`:
1. `possessionFor()` — at plan start, does the item release now or is it held?
2. `onMissedPayment()` — on a miss, does something switch off, or does the plan stretch?
Everything else — collection, ledger, progress, reminders, completion,
record-building — is shared.
## Run it
Needs Node 20+ and Docker.
```bash
cp .env.example .env # working demo defaults, nothing to fill in
docker compose up -d db # wait for it to report healthy
npm install
npm run migrate
npm run seed
npm run dev
```
Then open . `GET /health` tells you whether the database
is up and which MoMo provider is live.
The copied `.env` runs entirely on `MOMO_PROVIDER=mock` — no MoMo credentials, no
network — with the billing clock at twenty seconds per "week" so plans move while
you watch. Two of its values are what make the demo *live* rather than static:
`SCHEDULER_ENABLED=true` and `BILLING_PERIOD_SECONDS=20`. With the scheduler off,
or the clock at a real week, everything loads and then nothing ever happens.
**If port 5432 is already taken** — you have Postgres installed natively — `docker
compose up` fails to bind. Publish the container somewhere else instead:
```bash
cat > docker-compose.override.yml <<'EOF'
services:
db:
ports:
- "5455:5432"
EOF
```
Then point `DATABASE_URL` at 5455 in your `.env`. The override file is gitignored,
so it stays local to your machine.
To wipe the d …