Pre-launch · EdTech · Подготовка к IELTSIELTS prep · Next.js · Supabase

bando.study —
платформа подготовки к IELTS.
bando.study —
a platform for IELTS prep.

Веб-платформа для подготовки к IELTS: тренажёры Reading и Listening в формате реального экзамена, мгновенная и воспроизводимая проверка ответов, режим экзамена с таймером. Платформа готова и развёрнута — публичный запуск заказчик готовит. A web platform for IELTS prep: Reading and Listening trainers in the real exam format, instant and reproducible answer checking, an exam mode with a timer. The platform is built and deployed — the client is preparing the public launch.

~/bando/app/api/attempts/[id]/submit.ts server
export async function POST(req: Request, ctx: Ctx) {
  const user = await requireUser(req)
  const attempt = await loadAttempt(ctx.params.id, user.id)

  if (attempt.submittedAt)              // повтор сдачи — тот же результат// resubmit — same result
    return json(attempt.result)

  return db.transaction(async (tx) => {
    await tx.lock(attempt.id)            // блокировка строки против гонок// row lock against races
    const key = await tx.answerKeys.of(attempt)     // ключи только на сервере// keys stay on the server
    const result = score(attempt.answers, key)     // проверка детерминирована, без AI// deterministic check, no AI
    await tx.finish(attempt, result)
    return json(result)

§ 01О чём проектWhat this is

Заказчик готовит студентов к IELTS и накопил библиотеку готовых тестов в формате HTML. Нужна была платформа, где студент проходит Reading и Listening в том же виде, что и на реальном компьютерном экзамене, сразу видит результат с разбором, а прогресс копится в личном кабинете. The client prepares students for IELTS and had accumulated a library of ready tests in HTML format. What was needed was a platform where a student takes Reading and Listening exactly as on the real computer-based exam, sees the result with a breakdown right away, and where progress accrues in a personal account.

Задача была не «один экран с вопросами», а платформа целиком: импорт готового контента, движок прохождения, честный рейтинг, оплаты и админка. Права на учебный контент остаются у заказчика — я отвечал за платформу, код и архитектуру. Платформа развёрнута и открывается на bando.study; публичный запуск заказчик готовит. The task wasn't "one screen with questions" but a whole platform: content import, a test-taking engine, a fair leaderboard, payments and an admin panel. Rights to the learning content stay with the client — I was responsible for the platform, the code and the architecture. The platform is deployed and opens at bando.study; the client is preparing the public launch.

Лендинг bando.study: заголовок «Stop guessing your band» и карточка Band Score 6.5 с разбором результата по типам вопросов IELTS — Matching Headings, True/False/Not Given, Multiple Choice.
Рис. 1 · Публичный лендинг bando.study. Карточка Band Score показывает разбор по типам вопросов — то, ради чего платформа и делалась. Fig. 1 · The public bando.study landing. The Band Score card shows the per-question-type breakdown — the whole point of the platform.

§ 02Как устроеноHow it's built

Платформа на Next.js: серверный рендеринг страниц, серверные API-роуты, данные в Supabase (Postgres). Логика прохождения теста живёт на сервере — браузер получает вопросы, но не ключи ответов до сдачи попытки. The platform runs on Next.js: server-rendered pages, server API routes, data in Supabase (Postgres). The test-taking logic lives on the server — the browser gets the questions, but not the answer keys, until the attempt is submitted.

  • Два тренажёра — Reading и Listening — в формате реального экзамена: таймер, навигатор по вопросам, автосохранение ответов.Two trainers — Reading and Listening — in the real exam format: timer, question navigator, answer autosave.
  • Импорт готовых тестов заказчика — платформа принимает подготовленные HTML-тесты и превращает их в интерактивные попытки.Import of the client's ready tests — the platform ingests prepared HTML tests and turns them into interactive attempts.
  • Детерминированная проверка — по правилам, без нейросетей. Поэтому результат мгновенный и воспроизводимый: одинаковые ответы всегда дают одинаковый балл.Deterministic checking — by rules, no neural nets. That's why the result is instant and reproducible: the same answers always give the same score.
  • Разбор результата по типам вопросов — видно, где именно студент теряет баллы.Result breakdown by question type — you can see exactly where the student loses points.
  • Каталог с фильтрами, личный кабинет, лидерборд, бейджи, стрики за регулярность и реферальная программа.Filtered catalog, personal account, leaderboard, badges, streaks for consistency, and a referral program.
  • Writing и Speaking с автоматической оценкой на базе Gemini (для Speaking — с разбором аудио) реализованы и ждут запуска за фиче-флагом.Writing and Speaking with automatic scoring powered by Gemini (with audio analysis for Speaking) are built and waiting behind a feature flag.
  • Локальные оплаты — Payme, Click, Uzum. Интеграции написаны; включатся, когда заказчик подключит мерчант-ключи.Local payments — Payme, Click, Uzum. The integrations are written; they switch on once the client connects the merchant keys.
Плеер тренажёра Reading в bando: слева пассаж «What would happen if all the world's trees disappeared?» с жёлтыми выделениями и плавающим маркером, справа таблица вопросов Matching Information 14–19, сверху чип PRACTICE и темп ≈1.3 min/Q, таймер и кнопка Submit, внизу навигатор вопросов 14–29.
Рис. 2 · Экзамен-плеер повторяет формат реального компьютерного IELTS: пассаж с выделениями, таблица вопросов, таймер и навигатор — как на настоящем экзамене. Fig. 2 · The exam player mirrors the real computer-based IELTS format: a passage with highlights, a question table, a timer and a navigator — just like on the actual exam.
Экран «Review your mistakes» в bando: интервальные повторения с фильтрами по типам вопросов (True/False/Not Given, Note Completion, Matching Information, Multiple Choice), очередью «Due now (50)» и карточками вопросов с кнопками «Practise this question» и «Mark learned».
Рис. 3 · Разбор ошибок на интервальных повторениях: каждая ошибка попадает в очередь и всплывает снова, пока студент не начнёт отвечать на неё стабильно верно. Fig. 3 · Mistake review on spaced repetition: every error goes into a queue and resurfaces until the student answers it consistently right.
structure · project layout
bando/
├── app/
│   ├── (exam)/       # движок прохождения: таймер, навигатор# test-taking engine: timer, navigator
│   ├── catalog/      # каталог тестов с фильтрами# test catalog with filters
│   └── api/          # серверные роуты: сдача, скоринг, оплаты# server routes: submit, scoring, payments
├── lib/
│   ├── scoring/      # детерминированная проверка по типам вопросов# deterministic checking by question type
│   ├── import/       # песочница для чужого HTML# sandbox for foreign HTML
│   └── payments/     # Payme · Click · Uzum
├── db/            # Drizzle: 37 таблиц, 58 миграций# Drizzle: 37 tables, 58 migrations
└── jobs/          # 8 фоновых крон-задач# 8 background cron jobs
Рис. 4 · Структура. Проверка ответов и ключи живут на сервере, в lib/scoring.Fig. 4 · Structure. Answer checking and keys live on the server, in lib/scoring.

§ 03Что было сложноWhat was hard

(1) Импорт чужого HTML. Тесты приходят готовыми HTML-файлами со своими встроенными скриптами. Запускать чужой код на своём сервере опасно, поэтому он исполняется в изолированной песочнице с лимитами по времени и памяти — из скриптов достаётся только логика подсчёта баллов, ничего лишнего выполниться не может. (1) Importing someone else's HTML. Tests arrive as ready HTML files with their own embedded scripts. Running foreign code on your own server is dangerous, so it executes in an isolated sandbox with time and memory limits — only the scoring logic is extracted from the scripts, nothing else can run.

(2) Защита ответов. Ключи и разборы физически не отдаются в браузер, пока студент не сдал попытку — иначе правильные ответы можно было бы подсмотреть в коде страницы. Проверка идёт на сервере, браузер получает только сам балл. (2) Protecting the answers. Keys and breakdowns are physically not sent to the browser until the student submits the attempt — otherwise the correct answers could be peeked at in the page source. Checking happens on the server; the browser receives only the score itself.

(3) Одновременные сдачи и честный рейтинг. Когда несколько студентов сдают попытки в один момент, легко получить гонку и испорченный рейтинг. Здесь стоят блокировки на уровне базы данных, а конкурентность проверяется адверсариальными тестами — специально сталкивающими сдачи друг с другом. (3) Concurrent submissions and a fair leaderboard. When several students submit at the same moment, it's easy to get a race and a corrupted ranking. Here there are database-level locks, and concurrency is verified with adversarial tests that deliberately collide submissions against each other.

(4) Два движка прохождения. Первый — точная реплика интерфейса реального компьютерного IELTS: тест открывается в изолированном окне без доступа к сети, чтобы всё было как на экзамене. Второй — собственный режим практики с подробным разбором. Один и тот же тест проходится в обоих. (4) Two test-taking engines. The first is an exact replica of the real computer-based IELTS interface: the test opens in an isolated window with no network access, so everything is like on the exam. The second is a custom practice mode with a detailed breakdown. The same test can be taken in both.

Там, где правила проверки известны заранее, нейросеть не нужна — детерминированный движок надёжнее, мгновеннее и его не надо перепроверять. Where the checking rules are known in advance, a neural net isn't needed — a deterministic engine is more reliable, more instant, and needs no re-checking.

§ 04ЦифрыNumbers

5.5wk BUILD TIME
~75k LINES TS
1814 TESTS
37 DB TABLES

За 5,5 недель от первого коммита до готовой платформы: 985 коммитов, ~75 000 строк TypeScript, 1814 автотестов и e2e-сценарии Playwright, 37 таблиц и 58 миграций, 46 страниц и 16 API-роутов, 8 фоновых крон-задач, 3 платёжные интеграции. In 5.5 weeks from the first commit to a finished platform: 985 commits, ~75,000 lines of TypeScript, 1,814 automated tests plus Playwright e2e scenarios, 37 tables and 58 migrations, 46 pages and 16 API routes, 8 background cron jobs, 3 payment integrations.

§ 05Что я вынесLessons learned

(а) Там, где правила известны заранее, детерминированная проверка надёжнее и дешевле нейросети: результат воспроизводим, мгновенен и его не надо перепроверять. AI я приберёг для Writing и Speaking, где без него действительно не обойтись. (a) Where the rules are known in advance, deterministic checking is more reliable and cheaper than a neural net: the result is reproducible, instant, and needs no re-checking. I saved AI for Writing and Speaking, where there's genuinely no way around it.

(б) Безопасность — это модель данных, а не заплатки поверх. Ключи ответов не уходят в браузер не потому, что «спрятаны», а потому что сервер их туда не отдаёт — так спроектировано. (b) Security is a data model, not patches on top. The answer keys don't reach the browser not because they're "hidden," but because the server doesn't send them there by design.

(в) «Платформа под ключ» — это импорт контента, экзамен, оплаты и админка, а не один экран с вопросами. Большая часть работы там, где пользователь её не видит. (c) A "turnkey platform" is content import, the exam, payments and an admin panel — not one screen with questions. Most of the work is where the user never sees it.

Нужно похожее решение для вашего бизнеса?Need a similar solution for your business?

Опишите задачу — отвечу в течение дня, оценку дам бесплатно.Describe your task — I'll reply within a day, the estimate is free.