E-learning platform · Course marketplace
Browse a curated course catalog, purchase access via Stripe, and consume video lessons. Teachers publish and manage their own courses through a dedicated dashboard.
Learn Hub is a full-stack web application with two clearly separated roles:
- Students browse the catalog with filters and search, buy courses via Stripe, and watch video lessons from their personal dashboard.
- Teachers create courses with cover images and video uploads (via Cloudinary), set pricing and metadata, and manage their published catalog.
A REST API powered by Flask sits behind the React frontend. JWT-based auth gates the student and teacher dashboards, and an admin panel at /admin provides direct DB access for inspection.
┌────────────────┐ HTTP / JSON ┌───────────────────┐
│ React SPA │ ──────────────────────▶│ Flask API │
│ (port 3000) │ ◀──────────────────────│ (port 3001) │
└───────┬────────┘ └─────┬─────────────┘
│ │
│ Stripe.js │ SQLAlchemy 2
│ Checkout │
▼ ▼
┌────────────────┐ ┌───────────────────┐
│ Stripe │ │ PostgreSQL │
│ Payments │ │ (learn_hub) │
└────────────────┘ └───────────────────┘
▲
│
┌───────┴──────────┐
│ Cloudinary │
│ (image / video) │
└──────────────────┘
learn-hub/
├── src/
│ ├── api/ Flask blueprint: routes, models, admin
│ │ ├── models.py SQLAlchemy 2 models
│ │ ├── routes.py REST endpoints
│ │ ├── admin.py Flask-Admin views
│ │ └── utils.py API helpers
│ ├── app.py Flask app factory
│ ├── wsgi.py WSGI entry point (Gunicorn)
│ └── front/
│ ├── js/
│ │ ├── pages/ Top-level routes
│ │ ├── component/ Reusable UI components
│ │ └── store/ Flux store + Context provider
│ ├── styles/ CSS per page / component
│ └── img/ Static assets
├── migrations/ Alembic migrations
├── public/ Webpack output target
├── pyproject.toml uv-managed Python deps
├── package.json pnpm-managed Node deps
└── Makefile make dev and friends
| Tool | Install |
|---|---|
uv |
brew install uv or curl -LsSf https://astral.sh/uv/install.sh | sh |
pnpm |
brew install pnpm or npm install -g pnpm |
| Node 16 | nvm install 16 && nvm use 16 |
| PostgreSQL | Running locally on :5432 with a postgres superuser |
git clone https://github.com/iRuperth/learn-hub.git
cd learn-hub
createdb -U postgres learn_hub
psql -U postgres -d learn_hub -c "CREATE EXTENSION IF NOT EXISTS unaccent;"
make devmake dev will create .env from the template, install Python deps with uv sync, install Node deps with pnpm install, and start both servers in parallel.
Open http://localhost:3000 — the API lives at http://localhost:3001.
| Target | What it does |
|---|---|
make dev |
Run backend and frontend in parallel |
make install |
Install backend and frontend dependencies |
make install-back |
Install Python deps only (uv sync) |
make install-front |
Install Node deps only (pnpm install) |
make back |
Run backend only on :3001 |
make front |
Run frontend only on :3000 |
make lock |
Regenerate uv.lock from pyproject.toml |
make stop |
Kill any dev processes on ports 3000/3001 |
# Apply pending migrations
uv run flask --app src/app.py db upgrade
# Create a new migration after editing models
uv run flask --app src/app.py db migrate -m "describe change"
# Roll back the most recent migration
uv run flask --app src/app.py db downgrade# Backend
uv run --env-file .env flask --app src/app.py run -p 3001
# Frontend
pnpm start
# Production build
pnpm run buildCopy .env.example to .env and fill in:
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
FLASK_APP_KEY |
Secret key for Flask sessions and JWT |
BACKEND_URL |
Public API URL (defaults to :3001) |
STRIPE_PRIVATE |
Stripe secret key |
STRIPE_PROMISE |
Stripe publishable key |
CLOUDINARY_NAME |
Cloudinary cloud name |
CLOUDINARY_KEY |
Cloudinary API key |
CLOUDINARY_SECRET |
Cloudinary API secret |
Frontend — React 16, React Router 6, Bootstrap 5, Webpack 5, Babel, Flux pattern with Context API, React Player, Stripe.js
Backend — Python 3.10+, Flask 3, SQLAlchemy 2, Flask-SQLAlchemy, Flask-Migrate (Alembic), Flask-JWT-Extended, Flask-Admin, Flask-CORS, Gunicorn
Database — PostgreSQL with Alembic migrations and the unaccent extension
Tooling — uv for Python, pnpm for Node, GNU Make for orchestration
Third-party — Stripe for payments, Cloudinary for media hosting
The repo ships with a render.yaml and a Procfile configured for Render:
# Render runs render_build.sh on every push
pnpm install && pnpm run build
uv sync
uv run flask --app src/app.py db upgradeThe web service then runs uv run gunicorn wsgi --chdir ./src/.