// sinancanozer.dev
← back to work
API·2026·IN DEVELOPMENT

MathBank API

Gamified math practice platform for 5th–8th graders preparing for LGS, built around a ranked progression system inspired by competitive games.

Solo Developer · Personal Project · 2026
Math curriculum review by Zeynep Kabaş Özer, math teacher
  • Java 25
  • Spring Boot
  • PostgreSQL
  • JPA/Hibernate
  • JWT
  • React
  • TypeScript
MathBank API

Context#

Math practice for 5th–8th graders in Turkey looks the same way it did twenty years ago: thick test books, repetitive drills, no feedback loop. Motivation is the first thing to break, especially through the long stretch leading up to the LGS — the national high school placement exam.

MathBank started from a personal observation. Kids who spend hours grinding ranked games every weekend can't sit through twenty minutes of math homework. The problem isn't math. It's framing.

So I built a platform that treats math practice the same way games like League of Legends or Valorant treat skill development: a 25-tier ranked progression system, exam-based promotion and demotion, a question pool that scales with your rank, and badges for milestones. Every exam is a ranked match. The math is real — every question is curated against the 2025 Maarif curriculum (grades 5–6) and MEB curriculum (grades 7–8), reviewed by a math teacher I trust. The wrapper is what changes.

Challenge#

Three things were hard, and they were hard for different reasons.

The first was the schema. Thirteen entities — Grade, Subject, Subtopic, Question, User, RankExam, ExamAnswer, RankTier, Badge, and the rest — all had to relate without painting myself into a corner. RankTier alone needed to be an enum with 25 ordered values, helpers for getNextTier and getPreviousTier, and a clean way to associate questions with the tier they belong to. Get the schema wrong early and you bleed for the next ten sprints.

The second was the exam engine. Each ranked exam pulls 30 questions — 10 easy, 12 medium, 8 hard — filtered by the student's grade and current tier. Net score is calculated like the real LGS: correct minus a quarter of incorrect, with unanswered counted as wrong. Promotion, demotion, and protection-shield logic all live in one place. The whole thing has to be cheat-resistant: no peeking at the correct answer mid-exam, no starting a second exam while one is active, no accessing someone else's exam by guessing the id.

The third was operational discipline. Solo means every decision is mine. There's no architect to overrule me, no reviewer to catch the stupid mistake. So the answer was to lean hard on conventions and let the framework enforce structure.

Approach#

I picked Spring Boot deliberately. I trained in Java and Spring, and even though I don't reach for it daily, when the project demands strict structure, predictable patterns, and long-term readability, it's the ecosystem I trust most. The opinionated layout — controllers, services, repositories, DTOs — keeps a solo project from drifting into chaos.

The schema came first. Before writing any code I sketched all 13 entities, their relationships, and the RankTier enum on paper. A BaseEntity class centralized createdAt and updatedAt so I'd never write that boilerplate twice. RankTier got real methods on it, not just values — getOrder, getNextTier, getPreviousTier — so promotion logic reads naturally at the call site. I considered making rank a separate table; the enum won on performance and intent.

The exam engine uses a rich domain model. Methods like exam.finish(), exam.recordCorrectAnswer(), and exam.calculateNet() live on the entity itself. Controllers don't reach into exam state — they tell the entity what happened and let it decide. This "tell, don't ask" pattern made the engine easier to test, easier to read, and easier to extend.

Two pitfalls cost real time. First, returning JPA entities directly from controllers triggered LazyInitializationException — the classic Hibernate trap. Fix: a strict DTO layer, every response shape owned by a dedicated SubjectResponse, QuestionResponse, or ExamResponse. Second, Spring Security and multipart/form-data didn't get along on the CSV import endpoint; sorting that out meant rethinking how the security filter chain handles file uploads.

Tech Stack#

Spring Boot 4.0.3 on Java 25 sits at the core. JPA/Hibernate handles persistence against PostgreSQL — chosen for transactional safety and a feature set deep enough to grow into. JWT handles authentication with separate access and refresh tokens; BCrypt at strength 12 hashes passwords. Swagger generates API documentation automatically from the controllers.

The API exposes 25 endpoints across seven domains: auth, questions, subjects, exams, leaderboard, user stats, and badges. Versioning lives under /api/v1/ from day one so future breaking changes don't break existing clients.

The frontend is React 19 with TypeScript and Vite, styled with Tailwind. Axios handles HTTP with interceptors for token refresh. The frontend is intentionally minimal in this phase — the harder problem was the backend, and the frontend builds on top once the API surface stabilizes.

Cache, rate limiting, and load testing are planned for Sprint 8: Redis on Upstash for leaderboard caching, Bucket4j for per-user rate limits, k6 for load tests. Deployment moves to Railway for the backend and Vercel for the frontend in Sprint 9.

Visuals#

// GALLERY · 05 ITEMS
[01/05]

25-tier rank system: 5 ranks × 5 tiers, modeled as a Java enum

Domain methods on the enum: getNextTier, getPreviousTier, fromOrder

13 entities and relationships: Grade, Subject, Subtopic, Question, User, RankExam, ExamAnswer, RankTier, Badge, and more

REST API surface: 25 endpoints across 7 domains, versioned under /api/v1/

System architecture: client, REST API, business logic, persistence, and infrastructure layers

Outcome#

Currently in development. Backend is at roughly 80% complete with all 25 endpoints implemented and manually tested through Postman. Thirteen entities, seven services, six exception types, eight badge strategies, and a 25-tier rank system are live in the local environment. Frontend is at 10% — login and registration screens — with the dashboard, exam screen, and result screen coming up in Sprint 5–6.

The question pool sits at 34 manually crafted questions at the Bronze 1 tier. The target is 5,000: four grades, 25 tiers, 50 questions per tier. Producing that volume is a content problem more than an engineering one, and it's the area where curriculum review matters most.

Total development time so far: around 50 hours over five intensive days. Sprint 9 ships the public deploy at mathbank.com.tr. Sprint 10 begins the React Native mobile build.

MathBank is a real platform aimed at real students, not a portfolio prop. The portfolio framing is a side effect: the same project happens to demonstrate how I think about schema design, domain modeling, and shipping under solo constraints.