UNLOCK: интерактивные открытки и адвент-календарь
собственный сервис студии: открытка по ссылке с паролем, управление из Telegram
Собственный сервис интерактивных открыток и адвент-календарей: получатель разгадывает закрытый терминал, владелец правит всё из Telegram-бота и веб-кабинета. Python, aiohttp, PostgreSQL.
Задача
Обычная открытка — картинка или шаблонный лендинг, который получатель проматывает за секунду. Отдельный сайт с бэкендом под каждое личное событие никто не станет разворачивать и оплачивать. Нужен был способ сделать из ссылки маленькую историю и при этом не запускать новый проект под каждого клиента.
Дополнительные требования:
- владелец сервиса заводит и правит открытки сам, с телефона, без разработчика;
- одна открытка рассылается многим гостям, и каждый видит своё имя;
- клиентов можно подключать и ограничивать по тарифу;
- открытка открывается на слабом телефоне и не падает вместе с сервером.
Решение
Интерактивная открытка — страница, в которой получатель что-то делает сам: разгадывает, выбирает, открывает. Мы сделали её как закрытый терминал и добавили админку в Telegram.
Что реализовано:
- Открытка по ссылке с экраном пароля, Recovery Protocol, тремя экранами и финалом; выбор получателя уходит владельцу в Telegram.
- Мастер создания открытки в боте из пяти вопросов: повод, кому, от кого, когда, ключ.
- Семь тем оформления: «Романтика», «Стрелковый», «Бункер», «День рождения», «Свадьба», «Неон», «Нуар».
- Веб-кабинет с предпросмотром: поля слева, открытка справа, отчёт «Как прошло» о том, докуда дошёл получатель.
- Одна открытка на многих гостей: имя в ссылке, массовый выпуск ссылок, выгрузка гостей и заявок в CSV.
- Адвент-календарь: окошки по дням, четыре оформления, пароль и дату проверяет сервер.
- Тарифы, роли владельца, оператора и клиента, коды приглашения, личные открытки и закрытые черновики.
- Отложенная публикация, QR-код ссылки, вебхук с заявками и витрина-лендинг сервиса с демо-открытками.
Как это устроено
Открытка из одного HTML-файла
Страница открытки — один статический HTML-файл: без сборки, без зависимостей, без бэкенда. Шрифт лежит рядом, салют рисуется своим кодом, звуковые эффекты синтезируются через Web Audio. Она получает тему и тексты от сервиса, но хранит свою копию значений, поэтому при недоступном сервисе открывается на них и на кэше прошлого визита. Эту копию не пишут руками: команда sync_site_defaults генерирует её из схемы сервиса, а смоук-тесты падают, если файл разошёлся со схемой.
Веб-кабинет как Mini App в Telegram
Mini App — веб-страница, которая открывается внутри Telegram. Вход в кабинет без паролей: Telegram передаёт подписанные данные о пользователе, а сервис проверяет подпись токеном бота на каждый запрос. Права те же, что в чате: клиент видит только свои открытки. С компьютера кабинет открывается по одноразовой ссылке из бота: она живёт 10 минут и тратится только нажатием кнопки, поэтому превью мессенджеров её не сжигают. В базе хранятся только хэши токенов, сессия действует 30 дней.
Одна открытка на многих: имя гостя в ссылке
День рождения, свадьба, корпоратив: адресатов много, открытка одна. Ссылка вида «/c/адрес?to=Имя» подставляет имя в терминал, приветствие, билет и превью. Без параметра работает имя из самой открытки, поэтому разосланные ранее ссылки не ломаются. В отчёте видно, кто открыл, докуда дошёл и кто прислал ответ, включая молчащих.
Адвент-календарь: пароль и дату проверяет сервер
У открытки ключ — часть игры, у календаря он охраняет подарок. Содержимое окошка и его файлы уходят в браузер только после двух проверок на сервере: пароль верный и нужный день настал. Окошко открывается в полночь по поясу получателя, пропущенные дни не сгорают. Регистр, буква «ё» и лишние пробелы в пароле не учитываются.
Превью ссылки в мессенджерах для каждой открытки
Робот мессенджера не выполняет скрипты и читает только то, что зашито в файл. Поэтому страницу по адресу «/c/адрес» отдаёт сервис и сам подставляет заголовок, описание и картинку именно этой открытки. Без этого у всех клиентов в чате была бы одна и та же карточка ссылки.
Тарифы и роли клиентов
У каждого тарифа три числа: сколько открыток, сколько мегабайт на открытку и сколько дней она живёт. Тариф приезжает вместе с кодом приглашения: владелец нажимает «Код клиенту», человек присылает код боту и сразу работает по своему тарифу. За три дня до конца срока владелец открытки получает предупреждение в чат.
Результат
- Новый клиент подключается кодом приглашения: без деплоя, без отдельного сайта и без правки кода.
- Открытка превращается из картинки в короткий сценарий, а ответ получателя приходит в Telegram.
- Открытка остаётся рабочей при недоступном сервисе.
- База данных не публикует порт наружу и видна только сервису.
- Тарифы задают пять вариантов: от пробной открытки на 14 дней до тарифа «Студия» без ограничения числа открыток.
- Смоук-тесты в CI запускаются на каждый push; в README отмечено 2305 проверок.
Технологии: что и зачем
- Python 3.13 и aiohttp — API, которое отдаёт настройки открытки и принимает выбор получателя.
- aiogram 3 — бот-админка на long polling: мастер создания, панели правки, коды приглашения.
- PostgreSQL 17 — открытки, заявки, тарифы и сессии; отметки времени хранятся как TIMESTAMPTZ.
- Один HTML-файл — сама открытка, без сборки и зависимостей.
- Docker Compose и nginx — два контейнера, сервис и база; порт наружу публикуется один.
- GitHub Actions — смоук-тесты с Postgres на каждый push.
Статус
Версия 3.16.1 от 29 сентября 2026 года, в продакшене, собственный продукт студии. Последние выпуски: витрина-лендинг сервиса и кабинет, удобный на телефоне и компьютере. Чего пока нет: приёма оплаты, тарифы назначаются вручную кодом приглашения или командой владельца. Живой прогон с настоящим токеном Telegram не выполнялся, тесты идут на заглушке. Список задач ведётся в ROADMAP репозитория.
Вопросы по проекту
Что такое интерактивная открытка по ссылке с паролем?
Как сделать одну открытку на всех гостей?
Как сделать подарок-квест с адвент-календарём онлайн?
Как владелец правит тексты и оформление, не трогая код?
Что будет, если сервис недоступен?
Как ограничивается доступ клиентов и сроки открыток?
Ещё по этому направлению
BruDgital: платформа онлайн-курсов с защищённым видео и живыми эфирами
онлайн-школа по маркетингу: свой сайт, вход через ботов, оплата и эфиры вместо Zoom
Интернет-магазин рубашек на Nuxt 4 с админкой для владельца
магазин рубашек в Чебоксарах: владелец сам ведёт товары, цены и заказы
DevUnit Lab: многоязычный сайт студии на Nuxt 4
собственный сайт студии, в продакшене с 29 сентября 2026 года
Нужно похожее?
Расскажите о задаче — покажем, как решали такое, и прикинем объём работ.