← All projects
Case study · Edtech · Marketplace · Web

An Arabic-first e-learning marketplace for Algerian students, live with thousands of enrolled learners.

Nawafid lets teachers publish video courses, quizzes and files, lets students pay by bank transfer and get approved, and gives the operator commissions, reports and staff permissions. Designed, built and operated by one person on React, Supabase and Mux.
RoleProduct, design, full-stack, operations
Timeline2026, in production since June
PlatformResponsive web app, RTL
StackReact 18, TypeScript, Vite, Supabase, Mux, OpenRouter
www.nawafiddz.com/#/
Nawafid home page
2,150+
registered students
760+
course enrolments
69
courses from 13 teachers
51
routes, 21 tables, 4 roles

Overview.

Who it is for, what was broken, what shipped.
The audience

Algerian school students and their parents

From fourth grade to the baccalaureate year. They pay in dinars by CCP or BaridiMob transfer, use Arabic, and mostly browse on phones. The teachers are independent tutors who already have a following.

The problem

Tutoring runs on WhatsApp and cash

Lessons shared as loose video links, payments confirmed by chat, no progress tracking, no exams, and no way for a teacher to sell to students outside their city.

The product

A marketplace with an operator in the loop

Teachers publish courses with video, quizzes and files. Students enrol by uploading a transfer receipt that a human approves. The platform takes a commission and gives every role its own dashboard.

Walkthrough.

Desktop captures from the live site, page by page.
01 · Landing

A landing page that sells a school, not a SaaS

Parents and students in Algeria are the buyers. The home page speaks to them in Arabic, leads with real teachers and real numbers, and keeps every call to action pointed at the catalog or sign-up.

www.nawafiddz.com/#/
Live stats strip and subject bar
Live counts: students, teachers, hours, support
www.nawafiddz.com/#/
What sets Nawafid apart section
Why Nawafid: accredited teachers, live and recorded lessons, PDFs, certificates
  • 1
    Made in AlgeriaThe header badge, CCP payment methods and ar-DZ copy make the platform feel local. Right-to-left layout throughout, on every breakpoint.
  • 2
    Proof up frontStudent count, five-star rating and a live-class chip sit on the hero illustration. The numbers are wired to the marketing copy, the catalog reads them from the database.
  • 3
    Two paths, one funnelCreate account or browse courses. Both end at the same enrolment flow, so nothing on the landing page is a dead end.
02 · Levels and teachers

Structured by school stage, fronted by people

Algerian schooling has three stages and exams that matter. The site is organised the same way, and the teachers are shown by name and subject because that is what parents ask about first.

www.nawafiddz.com/#/#levels
Choose your school stage
Elementary, middle and high school entry points
www.nawafiddz.com/#/#teachers
Nawafid teachers section
Teachers filtered by stage, with photos and subjects
  • 1
    Three stagesPrimary, middle and secondary, each with its own card, course count and a direct link into the filtered catalog.
  • 2
    Teachers by subjectPhotos, subject, stage and years of experience. The teacher record drives the course page, the revenue split and the approval queue later on.
  • 3
    Stats stripRegistered students, teachers, hours of content and support hours, rendered from live counts rather than hard-coded text.
03 · Catalog

Sixty-nine courses, filterable in two taps

The public catalog is the busiest page. It has to work for a parent on a phone and a student comparing prices, so filtering is by stage and by course type, with prices in dinars and discounts shown honestly.

www.nawafiddz.com/#/public-courses
Public course catalog with stats and course cards
Catalog stats and course cards with teacher photos
www.nawafiddz.com/#/public-courses
Catalog search and filters
Search plus stage and course-type filters with counts
  • 1
    Filters with countsSchool year (from fourth grade to final year) and course type (monthly, seasonal, annual). Each chip shows how many courses match before you tap.
  • 2
    Honest pricingOriginal price, discounted price and the percentage saved on every card. Monthly subscriptions from 1,200 DZD, seasonal courses from about 3,400 DZD.
  • 3
    Cards that load fastThumbnails are compressed to WebP on the teacher's device at upload time and served with immutable caching. That fix is what kept the platform on the free storage tier.
04 · Course page

Everything a parent needs before paying

A course page carries the schedule, what is included, the teacher's profile and the price. It is the page people send to each other on WhatsApp, so it has to answer every question without a login.

www.nawafiddz.com/#/public-courses/…
Course page with price and inclusions
Stats, inclusions and the price card with discount
www.nawafiddz.com/#/public-courses/…
Course page teacher card
Program outline and the teacher's card
  • 1
    Schedule and formatLive session times, recorded replays, PDF summaries, homework and exams, all listed in the description block.
  • 2
    Price cardDiscounted price, original price struck through, percentage saved and a single enrol button. No hidden fees.
  • 3
    Teacher cardName, stage, subject, bio, graduates, rating and years of experience, pulled from the same teacher record the admin manages.
05 · Enrolment without a gateway

Pay by CCP or BaridiMob, upload the receipt, get approved

There is no Stripe in Algeria. Instead of blocking on that, the platform turns a bank transfer into a reviewable request with a clear status for the student and a queue for the teacher.

www.nawafiddz.com/#/login
Sign-in page
Sign-in, with one-step student registration behind it
  • 1
    Per-course payment detailsEach course carries its own CCP account or BaridiMob number, so a teacher can be paid to their own account.
  • 2
    Receipt uploadThe student uploads a screenshot of the transfer. It lands in a pending queue with the course, the amount and the timestamp.
  • 3
    Approval creates accessA teacher or admin approves the request, which creates the enrolment and records the commission split. Nothing on the client can grant access to itself.
06 · Student experience

Video that is hard to steal, quizzes that grade themselves

Once enrolled, students watch lessons through Mux, track progress, take quizzes and download materials from their dashboard.

  • 1
    Mux player with hardeningBlocked context menu, intercepted fullscreen keys, tab-visibility monitoring and a security timeout around the player. It deters casual copying without pretending to stop screen capture.
  • 2
    Quizzes with mathPassing score, time limit, attempt limits and KaTeX-rendered questions with images. Attempts are graded server-side and explanations show after submission.
  • 3
    Files and progressPDF library per course with view-only mode through an embedded viewer when downloads are disabled. Lesson progress is stored per student.
07 · Teacher dashboard

Upload, build, publish, get paid

Teachers run their own courses: upload video straight to Mux, build lessons and quizzes, approve enrolment requests and watch net revenue after commission.

  • 1
    Direct-to-Mux uploadThe browser uploads to Mux directly. A signed webhook reports when the asset is ready and a status function catches stuck uploads.
  • 2
    AI quiz generationPaste lesson content and get draft questions from an LLM, then edit them in the same editor as manual questions.
  • 3
    Requests and revenueA queue of pending subscribers to approve, and a revenue page showing gross, commission and net per course.
08 · Admin and staff

A marketplace needs an operator

Admins manage teachers, students, courses, commissions and reports. Staff accounts get page-level permissions so a support worker can approve payments without seeing revenue.

  • 1
    Page-level RBACThirteen page keys such as courses, subscribers and commissions. A worker sees only the pages an admin grants.
  • 2
    Commissions and reportsPlatform commission per enrolment, teacher net revenue, activity log and alerts.
  • 3
    Admin-created teachersTeacher accounts are created by an edge function with the service role, never by open sign-up.
Live-class links per course
Lesson comments with likes
Community management
Password recovery deep links
Activity log and alerts
WhatsApp support button
Responsive RTL on every page

Architecture.

A single-page app on Supabase, with Mux for video and an LLM for quizzes.
Client
React 18 + Vite SPA51 routes · hash routing · shadcn/ui on Radix · Tailwind · TanStack Query · react-hook-form + zod · recharts · KaTeX
Four dashboards, one buildPublic site, student, teacher and admin/staff areas gated by ProtectedRoute with allowed types and page keys
Mux PlayerPlayback component with client-side anti-piracy hardening
→
Supabase
Postgres 1721 tables: profiles, students, teachers, courses, lessons, progress, comments, enrolments, materials, payment details, pending subscribers, quizzes, attempts, files, livestreams · RLS · GIN-indexed course_ids arrays
Edge Functions (Deno)ai-generate-questions · create-admin-staff · mux-upload · mux-webhook · mux-status · mux-check-upload
Auth + StorageEmail/password with recovery flow · buckets for files, thumbnails and quiz images with WebP compression and immutable caching
→
External
MuxDirect uploads · HMAC-verified webhooks · CDN playback
OpenRouter / OpenAIQuiz question generation from lesson content
PaymentsCCP and BaridiMob transfers reviewed by humans · no gateway

Engineering deep dives.

Six decisions that shaped the platform.

1. Manual-payment subscription pipeline

Problem
The Algerian market has no card gateway that students can use. Enrolment still has to be reliable and auditable.
Approach
Per-course payment details (CCP or BaridiMob), a receipt-upload page, a pending_subscribers queue, approval screens for teachers and admins, then course_enrollments plus a commission record so admin gross and teacher net revenue reconcile.
Trade-off
A human reviews every payment. Right for bank transfers, but there is no automated reconciliation.
Lives in: CourseSubscribe, TeacherRequests, Subscribers, AdminCommissions, TeacherRevenue

2. Mux video pipeline with signed webhooks

Problem
Teachers upload large videos from ordinary connections, and the platform must know when playback is ready without polling forever.
Approach
Direct upload URLs from Mux, a Deno edge function that verifies the mux-signature header with HMAC-SHA256 before persisting asset and playback ids, and a separate status function for stuck uploads.
Trade-off
The same endpoints exist in three homes (edge functions, an Express server and serverless handlers) from a migration. Flexible, but duplicated.
Lives in: supabase/functions/mux-upload, mux-webhook, mux-status

3. Anti-piracy player hardening

Problem
Paid lessons get copied and reshared. Nothing client-side can stop a determined screen recorder, but casual copying can be made annoying.
Approach
Capture-phase key interception that blocks the player's own fullscreen hotkey, context-menu suppression, visibility-change monitoring and a security timeout around the player.
Trade-off
Client-side only. Documented as a deterrent, not a DRM system.
Lives in: StudentCourseView, VIDEO_PROTECTION_GUIDE

4. The storage-egress fix

Problem
Uncompressed phone-camera PNGs blew through the free-tier Supabase egress, which would have meant a paid plan for a platform charging in dinars.
Approach
Client-side canvas re-encoding to WebP with EXIF orientation correction, one-year immutable cache headers on upload, a lazy-loading SmartImage component, and a script plus SQL guardrails to recompress existing objects.
Trade-off
Compression happens on the uploader's device, so quality depends on the browser's canvas. Zero server cost in exchange.
Lives in: src/lib/imageOptimization.ts, src/lib/storageUpload.ts, scripts/recompress-storage-images.mjs

5. Files and quizzes linked to many courses

Problem
A teacher's PDF or quiz often applies to several courses. A junction table would have needed a migration with downtime on a live platform.
Approach
A course_ids UUID array with GIN indexes and overlap queries, keeping the original course_id for backward compatibility, plus per-file visibility and download-allowed flags that drive student-side filtering.
Trade-off
Array columns are simpler to query but weaker on referential integrity than a junction table.
Lives in: TeacherFiles, StudentFiles, multi_course_files_quizzes_and_visibility migration

6. Auth deep links under hash routing

Problem
Supabase recovery emails put tokens in the URL fragment, which collides with hash-based routing. Users landed on a 404.
Approach
Recovery redirects to the site root, token and error hashes are rewritten into a routable reset-password URL, the app listens for the PASSWORD_RECOVERY event, and legacy double-hash links are handled by setting the session manually.
Trade-off
Hash routing was inherited from the original build and kept to avoid breaking shared links.
Lives in: AuthContext, ResetPassword

Business model.

Commission on every approved enrolment, four roles, no gateway fees.
1 · CourseTeacher sets price, discount and their own CCP or BaridiMob details.
2 · TransferStudent pays by bank or mobile transfer, then uploads the receipt.
3 · QueueRequest lands in pending subscribers with amount and time.
4 · ApprovalTeacher or staff approves. Enrolment and commission are written server-side.
5 · RevenueAdmin sees gross and commission. Teacher sees net.
Student
  • Browse and enrol
  • Watch, quiz, download
  • Track progress
Teacher
  • Publish courses and lessons
  • Approve requests
  • Net revenue and students
Worker
  • Page-level permissions
  • Approve payments
  • Support without revenue access
Admin
  • Everything, plus commissions
  • Create teacher accounts
  • Reports, alerts, activity log

Results.

What the database and the site show today.
Traction

Thousands of students, hundreds of paid enrolments

More than 2,150 registered students, over 760 approved course enrolments and 69 published courses from 13 teachers, all counted from the production database.

Cost

Still on the free storage tier

Client-side WebP compression and immutable caching brought storage egress back under the free limit after the first surge of phone-camera uploads.

Operations

Payments without a gateway, at scale

Hundreds of transfers reviewed and approved through the in-app queue, with commission and net revenue reconciled per course.