Skip to main content

NRC Zaporizhzhia — a course platform

Someone without a browser gets exactly the same access to the courses as on the site — and there is no second version of the truth

The challenge

The training centre had a site with the courses, and talked to people separately in a messenger. The timetable lived in one place, applications in another, reminders were sent by hand. The classic situation where two systems drift apart and nobody knows which is right.

The solution

Courses, applications, the waitlist, reminders and news all live in one database. The public site, the admin and the Telegram bot read the same rows. The bot does not mirror the site menu — it guides the conversation, finds the right course, and drops the application into the same table the web form writes to.

  • ✓ Enrol in a course entirely inside Telegram, no browser needed
  • ✓ Waitlist and released-seat offers run as background jobs on BullMQ
  • ✓ Bilingual content as data: every entity has its own translation table
  • ✓ A separate three.js front end with GSAP — an interactive scene, not a decorative canvas
  • ✓ Role-based access in the admin, on JWT

Architecture

  • pnpm monorepo: web, admin, api, bot, experience
  • NestJS + Prisma + PostgreSQL
  • Redis and BullMQ for reminders and offers
  • Sharp for image processing, Zod at the boundaries
  • Docker Compose for dev, dev-server and prod

Why it was built this way

When a bot and a site keep separate databases, drift is a matter of time, not probability. Here they physically cannot diverge: it is one row in one table, shown two ways.

Stack

TypeScript · NestJS · Prisma · PostgreSQL · Redis · BullMQ · Next.js · React · three.js · GSAP · grammY · Docker · i18next