Мне 15, я за три недели нон-стоп написал свой todoist на FastAPI. ЮKassa отказала из-за возраста — пришлось переделать на Telegram Stars
TL;DR: 2 мая открыл новую папку, набрал uv init, и три недели подряд писал собственный todo-сервис. Сейчас он живой, на проде (getdoday.ru), 850+ тестов, 39 миграций, ~20к строк Python. Хотел подключить ЮKassa — отказ из-за возраста. Пришлось делать оплату через Telegram Stars. Получилось даже лучше. Open source, MIT, код тут.
Привет, vc.
Мне 15. Учусь в 9 классе. В свободное время пишу свой стартап. Не «приложение», не «pet-проект», а именно стартап — я хочу с него жить. Уже принял несколько решений из этой логики (включая отказ от ЮKassa в пользу Telegram Stars — об этом будет ниже).
Сервис называется Doday. Todo-лист на русском, с командной работой, помодоро, расписанием уроков, Telegram-ботом и Mini App. Похож на Todoist, но бесплатный там, где у Todoist «только в Pro», и работает в любой стране без VPN.
История которую хочу рассказать — про то как я три недели в одно лицо собирал продукт, как пытался выйти на монетизацию, упёрся в стену «вам нет 18, отказ» три раза, и в итоге придумал обход. Легальный. Если ты тоже несовершеннолетний разработчик — это для тебя. Если ты родитель такого — тоже.
С чего всё началось
2 мая 2026 года я открыл новую папку, набрал uv init doday, и за следующие десять дней написал первую версию. Никаких готовых шаблонов, никаких boilerplate — с нуля. Это был марафон.
Зачем? Я давно сидел на Todoist. Free-тариф у них на 5 проектов, и я в него регулярно упирался. Pro стоит ~500 рублей в месяц. Я мог бы себе это позволить, в принципе, но мне было обидно. Помодоро встроить нельзя (нужно докупать отдельно). Канбан в free вообще нет. Утренний дайджест на email — только Pro. То есть платишь 6 тысяч в год за функции которые у нормального todo должны быть бесплатно.
А ещё Todoist жутко медленный из России. Иногда ждёшь 3-4 секунды чтобы галочка прокликала. Сервера у них в США, и каждый запрос проходит через все возможные таможни. На телефоне это становится невыносимо.
В какой-то момент я подумал «блин, я же могу написать сам». И начал.
Стек я выбирал не «модный», а «понятный мне». FastAPI потому что я уже немного писал на нём раньше. PostgreSQL потому что это единственный production-grade SQL который не врёт про даты. Jinja2 + HTMX вместо React — я не люблю фронтенд, а HTMX позволяет не любить его и при этом получить SPA-фил. Tailwind через CDN, без билд-степа. Alpine.js для мелкой интерактивности.
Через десять дней у меня была работающая версия с регистрацией, проектами, секциями, лейблами, фильтрами, помодоро-таймером, статистикой, импортом-экспортом. Порядка 300 коммитов, тысяч 40 строк кода (потом я половину выпилил в большой чистке — там много лишнего наросло за десять дней под утренний кофеин).
Деплой я сделал нестандартный. На VPS крутится cron-задача, которая раз в минуту проверяет master-ветку, и если HEAD сместился — git pull, миграции, рестарт uvicorn. То есть мой workflow на сегодня: пишу код, git push, через 60 секунд это на проде. Никаких CI/CD, никаких докеров, ничего. Просто git push.
Что было дальше — командная работа, Telegram-бот, Mini App
После первого MVP я начал добавлять то что в Todoist либо в Pro либо вообще нет.
Командная работа — это была мощная задача. Доделать так, чтобы юзер мог пригласить другого по email, тот заходил по ссылке, оба видели общий проект, оба могли назначать задачи друг другу, комментировать, видеть кто что закрыл. И при этом не уронить производительность и не порушить безопасность (юзер не должен видеть чужие задачи если его не пригласили). Получилось — в Doday вся авторизация централизована в трёх функциях get_project, get_task, get_section. Добавил team-sharing — изменил три функции, и весь сервис заработал с командами.
Telegram-бот — был очевидным шагом, потому что моя целевая аудитория (школьники) живёт в Telegram. Через бота можно добавлять задачи командой /add, получать утренний дайджест, читать уведомления о дедлайнах. Самое полезное — Mini App. Это не отдельное приложение, а просто веб-страница которая открывается прямо внутри Telegram, и Telegram-клиент делает её похожей на нативное приложение. Жесты, haptic feedback, без выхода из чата.
Mini App стоил мне примерно недели работы — там много мелочей. Auth через initData от Telegram, валидация HMAC-подписи, swipe-actions, drag-and-drop задач между секциями. Но когда дело пошло — оно реально классно. Открываешь чат с ботом, тапаешь «Doday» в menu, и у тебя полный todo прямо в Telegram. Friend'у даже устанавливать ничего не надо.
Школьный синк — это пока экспериментальная фича. Идея: твой школьный портал (Школьный портал МО / МЭШ) ведёт твой дневник, домашка туда падает. Я написал интеграцию: вставляешь токен своего портала в настройках Doday, и домашка раз в 15 минут синхронизируется в твои задачи. Дедлайны автоматически, без копипасты.
Это пока альфа потому что у каждого региона свои нюансы API, и я тестировал только на своём аккаунте. Но костяк работает.
Архитектурно — mypy --strict проходит на всё что в app/, ruff со всеми paranoid-rule'ами. Pre-commit hook проверяет это на каждый коммит. CI на GitHub Actions гоняет полный pytest на каждый push в master. Каждый деплой проходит через 26-эндпоинтный смок-тест на проде — если хоть один эндпоинт упал, я узнаю об этом сразу.
А что с монетизацией?
Через две с лишним недели работы я понял что Doday — это уже не «pet-проект на пару выходных», это реальный продукт. Юзеры приходили из моих личных каналов (друзья, родственники, школа), но я хотел масштабироваться. И платежи становились неизбежной темой.
Я сел подумать, и пришёл к такому плану:
- Free — всё что нужно школьнику и обычному пользователю. Безлимитно. Без рекламы. Навсегда.
- Pro (~199₽/мес) — премиум-темы, утренний email-дайджест, безлимит везде, эксп-функции.
- Family (~299₽/мес) — Pro на 5 человек + общий проект «Семья».
Цены — намеренно ниже Todoist (тот берёт 500₽/мес за Pro). Логика: я инди, у меня нет маркетинговых расходов, я могу позволить себе быть дешевле.
Чтобы это всё работало — нужен эквайринг. То есть способ принимать деньги юзеров на свой счёт. В России это значит ЮKassa или Т-Банк эквайринг или Тинькофф кассу. Все три работают по одной схеме: ты регистрируешь магазин, они проверяют твои документы, выдают ключи API, ты вставляешь их в код. Юзер платит — деньги падают тебе на счёт самозанятого или ИП.
Я уже был самозанятым (оформил через приложение «Мой налог» — это можно с 14 лет с согласия родителей). У меня был счёт в Т-Банке. Казалось — что может пойти не так?
ЮKassa и Т-Банк отвалились на возрасте. Оба
Захожу на ЮKassa, регистрируюсь, нажимаю «Войти через Госуслуги» — это удобно, паспортные данные подтягиваются автоматически, проверка идёт быстрее. Минут 20 на всё, думал я.
Экран: «Вход недоступен. Войти в систему не может пользователь с учётной записью ребёнка на Госуслугах».
Сижу. Перечитываю. У меня полная учётная запись на Госуслугах. Я через неё налоги плачу, госуслуги получаю, в МФЦ хожу с QR-кодом оттуда. Всё работает. Но ЮKassa проверяет по дате рождения, и если меньше 18 — категорически нет. Без вариантов.
Думаю — окей, может это глюк именно с Госуслугами.
Хорошо, попробую вручную. На ЮKassa есть кнопка «Заполнить анкету вручную» — ввести паспортные данные без Госуслуг. Захожу — там просят загрузить скан паспорта. Их OCR смотрит дату рождения и отказывает на той же стадии. Даже когда я попробовал загрузить скан со специально замазанной строкой даты (просто чтобы посмотреть что будет) — пришёл отказ через час, «не удалось проверить личность». Ну логично.
Ладно. Иду в Т-Банк. У меня там карта, я их клиент уже два года, может они проще. Регистрируюсь на интернет-эквайринг. Через 10 минут приходит SMS: «Для подключения интернет-эквайринга необходимо ИП или юридическое лицо. Самозанятые принимаются только с 18 лет».
Хорошо, открыть ИП? Тоже только с 18 лет, без вариантов. С согласия родителей можно с 14 лет, но банки на это смотрят косо, и в любом случае ЮKassa и Т-Банк не работают с такими ИП.
Открыть всё на родителя? Я не хочу. Это значит что деньги юридически чужие, в случае спора с юзером — спорить будет родитель, не я. Налоговая будет считать доход чужим. Это не моя ниша. Плюс если родитель завтра передумает участвовать — я остаюсь без эквайринга в один день.
Подождать до 18? Мне 15, до совершеннолетия ещё три года. Это слишком долго. Без монетизации я не могу инвестировать время в продукт всерьёз. Мне нужно понимать что он работает экономически. Иначе это просто хобби, а хобби у меня и так есть.
Я почти сдался. Поспал. Утром подумал ещё.
Telegram Stars — единственный путь
Я вспомнил что у Telegram есть встроенная валюта — Stars (звёзды, в API называются XTR). Юзеры покупают их в Telegram-приложении (через App Store / Google Play), и могут тратить на покупки в любом боте. Это API для разработчиков — createInvoiceLink, successful_payment, обычные вещи.
Главное: Stars не требуют ничего кроме Telegram-аккаунта. Регистрация бота через @BotFather доступна с 13 лет. Договор у меня — с Telegram, не с банком. ЮKassa, паспорта, ИП — всё это не нужно. Telegram сам разбирается с возрастом плательщиков, я только принимаю деньги.
Минусы — Telegram забирает ~30% комиссии. То есть 250 Stars (это примерно 300 рублей с учётом курса Stars-в-рубли в РФ) → мне на руки приходит около 210 рублей. Это чуть дороже моих оригинальных 199 рублей. Терпимо.
Я сел писать.
Архитектура которая получилась:
- Каталог продуктов — отдельный файл с дата-классами. Pro месяц = 250⭐, Pro год = 2500⭐ (скидка 17%), Pro навсегда = 12500⭐, Family месяц = 500⭐, Family год = 5000⭐. Меняешь цены — правишь один файл.
- Подписанные payload'ы — каждый invoice содержит HMAC-подписанную строку v1:{product}:{user_id}:{nonce}:{sig}. Без подписи можно было бы тампернуть URL, заменить product, и купить «навсегда» за цену «месяца». С подписью — нельзя.
- Идемпотентность — после оплаты Telegram отправляет webhook на мой бот. Этот webhook может прийти повторно (если бот упал между обработкой и подтверждением). Я делаю insert в таблицу star_payments с UNIQUE на telegram_payment_charge_id. Второй insert падает с IntegrityError → сервис понимает «это дубль, проигнорировать». Юзеру никогда не зачисляется два раза.
- Pro-срок — у юзера есть поле pro_until. После оплаты Pro 1 месяц этот срок продлевается от существующего pro_until + 30 дней (если он был в будущем) или от сегодня + 30 дней (если истёк). То есть продлевая раньше срока, ты не теряешь оставшиеся дни. Это казалось бы очевидно, но в Todoist это работает не так — они там просто перезаписывают дату.
- UI — в Mini App кнопка «Купить Pro» вызывает Telegram.WebApp.openInvoice(url, callback). Юзер видит окно оплаты прямо в Telegram, тапает, Stars списываются, бот присылает благодарность, тариф активируется через 2 секунды. На десктопе — открывает invoice-URL в новой вкладке, дальше всё то же.
Всё это я написал за ~6 часов работы. 24 теста покрывают подписи, идемпотентность, продление сроков. На случай если юзер захочет вернуть деньги — есть refund-эндпоинт для админа, Telegram даёт окно 21 день для возврата без вопросов.
Параллельно я закрыл security-баг который у меня болтался с аудита — раньше эндпоинт /api/billing/change-tier позволял любому залогиненному юзеру POST'нуть {"tier": "pro"} и стать Pro бесплатно. Теперь только downgrade до free разрешён, upgrade требует реального платежа.
Важная оговорка про монетизацию прямо сейчас
Я только что включил Stars, но сейчас сервис в бета-режиме и Pro-функции бесплатны для всех. Никто пока ничего не платит, и я не давлю на это. Когда уйду из беты — введу платный режим, и ранние юзеры (то есть кто зарегистрировался до этого момента) останутся бесплатно с тем что уже создали. В Mini App есть founder-оффер «Pro навсегда» за 12500⭐ — это для тех, кто хочет зафиксировать Pro насовсем ДО возврата к платному режиму. Покупать не обязательно. Если не купил — после возврата платного будешь на Free.
То есть я монетизацию ПОДГОТОВИЛ. Сейчас она опционально-добровольная. Когда продукт стабилизируется и начнёт расти — переключу.
Что в итоге
На сегодня у Doday:
- 511 коммитов в master
- ~20 000 строк Python
- 850+ тестов на pytest
- 39 миграций Alembic
- 33 отдельных модуля в app/ (auth, tasks, projects, comments, labels, pomodoro, reminders, stats, miniapp, telegram, billing, experiments, school, links, habits, mood, time_tracking, achievements, user_templates, calendar_feed, views, pages, digest, help, admin, backup, profile, sections — и templates)
- CI зелёный, smoke 26 эндпоинтов проходит на каждый деплой
- Веб-приложение, Mini App и Telegram-бот — три surface, один backend
- Open source — MIT, SwairIt/doday на GitHub
Если ты хочешь попробовать — это getdoday.ru. Регистрация по email, без карты, без подтверждения телефона. Сейчас всё бесплатно для всех в бета-режиме. Mini App открывается через @DodayTaskBot в Telegram.
Технологии и грабли
Я не буду тут писать туториал по FastAPI — этого добра в интернете полно. Но пара заметок которые могут сэкономить кому-то время:
HTMX + Alpine.js — это правда работает. Я начинал думать что без React будет сложно. Оказалось наоборот. Большинство интерактивности — это hx-get / hx-post который подгружает кусок HTML и заменяет область на странице. Сложная клиентская логика — Alpine.js, который инлайнится прямо в HTML. Bundle весит 30 КБ против 250 КБ у React. Time-to-interactive отличный.
Mini App auth — initData HMAC. Telegram передаёт в Mini App строку initData с подписью HMAC-SHA256 на основе твоего bot-token. Ты проверяешь подпись на сервере, и если ок — выдаёшь сессию. Документация Telegram на эту тему — отдельный челлендж, написана не для людей. Я потратил два дня на отладку.
Alpine x-data ловушка. Несколько раз ловил баг когда x-data="apply({{ var|tojson }})" рендерилось в x-data="apply("string")" — двойные кавычки в HTML-атрибуте ломают парсинг, Alpine не видит выражения, ничего не работает. Pytest этого не ловит (рендерит HTML и проверяет наличие подстрок, не парсит JS). Только Playwright или ручная проверка в браузере. Решение — |forceescape после |tojson чтобы " стало ".
JSONB column в SQLAlchemy не отслеживает мутации. Если ты делаешь user.flags["x"] = True, SQLAlchemy не поймёт что строка dirty. Нужно user.flags = {**user.flags, "x": True} — assignment целого объекта. Очевидно когда знаешь, ловится когда не знаешь.
А что с Claude Code
Я писал Doday в паре с Claude Code — это AI-ассистент от Anthropic для разработки. И я не собираюсь это скрывать.
Что я скажу:
- Архитектурные решения — мои. Тарифная сетка, модель шаринга, layout сайдбара, какие фичи делать опт-ин, как назвать пресеты — выбирал я. Claude был быстрым машинистом с хорошей памятью о codebase.
- Каждый коммит я ревьювил перед пушем. Строчки которые я не понимал — переписывал руками пока не мог объяснить вслух.
- Качество держится на инструментах, не на «vibe». mypy --strict + ruff + 850 тестов — рельсы которые ловят AI-slop. Type errors фейлят билд, каждый behavior-change приходит с тестом, jinja-linter ловит плохие паттерны Alpine.js.
- Я многому научился. SQLAlchemy 2.0 async, Pydantic v2, HTMX swap-стратегии — я их знаю не на уровне «скопировал из примера», а на уровне «дебажу без помощи».
Считается ли это «настоящей разработкой» — зависит от твоего определения. Я считаю что да. Я бы не написал столько за три недели в одиночку без AI. Но я и не написал бы это без вкуса к архитектуре, ревью и понимания того что я делаю.
Если ты человек который считает что AI делает за разработчиков работу, и проект перестаёт быть «твоим» — окей, я не буду спорить. Но я бы с интересом послушал что ты сделал за три недели один.
Что дальше
В roadmap'е (он публичный, getdoday.ru/roadmap):
- Сейчас: Telegram Stars готовы ✅. Публичные invite-ссылки для команд. Полировка mobile.
- Дальше: Parent dashboard для Family-тарифа. iCal feed v2. Публичный API + Personal Access Tokens.
- Может быть: Нативное iOS-приложение (через Capacitor, обёртка Mini App). Voice-input через Telegram. Обратное — английский quickadd-парсер.
Когда мне будет 18 — открою ЮKassa параллельно. Stars остаются (они работают глобально без VPN), карты добавлю для удобства РФ-юзеров. Архитектура к этому готова — модуль app/billing/ написан под расширение, добавить yookassa.py рядом со stars.py будет час работы.
Если ты дочитал — спасибо
И если кто-то из вас тоже подросток который пытается монетизировать свой проект — пиши, расскажу детали Stars-интеграции (или просто посмотри в app/billing/stars.py). Это не rocket science, но первые два часа документация Telegram кажется написанной криптовалютчиками.
Кому интересен сам Doday — getdoday.ru, @DodayTaskBot, код на GitHub. Если поставишь ⭐ на репозиторий — спасибо, это правда мотивирует. Если найдёшь баг — пиши issue. Если хочешь Pro бесплатно навсегда сейчас — просто зарегистрируйся, ты сразу попадаешь в эту группу.
Спасибо что почитал. Если есть вопросы — отвечу в комментах. Реально каждый.