Skip to content

Repository files navigation

bkdojo — Backend Interview Trainer

Адаптивный тренажёр для подготовки к собеседованиям на Java/Kotlin backend. Вдохновлён Duolingo, но не инфантильный: это ежедневный тренажёр для инженеров.

Живая версия: https://olluorg.github.io/bkdojo/ (деплой на GitHub Pages из main)

Главная ценность — не «выучить факт», а уметь внятно объяснить его вслух на интервью. Поэтому открытые вопросы оценивает AI по рубрике, а не по совпадению ключевых слов, и после ответа начинается короткий диалог с уточняющими вопросами — как у живого интервьюера.

Экран «Сегодня»: до собеседования 21 день, фокус дня и план


Что внутри

Доменов 5 — Java Core, Spring Boot, Databases, Message Brokers, System Design
Вопросов 647 (java-core 315, spring-boot 122, databases 78, system-design 75, brokers 57)
Из них открытых 95 — те, что оценивает AI по рубрике
Уроков 120
Терминов в словаре 132
Тестов 418 в 73 файлах (bun test)

Типы вопросов: single (один вариант), multiple (несколько), open (развёрнутый ответ, оценивает AI по рубрике), плюс вопросы с кодом.


Возможности

Ежедневный цикл

  • Сегодня — одна миссия дня: фокус-тема, объяснение почему именно она (слабое место / самый большой разрыв до цели / накопились повторения), план из 5 шагов со ссылками на экраны и ожидаемый прирост готовности.
  • Цель — грейд (Junior/Middle/Senior), опционально компания и дата собеседования с обратным отсчётом. Готовность считается относительно выбранного грейда: поднял цель — честно упала готовность.
  • Разрывы до цели формулируются работой, а не процентом: «До Middle по Spring Boot: 4 темы».
  • Стрик, история, аналитика прогресса, предсказания.
  • Перенос прогресса между устройствами: выгрузка в JSON и импорт, который сливает данные с текущими, а не затирает их (плюс опциональная синхронизация).

Обучение

  • Курсы и уроки с интерактивными виджетами (пошаговая симуляция HashMap с рехешем и treeify, поколения GC с продвижением в old, рост ArrayList и демо Integer-кеша), подсветкой терминов из словаря и практикой после урока.
  • Защита темы (lesson defense) — чтобы закрыть урок, нужно пройти все его вопросы за один заход, без подсказок и пропусков. Галочка должна стоить дорого.
  • Словарь с дриллом терминов, закладки, «Мои ответы» — история своих формулировок открытых ответов.

Практика и оценка

  • Диагностика уровня (placement) — работает без AI, на вариантах ответа.
  • Адаптивный подбор: Elo-подобное обновление ability (1..5), подбор вопросов с «желаемой сложностью» +0.5 к текущему уровню. Сильного не гоняют по основам.
  • Интервал повторений — Leitner, боксы 1/3/7/16/30 дней; неверный ответ сбрасывает в первый бокс.
  • Слабые места — детекция концептов, которые стабильно не раскрываются в открытых ответах.
  • Мок-интервью по домену: спред по сложностям с рампой easy → hard.
  • Интервьюер-спарринг: после открытого ответа — до 3 уточняющих вопросов, нацеленных на самый слабый пробел; вердикт выносится по всему диалогу, и давление не может понизить уже полученную оценку.
  • Голосовой ввод ответов с таймером и полосой темпа (30–90 секунд — интервьюерский формат ответа).

Как это выглядит

Скриншоты сняты с живой версии после диагностики уровня и одной сессии практики.

Каждый разбор написан как ответ на собеседовании: короткая версия, развёрнутая, частые ошибки и вероятные доп. вопросы.

Вопрос практики с разбором «Как ответить на собеседовании»

Уроки — не просто текст: там, где статикой не объяснить, стоит интерактивный виджет. Ниже — степпер HashMap.put на шаге, где таблица выросла с 4 до 8 бакетов и всё перехешировалось.

Урок про HashMap с пошаговой симуляцией put и resize

Открытый ответ можно надиктовать вслух — как на реальном интервью — и поправить расшифровку перед отправкой.

Открытый вопрос: кнопка «Ответить голосом» и поле ответа

Прогресс — это не только проценты: есть прогноз «сколько дней до цели при текущем темпе», отдельно по каждому домену.

Экран прогресса: готовность 42%, прогноз по доменам

Ещё экраны: диагностика уровня, курсы, словарь, самопроверка, настройки

Диагностика — 10 вопросов с вариантами, без AI. Сложность подстраивается на ходу: ответил верно на лёгкий — следующий будет тяжелее. Здесь же задаётся цель.

Результат диагностики: уровень по каждому домену и выбор цели

Экран курсов: пять доменов с прогрессом

Словарь открывается по мере роста уровня, а термины подсвечиваются прямо в текстах уроков.

Словарь терминов

Когда AI недоступен (не Chrome и облачная оценка не подключена), открытый ответ уходит в самопроверку по эталону — оценка всё равно идёт по пунктам рубрики.

Самопроверка открытого ответа по рубрике

Способ оценки выбирается в настройках; там же видно, что доступно прямо сейчас. Тёмная тема — на скриншоте.

Настройки: способ оценки открытых ответов и доступность

Итоги мок-интервью


Как оценивается открытый ответ

Всё скрыто за абстракцией AnswerEvaluator; UI и слои ability/review знают только про EvaluationResult / AnswerOutcome.

Цепочка (режим auto, настраивается в Settings):

Chrome Built-in AI (на устройстве)  →  LLM-прокси (если задан)  →  самопроверка
  • Chrome AI — Prompt API, модель работает локально, ничего не уходит наружу.
  • Сервер — micro-platform LLM proxy (VITE_EVAL_ENDPOINT/functions/llm). Ключа провайдера на серверах bkdojo нет: пользователь сам выбирает провайдера (OpenRouter / OpenAI / routerai.ru), модель и вводит свой ключ в настройках — всё хранится только в localStorage и уходит в прокси заголовками X-Provider-Base-Url / X-Provider-Key.
  • Самопроверка — всегда доступный бэкстоп: пользователь сам отмечает раскрытые пункты по эталону.

Балл считается из весов рубрики, а не берётся у модели на веру — одинаково для локального и облачного пути (buildEvaluationPrompt + parseEvaluation). Совпадение по ключевым словам (RuleBasedFallbackEvaluator) — не продуктовый механизм, он остаётся только для тестов и аварийного режима.


Быстрый старт

Нужен Bun.

bun install
bun run dev       # http://localhost:5173

Всё остальное:

bun test          # 418 тестов
bun run typecheck # tsc --noEmit
bun run build     # typecheck + сборка в dist/
bun run start     # раздать dist/ одним Bun-процессом (server/prod.ts)

Приложение работает без всякой настройки: прогресс хранится локально (localStorage + IndexedDB), бэкенда и авторизации нет. .env нужен только чтобы включить серверную оценку или синхронизацию — см. .env.example.

Chrome-first: полная функциональность гарантируется только в Google Chrome Desktop (из-за Built-in AI и Web Speech API). В других браузерах открытые ответы уходят в самопроверку или в облачный оценщик.


Архитектура

src/
  app/          — оболочка, hash-роутер, тема
  components/   — переиспользуемый UI (карточки вопросов, ридер урока, виджеты)
  features/     — экраны: today, courses, lessons, practice, review, interview,
                  glossary, stats, history, bookmarks, answers, settings, onboarding
  domain/       — вся логика, чистый TypeScript без React
    ability/      Elo-обновление уровня
    selection/    адаптивный подбор, план дня, микс типов, placement
    review/       интервальное повторение, детекция слабых мест
    evaluation/   цепочка оценщиков, промпты, разбор ответа модели
    interview/    мок-интервью и цикл уточняющих вопросов
    goal/         цель, разрывы до цели
    lesson/       защита темы, корректирующие раунды, follow-up'ы
    progress/     mastery, стрик, аналитика, журнал событий
    content/      загрузка и валидация контента
  data/         — контент: questions/*.json, lessons/*.json, glossary.json
  storage/      — localStorage + IndexedDB
  sync/         — опциональная синхронизация через @ollu micro-platform
server/prod.ts  — единственный серверный код: статика dist/

Принципы: модули маленькие, домен отделён от UI, глобального мутабельного состояния нет, алгоритмы подбора и скоринга покрыты тестами.

Инвариант, который делает оценщик заменяемым: единственные файлы, которые трогают window / LanguageModel, — это domain/evaluation/aiCapability.ts и ChromePromptEvaluator.ts. Подробности и рецепт добавления своего оценщика — в EXTENDING.md.


Контент

Вопросы лежат в src/data/questions/<domain>.json и валидируются при загрузке (domain/content/questionValidation.ts):

  • single — ровно один correctOptionIds
  • multiple — один или больше
  • open — непустая rubric (AI оценивает каждый концепт отдельно)
  • у каждого вопроса обязателен answerGuide

Невалидные вопросы отбрасываются (с предупреждением в dev), поэтому битый контент не роняет приложение. bun test проверяет, что во встроенном контенте нет ошибок валидации.


Конфигурация

Vite вшивает в бандл только переменные с префиксом VITE_. Секретов на стороне bkdojo нет.

Переменная Назначение
VITE_EVAL_ENDPOINT URL LLM-прокси micro-platform. Пусто = серверная оценка выключена.
VITE_BKDOJO_SYNC 1 включает опциональную синхронизацию прогресса между устройствами. Без неё SDK синка вообще не попадает в бандл.
VITE_OLLU_SERVER Адрес сервера синхронизации.
VITE_OLLU_GOOGLE_CLIENT_ID Google OAuth client ID для входа в синк. Пусто = синк офлайн-only.
VITE_BASE База путей для сборки (для GitHub Pages — /bkdojo/).

Деплой

  • GitHub Pages — автоматически на каждый push в main (.github/workflows/deploy-pages.yml). Значения VITE_* берутся из repo Variables; они не секретные, поскольку всё равно попадают в клиентский бандл.
  • Docker / VPSdocker compose up -d --build, либо Bun + systemd + reverse-proxy. Полная инструкция: DEPLOY.md.

Ограничения MVP

Осознанные решения, а не недоделки:

  • нет собственного бэкенда и базы данных;
  • нет авторизации и платежей;
  • прогресс живёт в браузере пользователя;
  • ключей провайдеров на серверах bkdojo нет ни в каком виде;
  • Chrome-first.

Требования к вкладу в проект и границы («не добавлять бэкенд, auth, платежи, не тащить крупные зависимости») зафиксированы в CLAUDE.md.


Стек

React 19 + TypeScript 6 + Vite 8, Bun как пакетный менеджер и тест-раннер. Зависимостей в проде ровно три: react, react-dom и опциональный @ollu SDK для синхронизации.

About

BG DOJO - приложения для подготовки к backend interview

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages