Case Study // Exam-Prep Platform

cp-binom
EdTech Platform

Java 21Spring Boot 3.5PostgreSQL 16FlywayRustFSReact 18ViteTailwind 4Playwright
View Live Platform
01 // Executive Summary
The Challenge

A Growing School
With No Software

A tutoring center serving 200+ students operated through messaging apps, spreadsheets, and email — fragmented across teachers, students, and parents. Course materials lived in chat threads. Test results were tracked manually. Schedules were a moving target. The school needed a single source of truth — but no off-the-shelf system covered the unique workflows of a tutoring business.

The Solution

Self-Hosted EdTech
Built From Scratch

A full-stack platform built end to end. Java 21 and Spring Boot 3.5 on the backend: JWT authentication, PostgreSQL 16 under Flyway, S3-compatible RustFS for files, jsoup sanitising every piece of user-submitted HTML. React 18 with Vite and Tailwind 4 on the front, TipTap for content editing, FullCalendar and drag-and-drop for the timetable. It runs on one VPS behind nginx — Docker Compose, TLS from certbot, rate limits, security headers, Prometheus for monitoring, and nightly database backups.

02 // Key Outcomes
37k

Lines of code

Java backend, React frontend

27

Database tables

20 Flyway migrations

20

REST controllers

Auth, courses, quizzes, chat

Apr 2026

In production

Commissioned, in daily use

03 // Technical Highlights

Auth written from scratch

JWT with refresh-token rotation, email verification and password-setup links, and three roles — student, teacher, admin — enforced across 20 REST controllers. No third-party identity provider.

Self-hosted object storage

An S3-compatible RustFS instance keeps course materials, quiz images, chat attachments, news media and programme PDFs in four separate buckets. It replaced MinIO in October 2026 without a single change to the backend code. Files never leave the customer's own server, and there is no storage bill.

Two paths to indexable HTML

After every build a Playwright job crawls each public route and stores a static snapshot that nginx serves first — to everyone, so content is painted before any JavaScript runs. Search bots additionally get pages rendered straight from the database, split by User-Agent inside nginx.

04 // Project Walkthrough
LIVE // CP-BINOM.RU
PRJ-001

Live in Production

The platform has been running at cp-binom.ru since April 2026 and is used daily by the centre's students and teachers. The portal itself is behind a login; the public part is open to anyone.

About this project

Questions
about the architecture?

Happy to walk through the decisions behind it — why self-hosted storage, why two rendering paths for the same content, and what I would do differently next time.