Nabiji
ნაბიჯი — Georgian for a step.
Nabiji links students in Georgia’s regional cities with businesses in their own town. Students learn digital marketing. Businesses find local talent. A coordinator connects the two.
- Built
- API · student & business web app · admin panel
- Stack
- React · TypeScript · Java 17 · Spring Boot · SQL Server · AWS S3
every step is a gate
Businesssees ACTIVE students only
კონტენტი
1 / 3 დასრულებული
Studentsees its own training only
Coordinatorverifies · approves

waiting · derived
assigned · stored
approved

Student & business app
React · the page you scrolled
Admin panel
React · verify · approve · match
Spring Boot API
JWT · training · grading · matching
SQL Server
connection_request · project_students · …
S3
profile photos · uploaded straight from the browser
Cache
modules · 1 h progress: never
PUT profiles/{uuid}.jpg
presigned by the API · 15 min
JPEG · PNG · WebP · GIF
users
training_modules
module_contents
student_module_progress
student_content_progress
projects
the coordinator works here
Pending
Training
Pass
Active
Requested
Approved
Assigned
Nabiji
Built
step by step.
React · Spring Boot · SQL Server · S3
View live demo ↗An independently hosted demo with sample data.
NOT YET.
now.
you were in here
just the answers.
5 questions · illustrative
scorePercentage 60 · passed false · attemptCount 1
scorePercentage 80 · passed true · attemptCount 2
Completed trainings · 3
Students and businesses never meet directly.
role-based access · businesses only see ACTIVE students · students never see requests
A coordinator connects them.
admin panel · verifies every account · approves every request
You can't skip a step.
module locks computed server-side · finish the content → pass the quiz → the next module opens
The browser never gets the answer key.
quiz sent as { order, text } · no correct flag · graded on the server
80% or you try again.
score = correct × 100 ÷ total · pass ≥ 80 · attempts counted · a pass is kept
One status changes who can see you.
TRAINING_COMPLETED → ACTIVE, set by the coordinator · businesses can only list ACTIVE students
A request isn't an assignment.
a PENDING row · the project's waiting list is derived from it, never stored
One approval, two writes.
request → APPROVED · student → the project's roster (project_students)
I built the system behind it.
student & business app · admin panel · Spring Boot API · SQL Server data model · S3 upload flow
01 / 08
← Back to workNabiji
ნაბიჯი — Georgian for a step.
Nabiji links students in Georgia’s regional cities with businesses in their own town. Students learn digital marketing. Businesses find local talent. A coordinator connects the two.
- Built
- API · student & business web app · admin panel
- Stack
- React · TypeScript · Java 17 · Spring Boot · SQL Server · AWS S3
every step is a gate
02 / 08
Three sides.One person in the middle.
Student
Learns digital marketing module by module, passes every quiz, earns a profile businesses can open.
web app · /training · /profile
Coordinator
Verifies every account, creates the projects, approves every match. The admin panel is theirs.
admin panel · /students · /connections
Business
Asks for a trained student from its own city, for one specific project.
web app · /dashboard · /project
verify
approve
3 apps · 1 Spring Boot API · 1 users table — Student, Business and Admin in single-table inheritance
03 / 08
Getting inis a state.
Five statuses decide which product you’re allowed to see. Every route checks the role and the status before it renders, and every controller checks the role again on the server.
- Pending verificationon sign-up
- Training in progresscoordinator
- Training completedthe system — last quiz passed
- Activecoordinator
Rejected coordinator
ProtectedRoute(role, status) on the client · @PreAuthorize on every controller
04 / 08
You can’tskip a step.
Module two stays locked until the server says module one is done: every video and article marked complete, and the quiz passed.
- 01done
- 02open
- 03locked

quiz stays locked
until 3 / 3
one row per student + item,
so marking twice changes nothing
Locks computed on the server from one grouped count per student · curriculum cached for an hour, progress never
05 / 08
80%
The browser neversees the answers.
4 of 5 — just enough
- Keys
- The quiz sent to the browser carries questions and options — never which ones are correct.
- Grading
- A question counts only when the chosen set equals the correct set.
- Pass
- correct × 100 ÷ total, rounded down. Eighty or more passes.
- Retry
- Every attempt is counted. A pass is kept; a later fail can't undo it.
06 / 08
The last correctanswer changeswho you are.
submitQuiz()graded on the serverall modules complete?content and quiz, every moduleTRAINING_COMPLETEDset by the system, not a personACTIVEa coordinator’s callvisible to businessesactive students only, filtered on the server
Then the profile
browser→signed upload URL, 15 min→S3 · profiles/uuid
The photo shows at once from a local preview, goes straight to storage, and rolls back if the upload fails. The file never passes through the API.
07 / 08

A business asksfor someonelocal.
Inside a project, a business sees only active students from its own city. A request waits until the coordinator approves it — then the student joins the project.
“waiting” is never stored —
it’s read from open requests
approval writes twice: the request closes, the roster grows
08 / 08
Step bystep.
- API
- Spring Boot · JWT auth · training engine · quiz grading · matching · S3 uploads
- Student app
- sign-up · locked curriculum · video & article player · quizzes · profile
- Business app
- dashboard · projects · requesting a student
- Admin panel
- verification · projects · approvals · the three-step match wizard
The original service no longer runs. This is an independently hosted demo with sample data.
← Back to work