LogicBisonLogicBison
Work
Back to Work
Course Platform — Multi-Company Enrollment & Management System
Education Technology (EdTech)
Production

Course Platform — Multi-Company Enrollment & Management System

Two interfaces, one codebase: a public course catalog where students enroll, and a full admin system where institutions manage courses, enrollments, and users — serving multiple companies with isolated infrastructure

Next.js 15MUIFastAPIPython 3.12CouchDBDockerNginxNextAuthApollo Server
2 (Coyol + Evolution)
Institutions served
4 (isolated)
Services per institution
1-line script → compose
Provisioning
~17 months
Development span
465
Commits across all branches
~23,000 lines
Production source code

Educational institutions don't have the same workflows, the same data, or the same branding. But they all need the same thing: a course catalog that people can browse, an enrollment process that collects everything legally required, and an admin dashboard to manage it all.

The old approach was to build a custom system for each institution. I built it differently: one codebase, one architecture, that provisions isolated instances per institution — each with its own database, its own API, its own frontend — all served through a single gateway. The result is that adding a new institution isn't a new project. It's a configuration change.

The Problem

Two industrial park operators — Zona Franca Coyol and Evolution Free Zone — needed to offer professional courses to the companies in their parks. Each needed:
- A public course catalog students could browse and search

- An online enrollment process that collected the legally required consent documents

- An admin dashboard to manage courses, enrollments, users, and generate reports

- The ability to operate independently — different branding, different courses, different data

The traditional approach — build it twice, maintain two codebases, hire two support teams — would have cost more than the program itself. They needed one solution that served both, without compromise.

The Approach

I built a multi-company platform architected around template-based provisioning. The core is a shared codebase — FastAPI backend, Next.js admin dashboard (Pages Router), and a separate Next.js public frontend (App Router) — that generates isolated instances per institution.

When a new company is onboarded, a one-line script (bin/spawn_company.sh) generates the entire config from templates:
1. A docker-compose stack is produced by templating service names, ports, and container names — CouchDB database, FastAPI backend, admin dashboard, and public API, each on its own port range (base + 0/1/2/3).

2. An Nginx gateway routes traffic by path prefix — /{company}/dashboard, /{company}/api, /{company}/fastapi — to the right container.

3. The company gets its own .env configuration, its own CouchDB database seed, its own uploads directory, its own images directory for branding, and an entry in the central companies.json registry.

The student experience: browse a course catalog with date and modality filters (in-person or virtual), view course details including seats taken and available, enroll through a multi-section enrollment form protected by reCAPTCHA v3, and receive confirmation via a double opt-in flow. When a course is full, new enrollments automatically join a waiting list.

The admin experience: drag-and-drop document upload (informed consent PDFs) with one-click verification, batch enrollment verification, bulk consent PDF generation via ReportLab/PyMuPDF, Excel exports via openpyxl, user management with role-based access control via NextAuth, and per-company stats and charts on a MUI v6 dashboard with data grids.

Behind the scenes: FastAPI handles course CRUD, enrollment processing (with automatic waiting-list assignment when seats fill), consent PDF generation, user auth, and file management. CouchDB provides per-company schema-less document storage. Each company runs as four isolated containers on its own Docker network, with the gateway on a shared external network.

The Outcome

Two institutions — Zona Franca Coyol and Evolution Free Zone — run on one codebase today, each in fully isolated stacks (CouchDB + FastAPI + admin dashboard + public API). Each manages its own courses, enrollments, and users independently; no data crosses between them.

The platform carries 465 commits across roughly 17 months of iteration and ~23,000 lines of production source code (Python + TypeScript/React, excluding vendored dependencies). Adding a new institution no longer means a new development project — it means generating config from templates and running docker compose up --build. The bottleneck moved from "reinvent for each client" to "provision and deploy," which is what makes the architecture defensible as a services business scales.

The admin dashboard replaced what would have been a mix of spreadsheets, email, and paper consent forms with a unified digital workflow — course creation, enrollment management, document collection, and reporting in one place, with the waiting-list logic enforced at the backend so no one accidentally overbooks a full class.

Key Takeaway

Multi-tenant doesn't have to mean shared data and compromise. Template-based isolation means each client gets their own infrastructure — without rebuilding the platform every time. One architecture, one command to provision, as many isolated instances as the market demands. That's how you scale a services business without scaling the engineering team.

Ready to Build Your Platform?

One 30-minute call to see if we're a fit. No pitch. No pressure. Just a conversation about what you need to build.

Most engagements start with a bounded architecture diagnostic: $5,000 to $12,000, 1 to 3 weeks. Fixed-price platform builds: $20,000 to $80,000, milestone-gated, 50% deposit. Fractional CTO: $6,000 to $10,000 per month, 90-day minimum.