惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
MongoDB | Blog
MongoDB | Blog
Apple Machine Learning Research
Apple Machine Learning Research
The GitHub Blog
The GitHub Blog
博客园 - 聂微东
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
大猫的无限游戏
大猫的无限游戏
WordPress大学
WordPress大学
云风的 BLOG
云风的 BLOG
H
Help Net Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
A
About on SuperTechFans
Hugging Face - Blog
Hugging Face - Blog
罗磊的独立博客
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
Martin Fowler
Martin Fowler
博客园 - 司徒正美
Stack Overflow Blog
Stack Overflow Blog
B
Blog
博客园 - Franky
小众软件
小众软件
Recorded Future
Recorded Future
B
Blog RSS Feed
爱范儿
爱范儿
宝玉的分享
宝玉的分享
L
LangChain Blog
博客园 - 【当耐特】
The Register - Security
The Register - Security
P
Proofpoint News Feed
V
Visual Studio Blog
Blog — PlanetScale
Blog — PlanetScale
雷峰网
雷峰网
Last Week in AI
Last Week in AI
Microsoft Azure Blog
Microsoft Azure Blog
GbyAI
GbyAI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
M
MIT News - Artificial intelligence
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
MyScale Blog
MyScale Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
aimingoo的专栏
aimingoo的专栏
D
Docker
酷 壳 – CoolShell
酷 壳 – CoolShell
阮一峰的网络日志
阮一峰的网络日志
有赞技术团队
有赞技术团队
G
Google Developers Blog
S
SegmentFault 最新的问题
Microsoft Security Blog
Microsoft Security Blog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
GiftsHub — из чат-бота в полноценный backend-продукт
Кирилл Семенко · 2026-05-25 · via Все публикации подряд на Хабре

Простой

11 мин

8.1K

Привет! Меня зовут Кирилл Семенко, я AQA в SDET-команде Битрикс24. Сегодня расскажу о проекте GiftsHub — веб-платформе для координации мероприятий и дней рождений, которой пользуются сотрудники компании.

С 2019 года у нас в компании проводят внутренние Битрикс-хакатоны. Эта традиция даёт возможность поработать в новых командах, узнать что-то новое и сделать уникальный и интересный проект. Для лидеров команд это ещё и шанс развить свои способности менеджера и руководителя для достижения цели командой.

На хакатоне 2024 года начался проект, о котором я рассказываю сегодня — Telegram-бот для организации подготовки к праздникам. Потом появились Telegram WebApp / MiniApp, а следом полноценная платформа: отдельный сайт, публичные ссылки, email-вход, realtime и нормальная инфраструктура вокруг backend и frontend.

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

В статье расскажу про путь от быстрого bot-first MVP к самостоятельной продуктовой системе: с доменной моделью, несколькими интерфейсами, realtime и инфраструктурой вокруг backend и frontend.

Посмотреть и попробовать можно здесь

Содержание:

  • Откуда появилась задача

  • Почему стартовали через Telegram

  • Когда одного Telegram стало недостаточно

  • Telegram WebApp / MiniApp как промежуточный этап

  • Что на самом деле делает продукт

  • Почему backend стал центром

  • Когда проект вышел за пределы Telegram

  • Инфраструктура как следствие боли

  • Текущая форма продукта

  • Что я бы сделал раньше

Откуда появилась задача

Исходная боль была жизненной и практической: организовать подарок человеку так, чтобы остальные участники успели все обсудить, собрать деньги, выбрать вариант и не раскрыть сюрприз.

До автоматизации процесс держался на переписках и памяти организатора. Где-то обсуждали идею подарка, где-то уточняли участников, где-то вспоминали, какая сумма уже собрана. Пожелания именинника могли лежать отдельно, договоренности терялись, ответственность расползалась между людьми.

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

Если такие события происходят раза в 1-2 месяца, все можно вести руками. Когда сценарий повторяется регулярно, ручная организация начинает съедать слишком много времени и внимания. В какой-то момент стало ясно, что люди готовы участвовать, но процесс слишком завязан на одном человеке и множестве мелких сообщений.

Для хакатона это была удобная задача: боль понятная, цикл проверки короткий, сценарий уже существовал в жизни. Первая версия проекта была быстрой проверкой идеи: получится ли убрать часть ручной операционки из подготовки подарков.

Почему стартовали через Telegram

Telegram выбрали как самый быстрый канал для MVP. Пользователи уже там, сценарий организации подарка похож на переписку — кого поздравляем, когда день рождения, кто участвует. Ещё бота можно добавить в группу и сразу проверить базовый путь без отдельного frontend.

Поэтому на хакатоне с Telegram было удобно: можно быстро собрать реально работающий сценарий. Команды, кнопки, callback-события и сообщения позволяли провести пользователя по шагам: добавить бота, создать группу, присоединиться, указать день рождения, начать собирать данные.

Backend на этом этапе обслуживал bot-flow. В центре были обработчики, состояния диалога и тексты сообщений. Это нормальная цена быстрого старта: сначала появляется рабочий путь, потом становится понятно, какие сущности и правила за ним стоят.

Первая версия закрывала базовые вещи: профили пользователей, группы, дни рождения, вишлисты и участников поздравления. Но уже тогда стало видно ограничение: Telegram удобен как вход и канал общения, но в его возможности не помещаются все нужные функции.

Когда одного Telegram стало недостаточно

Поворот случился из-за конкретного тупика.

Главный сценарий сервиса — подготовка подарка для конкретного человека. Остальным участникам нужно место для обсуждения деталей: что дарить, кто участвует в сборе, какая сумма уже собрана. Подготовка при этом остается скрытой от самого именинника.

В Telegram это почти решаемо: можно попробовать тред, топик или отдельное обсуждение. Но если обсуждение живет внутри общего пространства, из него нельзя аккуратно убрать одного человека: то есть человек видит обсуждение собственного подарка, и сценарий ломается.

Второе ограничение рядом: боту недоступно создание управляемого приватного чата нужного состава. То есть бот должен создать отдельный закрытый чат, добавить туда только нужных участников и исключить именинника. В Telegram это невозможно, и для безопасности мессенджера это логично, но для продукта — тупик.

После этого стало ясно, что Telegram не может быть центром модели. Он оставался полезным каналом: привести пользователя, отправить уведомление, дать быструю кнопку. Но правила сценария уже должны были жить внутри продукта: кто участник события, кто именинник, кто может присоединиться и что нужно скрыть.

При создании события дня рождения именинник находится среди пользователей группы, но в участники события не попадает и не видит новый чат с обсуждением подарка на свой день рождения или другой праздник.

const participants = users.filter((user) => {
  return user !== birthdayPerson;
});

const event = new EventEntity();
event.birthdayPerson = birthdayPerson;
event.participants = participants;

Этот кусок хорошо показывает переход: сначала задача звучала как "создать обсуждение без именинника". Потом она стала backend-правилом. Именинник существует в событии как birthdayPerson и остается вне обсуждения подготовки.

Telegram WebApp / MiniApp как промежуточный этап

Между ботом и полноценной платформой был важный этап — Telegram WebApp / MiniApp.

WebApp позволил оставить Telegram входной точкой, но вынести сложный интерфейс туда, где уже можно нормально управлять состоянием, навигацией, событиями, списками и чатами.

Первая версия Telegram MiniApp

Первая версия Telegram MiniApp

3 февраля 2025 рядом с ботом вышло в релиз наше приложение Telegram WebApp, которое открывался прямо из Telegram. Внутри уже были NestJS, Angular, Postgres, Socket.IO и JWT. Часть функций оставалась в боте, часть переезжала на frontend.

WebApp закрыл то, что плохо помещалось в формат команд и сообщений: просмотр хотелок, личные списки, обсуждение подарка во внутреннем чате. Там, где бот превращался бы в длинную цепочку кнопок, WebApp давал нормальный экран.

Авторизация тоже стала переходной. Пользователь приходит из Telegram, backend проверяет initData, дальше выдает access и refresh JWT в cookie. Вход еще был завязан на Telegram-контекст, но приложение уже работало как web-клиент с собственной сессией.

if (this.authService.validateInitData(body.initData, body.hash)) {
  const user = await this.createUserIfNotExists(body.initData, body.userId);
  const accessToken = this.authService.generateAccessToken(user.id, user.tokenVersion, user.role);
  const refreshToken = this.authService.generateRefreshToken(user.id, user.tokenVersion, user.role);
  AuthService.setTokensCookie(res, { accessToken, refreshToken });
}

На этом этапе проект получил два слоя взаимодействия: Telegram приводил пользователя и отправлял уведомления, WebApp забирал на себя продуктовый интерфейс.

Что на самом деле делает продукт

Список сущностей звучит скучно: пользователи, группы, события, вишлисты, сообщения. Польза проекта раскрывается в сценариях между ними.

Первый сценарий — вишлист. Это список желаний, у которых есть название, ссылка, описание, цена и картинка. В подарочной логике есть важная деталь: участвующие в поздравлении могут забронировать пункт из вишлиста, который решили купить. Тогда несколько человек не купят случайно одно и то же. Сам владелец wishlist не видит, что кто-то забронировал в его вишлисте один из подарков.

Эту логику держит API. Когда wishlist смотрит владелец, backend скрывает данные бронирования.

if (isOwner) {
  dto.isLocked = false;
  dto.lockedBy = null;
} else if (dto.lockedBy && dto.lockedBy.id !== req.userId) {
  dto.lockedBy = null;
}

Одна и та же запись выглядит по-разному для разных пользователей:

  • Для владельца это просто пункт его вишлиста.

  • Для участника подготовки — подарок, который можно забронировать или увидеть как занятый.

  • Для пользователя, который забронировал желание — его ответственность.

Второй сценарий — группы и события. Это пространства подготовки подарка: участники, обсуждение, именинник, invite-ссылка, ответственный за сбор суммы на подарок и правила доступа. И ещё публичность: если пользователь не зарегистрирован на платформе и ему скинули ссылку на вишлист пользователя, ссылка откроется без авторизации.

Третий сценарий — внутренний чат события. Telegram не дал управляемое пространство для приватного обсуждения подарка, поэтому обсуждение переехало внутрь продукта.

В WebSocket-слое тоже есть проверка доступа на основе встроенной механики room. Пользователь не может подключиться к комнате события, если он не участник.

const hasAccess = user?.events?.some((event) => {
  return event.id.toString() === payload.room.toString();
});

if (!hasAccess) {
  return;
}

client.join(payload.room);

Чтобы участники не возвращались к обсуждению в обычных чатах, внутренний чат должен закрывать привычные сценарии: показывать не прочитанные сообщения, поддерживать реакции, ответы на конкретные сообщения. Тогда обсуждение подарка остается удобным внутри события, и договоренности не расползаются обратно по личным сообщениям и отдельным чатам.

Четвертый сценарий — сбор суммы на подарок. В раннем посте это была одна из главных болей: нужно понимать, кто участвует в сборе и какая сумма уже собрана. В текущей системе у события есть ответственный за сбор, собранная сумма, платежные данные и отдельная логика платежей.

В итоге сервис занимается не хранением данных о подарках, а координирует подготовку: кто участвует в сборе, что обсуждают, какая сумма уже собрана и кто отвечает за покупку подарка.

Почему backend стал центром

Когда был только бот, часть логики можно было держать в обработчиках. Пользователь нажал кнопку, бот ответил, состояние изменилось. То есть backend был, но только в роли сервера для Telegram-бота: принимал события из Telegram и отвечает на них.

Когда появились Telegram WebApp, отдельный сайт, публичные ссылки, email-вход, realtime и админские сценарии, такая схема перестала работать. Один и тот же пользователь может прийти из MiniApp, зайти через браузер, открыть публичный wishlist или попасть в событие через invite. Во всех случаях система должна точно понимать, кто он и что ему можно делать.

Так backend перестал быть службой при боте. Он стал местом, где живут правила: доступ к событиям, состав участников, скрытие бронирований, авторизация. A Telegram — один из клиентов рядом с web, публичными страницами и realtime.

Frontend здесь тоже важен: WebApp и отдельный сайт сделали продукт понятным для пользователя. Backend держит правила, но ценность видна через интерфейсы: список желаний, карточки событий, чат, публичные страницы, регистрацию, invite-ссылки и нормальную навигацию.

Когда проект вышел за пределы Telegram

Следующий большой шаг — отдельный сайт и публичные сценарии.

До этого Telegram все еще оставался обязательным контекстом. Даже с WebApp-интерфейсом регистрация была возможна только через бот. Это удобно для старта, но ограничивает продукт. Поэтому понадобилась вторая точка входа.

Публичные wishlist-страницы поменяли модель и стали первым сценарием, где Telegram больше не нужен: пользователь может открыть ссылку вида /u/:username и посмотреть желания человека, если тот дал на это согласие.

В backend появился публичный контроллер, который отдает wishlist по username, но не раскрывает лишнего. В публичной выдаче остаются только данные, которые можно показывать внешнему пользователю.

return {
  name: dto.name,
  description: dto.description,
  link: dto.link,
  price: dto.price,
  image: dto.image,
  isGifted: dto.isGifted,
};

Во frontend под это есть отдельный route без авторизации.

{
  path: 'u/:username',
  children: [ ... ]
}

Похожая история с invite flow. Событие можно открыть по токену, посмотреть базовую информацию и присоединиться, если правила это позволяют. Канал входа меняется, правила сценария остаются общими.

Позже появилась email-регистрация. Она сняла обязательную привязку к Telegram, который перестал быть условием существования пользователя в системе.

Изначально Telegram-группы помогали управлять составом внутренних групп событий: через них добавляли и исключали пользователей. Сейчас Telegram можно подключить как канал уведомлений о новых событиях, назначенных ответственных и днях рождения в календаре Ещё авторизованным через Telegram пользователям приходят личные уведомления через бота.

На этом этапе проект стал платформой с несколькими точками входа: Telegram MiniApp, отдельный сайт, публичные ссылки, email-аккаунт. Все они обращаются к одной продуктовой модели.

Инфраструктура как следствие боли

Инфраструктура обычно появляется, когда менять проект становится страшно.

Пока проект был ботом, многое можно было проверить руками: поправить обработчик, нажать пару кнопок, посмотреть ответ Telegram. Для MVP терпимо.

Когда один backend обслуживает Telegram, MiniApp, отдельный web, публичные страницы, realtime, фоновые задачи и уведомления, цена ошибки возрастает. Одно изменение может сломать авторизацию, чат, деплой.

Отсюда вырос отдельный orchestration-слой. Он собирает вокруг продукта backend, frontend, nginx, Redis, docker-compose, CI/CD и Makefile-команды. Этот слой не виден пользователю, зато продукт удобнее развивать и выкатывать.

В docker-compose видно, что система живет как набор связанных сервисов.

services:
  nginx:
    depends_on:
      backend:
        condition: service_healthy

  redis:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]

  backend:
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://localhost:${APP_PORT}/api/health || exit 1"]

Nginx ждет здоровый backend, Redis поднимается отдельно, backend имеет healthcheck, frontend собирается своим слоем. На этом этапе продукт уже нужно собирать, выкатывать и проверять как систему.

CI/CD закрепил ту же логику. В pipeline появились стадии validate, prepare, build, deploy, verify. Makefile закрыл повторяемые команды: деплой всего продукта, отдельно frontend, отдельно backend, dev-ветка, проверки статуса и синхронизация submodules.

Redis здесь тоже появился из практической нагрузки: Telegram-сессии, throttling, rate limiting и кеширование tokenVersion для auth-запросов. Он снижает лишние обращения к базе и убирает часть состояния из памяти процесса.

Текущая форма продукта

К этому этапу система уже объединяла вишлисты, события, участников, обсуждения, бронирования, сбор суммы, уведомления и публичные ссылки. Telegram MiniApp и бот остались удобными точками входа, а общая логика переехала в backend и frontend.

Пользователь может:

  • Прийти через Telegram, открыть MiniApp и работать внутри привычного мессенджера.

  • Зайти на сайт. 

  • Зарегистрироваться по email. 

  • Поделиться публичной ссылкой на wishlist. 

  • Попасть в событие через invite. 

Для продукта это разные входы в одну и ту же модель.

В отчетном посте на апрель 2026 уже было 455 человек — без дополнительного привлечения и рекламы. Для pet/side/hackathon-проекта это хороший сигнал: сценарий не был выдуманным. Людям действительно нужен способ проще координировать подарки и не держать все в чатах.

Итоговая схема: Telegram остался каналом входа и уведомлений. MiniApp дал удобный интерфейс внутри Telegram. Отдельный сайт убрал обязательную зависимость от Telegram. Backend стал местом, где живут правила продукта. Realtime закрыл обсуждения событий. Инфраструктура сделала все это сопровождаемым.

Что я бы сделал раньше

Старт через Telegram был правильным решением для первой проверки идеи. Пользователи уже были в мессенджере, сценарий был разговорным, а бот позволял быстро собрать рабочий путь без большого frontend.

Но границу между каналом и продуктовой моделью я бы провел раньше.

Удачный старт легко спутать с удачной долгосрочной архитектурой. Telegram помог быстро появиться, но потом начал диктовать ограничения там, где продукту уже нужны были собственные правила: приватность обсуждений, роли участников, события, бронирования, invite-ссылки и разные точки входа.

Backend быстро выходит за рамки CRUD, если продукт не просто хранит данные, а координирует действия нескольких людей. Пользователь участвует в процессе: обсуждает, бронирует, присоединяется, участвует в сборе, получает уведомления, видит одну часть информации и не видит другую.

Инфраструктуру лучше не откладывать до момента, когда менять уже страшно. Миграции, health checks, CI/CD, Redis, воспроизводимое окружение и нормальная схема деплоя выглядят избыточно, пока проект маленький. Потом внезапно оказывается, что без них каждое изменение превращается в маленькое гадание.

Ссылка на текущую версию приложения: https://gifth.ru/ 

Если сжать весь путь проекта до одной мысли, она будет такой: быстрый внешний канал помогает стартовать, но продукт должен вовремя стать самостоятельной системой.

Проект перерос Telegram по простой причине: реальный сценарий организации подарков потребовал собственной модели приватности, ролей, событий, обсуждений и точек входа.