Мне нужна была Jira. Я открыл страницу с ценами, прикинул стоимость на свою маленькую команду и закрыл вкладку. Бюджет был нулевой — не «пойду спрошу у финансистов», а буквально ноль. И я сделал единственное, что делает упрямый джун, когда не может купить нужный инструмент: открыл VS Code и решил собрать клон Jira на React и Firebase с нулевым бюджетом — за одни выходные, почти на чистом упрямстве.

Это была не Jira. И никогда бы ею не стала. Но она была моя, и команда пользовалась ею несколько месяцев.

Стек, который не стоил ничего

Firebase дал мне бэкенд без бэкенда. Real-time-база, аутентификация, хостинг — всё на бесплатном тарифе. React отвечал за интерфейс. Вот и вся архитектура: никаких серверов, которые надо поднимать, никакого счёта в конце месяца, деплой — бесплатно. Для джуна без бюджета Firebase — великий уравнитель. Ты получаешь real-time-данные и auth, не написав ни строчки бэкенда и не заплатив ни за одну VM, а силы тратишь на то, что действительно важно, — на продукт.

Drag-and-drop чуть меня не убил

Кажется, что перетащить карточку из «To Do» в «In Progress» — тривиально. Пока не сядешь это писать. Состояние должно обновиться сразу в трёх местах: колонка-источник, колонка-приёмник и само поле статуса задачи. Ошибись с порядком — карточки дублируются. Ошибись сильнее — исчезают в пустоту между двумя рендерами, будто их и не было.

Я убил на эту одну фичу целые выходные. Переписывал четыре раза. Первая версия воевала с рендер-циклом React. Вторая гонялась с подтверждением записи в Firebase и мигала на каждом дропе. Третья наконец объяснила мне, зачем нужны оптимистичные апдейты: двигаешь карточку в UI мгновенно, сверяешься с базой потом, а если запись упала — откатываешь. Четвёртая просто заработала. Без дублей, без призраков, без карточек, падающих в бездну.

Real-time-синхронизация и роли

Когда доска стала вести себя прилично, остальное пошло быстро. Задачи с приоритетами и дедлайнами. Три колонки — To Do, In Progress, Done. Real-time-слушатели Firebase позволяли двоим двигать карточки одновременно, не наступая друг другу на ноги: изменение с моего экрана появлялось у коллеги меньше чем за секунду. Добавил аутентификацию Firebase с ролями, чтобы не каждый мог снести всю доску одним неудачным кликом. Настоящий инструмент. Мой инструмент.

Разница в том, что зависишь от него сам

Есть особое чувство, когда собираешь инструмент, которым сам пользуешься. Каждый баг раздражает лично тебя. Каждая недостающая фича — то, что ты реально замечаешь, потому что упираешься в неё во вторник утром, пытаясь сделать нормальную работу. Эта злость делает тебя лучшим инженером, чем любой туториал. Ты не выкатываешь happy path и не уходишь — ты чинишь то, что тебя бесит, потому что тебе с этим жить завтра.

Почему это сильнее туториала на собеседовании

Лучший проект в портфолио — не туториал, который ты прошёл до конца. Это то, что было нужно настолько, что ты собрал это сам. На собеседовании ты говоришь о настоящих решениях: почему real-time-база, а не REST-поллинг, зачем оптимистичные апдейты, как обрабатываешь запись, упавшую на полпути. Это твои решения, а не туториальные. Такая история звучит совсем иначе, и любой толковый инженер слышит разницу секунд за тридцать.

Чему это меня на самом деле научило

Каждая фича научила меня тому, чему Jira не научила бы никогда. Управление состоянием в React перестало быть концепцией и стало войной, которую я вёл на каждом клике. Real-time-базы ведут себя так, как ни один REST-туториал тебя не готовит. Потоки аутентификации, доступ по ролям, UX перетаскивания — я выучил всё это, потому что продукт ломался, пока я не разберусь. Десять лет спустя я всё ещё опираюсь на инстинкты, собранные за те выходные.

Так что: не можешь оплатить инструмент? Собери его. Так и получаются инженеры. Нулевой бюджет, одни выходные, инструмент, которым я реально продолжил пользоваться, — упрямство один из самых недооценённых навыков в инженерии, и его не пишут в вакансиях.