wanis.dev
← All work
FreelanceLive ↗

ScopioQCM

A live, paid, French-language exam-prep platform for Algerian medical students, built on Next.js and Postgres.

Where
Freelance
Stack
Next.js · PostgreSQL (Neon) · Firebase

Visit live site

Context

Medical students in Algeria prepare for exams with QCM (multiple-choice) practice. ScopioQCM gives them that practice online, in French, as a paid subscription.

My role

Independent freelancer and main developer, working directly with the client. I didn’t start it from scratch: I took it over, and now build features and keep it running in production.

Architecture

sign inverify ID tokenpayment proofreview & approvewebhookgrants subscription

Student

Next.js app
on Vercel

Firebase Auth

Postgres on Neon
via Prisma

Upstash Redis

AWS S3 · SES

Admin

Paddle
international cards

Fig. 1 — ScopioQCM, simplified
  1. A Next.js app on Vercel, with Postgres on Neon through Prisma. Neon branching gives staging and test environments their own copy of the database.
  2. Students sign in with Firebase. The server verifies the Firebase ID token, then issues the app’s own session, stored in the database and set as a cookie.
  3. Files go to S3, email through SES, and Upstash Redis handles caching.

Two ways to pay

Students abroad can subscribe online through Paddle. But almost all students pay locally, and there is no automated way to take local payments in Algeria for a product like this. So the main flow is manual:

  1. The student submits a payment form with proof of payment.
  2. An admin reviews the proof and approves it.
  3. Approval automatically grants the subscription the student asked for.

The manual step is the one that can’t be avoided. Everything after the admin’s decision is automatic.

Design decisions & trade-offs

  • Firebase for identity, own sessions for the app. Firebase proves who the user is; the app issues and controls its own sessions. Trade-off: two systems involved in login, but sessions can be revoked and inspected without depending on Firebase.
  • Neon branching per environment. Staging and test get their own database branch instead of a shared, drifting copy. Trade-off: environments have to be created and cleaned up deliberately.
  • Manual approval, automatic fulfilment. Humans only where the payment rails force them. Trade-off: activation waits on an admin, so students aren’t served instantly.
  • Two payment paths, one subscription model. Paddle and manual approval both end by granting the same subscription, so the rest of the app doesn’t care how someone paid. Trade-off: two flows to keep consistent, for a card path that only a few students use.

Stack

Next.js · TypeScript · Vercel · PostgreSQL (Neon) · Prisma · Firebase · Paddle · Upstash Redis · AWS S3 · AWS SES · PostHog