Привет, Хабр! Меня зовут Настя, я редактор блога Рунити на Хабре. Обычно я помогаю коллегам рассказывать истории про их проекты в компании, но сегодня решила поделиться своим опытом.

Я не разработчик и никогда им не была, но всё равно решила сделать приложение — просто потому, что нужного мне решения я так и не нашла. В процессе мне пришлось узнать, как выглядит GitHub, что такое динамические плейсхолдеры и почему иногда приходится увольнять своего CTO. И да, я знаю, что не каждому нужно приложение, как не каждому нужен свой подкаст, но всё-таки решилась на этот проект и не пожалела. Ниже расскажу, почему.

Навигация по тексту:

С чего всё началось

Я давно хотела регулярно начать трекать потребляемый контент: книги, фильмы, сериалы, музыку. Плюс мне всегда нравились всякие итоги: книги года, фильмы года, Spotify Wrapped и вот это всё. Но каждый раз возникал один и тот же вопрос: почему обязательно ждать конца года? Почему нельзя посмотреть:

  • что я читала в марте;

  • как часто я слушала Лану дель Рей в те две недели, когда мне нравился мальчик;

  • какие фильмы я смотрела в сентябре.

В идеале я хотела одно (это важно!) приложение, в котором я собираю весь контент и в любой момент по одному нажатию кнопки могу получить что-то в духе:

«Ого, я вижу, ты пересматривала „Бегущего по лезвию“ и много слушала такую-то группу. Кажется, период был непростой, да? Надеюсь, хотя бы музыка немного сделала эти дни легче».

Я довольно долг�� искала готовые решения. Есть трекеры книг. Есть трекеры фильмов. Есть сервисы со статистикой. Но ничего, где всё это собиралось бы в одном месте, давало осмысленный срез и при этом выглядело хоть сколько-нибудь симпатично.

В итоге стало понятно, что если хочется именно такого инструмента — его придётся делать самой.

Ограничения (их было много)

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

  • какую задачу должен решать продукт;

  • какой функционал нужен на старте;

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

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

И вот на седьмой день январских каникул я решила взять судьбу в свои руки и попробовать другой вариант — убедить ChatGPT в том, что теперь он мой CTO. Но не в смысле «пусть он сам мне всё напишет», а в смысле — пусть он объясняет, задает рамки и помогает принимать решения с учетом того, что у меня из ресурсов есть только макбук и доступ в Интернет.

Почему Telegram, а не iOS

Изначально я думала, что это будет приложение на айфон. В вечной войне айфон против андроида я на стороне айфона — так сложилось, дело просто в привычке. Но довольно быстро выяснилось, что между «хочу приложение на iOS» и «у меня есть приложение на iOS» лежит длинный и не самый дружелюбный путь. А еще, возможно, учительница по алгебре была права и не надо было так часто прогуливать пары в университете по Python для начинающих, но это уже другой разговор.

Для таких же гуманитариев коротко объясню, что если делать iOS-приложение с нуля, то это сразу:

  • отдельная мобильная разработка;

  • бэкенд;

  • публикация и модерация в App Store;

  • онбординг пользователей и обновления.

Я попробовала в этом разобраться и довольно быстро поняла, что для проверки идеи это слишком тяжелая конструкция. Не потому что «невозможно», а потому что сложно лично для меня. В какой-то момент пришлось радикально скорректировать ожидания и амбиции. Telegram Mini App оказался самым приземленным вариантом для старта:

  • не нужен App Store и вся связанная с ним история;

  • не нужно устанавливать отдельное приложение;

  • авторизация уже есть;

  • интерфейс — обычный веб.

Это не идеальный формат и не «конечное решение». Но для первого запуска и проверки идеи этого более чем достаточно.

Что получилось по технологиям

Я вообще не понимала, что именно нужно, чтобы сделать приложение, поэтому начала с самого простого — попросила ChatGPT просто поговорить со мной об этом.

Я создала отдельный проект, включила голосовой режим и наговорила ему всё, что успела придумать: что за идея, зачем она мне, что я хочу на старте и чего точно не хочу. Перед этим я отдельно запромптила его на роль CTO — чтобы он не «фантазировал», а помогал принимать технические решения. Дальше мы довольно быстро пришли к следующему стеку:

  • Telegram Mini App — точка входа.

  • Next.js — фронтенд и серверные API в одном проекте.

  • Supabase — база данных и доступы.

  • Проверка Telegram initData — чтобы понимать, что пользователь реальный.

Логика работы такая:

  1. Пользователь открывает мини-апп в Telegram.

  2. Telegram передаёт данные авторизации (initData).

  3. Фронт отправляет их на сервер в заголовке x-telegram-init-data.

  4. Сервер проверяет подпись через TELEGRAM_BOT_TOKEN.

  5. Если всё ок — пользователь создаётся или находится в базе, и дальше работает с приложением.

Репозиторий и структура

Я не стала дробить проект на кучу репозиториев, потому что ChatGPT так и не смог даже в роли СТО меня убедить, что это важно и правильно. Пускай пока всё живёт в одном — так проще не потеряться.

Условно структура выглядит так:

/apps

  /web

    /app

    /api

/lib

  telegram.ts

  supabaseAdmin.ts

/supabase

  migrations

Отдельно для себя я зафиксировала правило: Telegram ID — это внешний идентификатор, но внутри у пользователя должен быть свой ID. Чтобы продукт не был навсегда привязан к одной платформе.

Supabase и данные

Среди всех предложе��ных вариантов Supabase я выбрала по довольно простой причине: он закрывает сразу несколько задач и не требует отдельной инфраструктуры. Минимальная модель данных:

  • users — пользователи;

  • items — книги, фильмы, музыка;

  • events — действия пользователя;

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

Это не идеальная схема, но вроде достаточная для MVP. И это слово — «достаточная» — здесь ключевое. Напомню, что я вижу код только когда мне коллеги его настойчиво показывают, так что всё описанное в этом тексте — ничтожный шаг для человечества, но большой лично для меня.

ChatGPT как CTO, и другие аббревиатуры

Вторая важная вещь обо мне, которую нужно знать читателю этого текста (кроме того, что я ничего не знаю о разработке приложений), заключается в том, что мне очень важно сохранять некое подобие независимости и самостоятельности. Как сказали бы психологи или коучи, важно не терять агентность. Поэтому я почти никогда не просила чат с нуля  просто «написать код». Я всегда просила объяснять, что мы делаем, для чего и, самое главное, можно ли это не делать. 

Примеры запросов, которые мне помогали:

Ты — мой CTO. Я не разработчик, а просто креативный директор этого стартапа. Мы сейчас делаем Х, вот скрин. Я не понимаю, куда нажать. Объясни, расскажи, что и зачем мы делаем. Можно ли сделать по-другому? Покажи альтернативы, я выберу.

Разбей Telegram-авторизацию на маленькие шаги. Что проверить на каждом этапе.

Сервер отдает 401. Вот код. Вот как я тестирую. Назови самые вероятные причины.

Так я постепенно начала ориентироваться в проекте и понимать, что вообще происходит. А ещё — довольно быстро поняла, что ChatGPT как CTO меня не до конца устраивает и в какой-то момент я всерьез захотела его уволить.

Проблема была не в том, что он плохо объяснял. Наоборот — он слишком хорошо вошел в роль СТО. В какой-то момент начал настойчиво предлагать вещи, которые с его точки зрения делали проект «правильным», но с моей — просто усложняли жизнь.

Например, он регулярно пытался отправить меня в терминал. Что-нибудь установить, что-нибудь запустить, что-нибудь «аккуратно разложить». Каждый раз это выглядело примерно так: я честно открываю терминал, делаю всё по инструкции — и ничего не работает. При этом довольно быстро становилось понятно, что:

  • на работоспособность приложения это не влияет;

  • на пользователей — тоже;

  • влияет это только на красоту и логичность архитектуры.

А красота и логичность архитектуры в этот момент волновали меня примерно на ноль процентов. Мне нужно было, чтобы приложение открывалось, сохраняло мои данные, не глючило. Всё остальное — здорово, но потом.

Это ощущалось как абсурдный сон: я плачу $20 в месяц за то, чтобы ИИ притворялся партнером моего стартапа и портил мне жизнь. Я включала голосовой чат и говорила ему: «Нет, давай вернемся на шаг назад и сделаем лучше покрасивее фронт», а он мне отвечал что-то в духе: «Да, ты права, но…».

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

Работа над фронтом приложения, или самая приятная часть

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

Мы с моим СТО остановились на Next.js — не потому что это «самый правильный выбор», а потому что он позволял держать всё в одном месте: и интерфейс, и серверные ручки. Для моего уровня погружения это было критично — чем меньше сущностей, тем меньше шансов запутаться.

Фронт я воспринимала не как «код», а как экраны, состояния и пользовательские сценарии, потому что мне так проще. Условно, что человек видит, когда заходит впервые? Что происходит, если данных пока нет? Что он делает дальше — и что приложение должно сделать в ответ?

В какой-то момент ChatGPT начал предлагать усложнять фронт: выносить логику, аккуратнее типизировать, заранее готовиться к масштабированию. И тут мы снова уперлись в тот же конфликт, что и раньше: ему хотелось делать «правильно», а мне — чтобы это просто работало. Поэтому фронт на старте получился максимально простым. Зато:

  • экраны собирались быстро;

  • было понятно, что где лежит;

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

Для MVP это оказалось важнее любой идеальной архитектуры. Если честно, именно фронт дал ощущение, что продукт вообще существует.

При этом даже в самой спокойной для меня части всё равно пришлось узнать вещи, которые я знать не планировала. Например, что такое динамические плейсхолдеры. Это выясняется ровно в тот момент, когда ты хочешь написать в интерфейсе что-то человеческое — вроде «В марте ты много слушала Лану Дель Рей» — и внезапно понимаешь, что «Лана Дель Рей» не может быть просто текстом. Она должна подставляться из данных. Как и месяц, и фильм, и настроение, и вообще всё, ради чего это приложение затевалось.

ChatGPT честно пытался объяснить мне, как делать это самостоятельно: шаблоны, переменные, условия, аккуратная логика. Я несколько раз пробовала разобраться и каждый раз упиралась в ощущение, что сейчас мне важнее, чтобы это просто работало, чем понимать, почему одна фигурная скобка лишняя, а другая обязательная. В итоге я пошла более прямым путём: попросила его на основе истории наших чатов и списков контента, которые я туда скидывала, посмотреть, какие фильмы, книги и музыка мне нравились, и предложить инсайты в моем стиле. И он это сделал. Местами получилось пугающе похоже на правду, местами — просто смешно. Я смотрела и думала: «Да…вот такой я человек, оказывается. Но ничего страшного». Выглядело это всё примерно так, как если бы меня описывал очень внимательный, но слегка самоуверенный знакомый.

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

Ниже — самый простой и приземленный вариант, до которого мы в итоге дошли:

// lib/template.ts

type Primitive = string | number | boolean | null | undefined;

export function renderTemplate(

 template: string,

 data: Record<string, Primitive>

): string {

 return template.replace(/\{\{(\w+)\}\}/g, (_, key: string) => {

   const value = data[key];

   if (value === null  value === undefined  value === "") return "—";

   return String(value);

 });

}

Пример шаблона для инсайта:

const INSIGHT_TEMPLATE =

 "В {{month}} ты чаще всего включала {{topArtist}} и пересматривала {{topMovie}}. Похоже, настроение было: {{mood}}.";

Использование на сервере:

import { renderTemplate } from "@/lib/template";

const text = renderTemplate(INSIGHT_TEMPLATE, {

 month: "марте",

 topArtist: "Лану Дель Рей",

 topMovie: "«Бегущего по лезвию»",

 mood: "не самым простым",

});
Вот так выглядят динамические плейсхолдеры на вкладке добавления контента для книг и музыки
Вот так выглядят динамические плейсхолдеры на вкладке добавления контента для книг и музыки

Тут должен был быть вывод, но у меня его нет

Важно сказать, что приложение я пока не выкатила. Как вы видите, я и так показываю не так много — просто потому, что это всё ещё рабочий процесс, а не готовый продукт. В свободное время я продолжаю что-то допиливать, проверять идеи, переписывать куски, которые вчера казались нормальными, а сегодня уже нет. Скорее всего, у этого текста будет вторая часть — или апдейт, когда станет понятно, что из этого всего в итоге выросло.

При этом работа над этим мини-проектом неожиданно дала мне гораздо больше, чем просто прототип. В какой-то момент я поймала себя на том, что спокойно использую слова вроде «динамический плейсхолдер» — и они больше не звучат как что-то чужое. И что я больше не чувствую себя гуманитарием-самозванцем, работая в ИТ-компании с умными людьми. Я по-прежнему не разработчик, но теперь я, кажется, немного лучше понимаю технарей.

Если вы это читаете и вам правда откликнулась вся эта история — и у вас есть идеи, что еще можно сделать с таким приложением, или вы готовы предложить помощь, или просто хотите что-то обсудить, — пожалуйста, напишите мне в комментариях. Серьезно. ChatGPT в роли CTO я уволила окончательно, так что живые люди сейчас в приоритете.