Делаем свой Telegra.ph на маркдауне за три минуты и один промпт
Последние два года я почти не пишу код. Наверное, только 10% кода в моих личных и коммерческих проектах написано мной, все остальное генерируют нейронки. За это время у меня выработался определенный подход к созданию проектов и появились инструменты, которые я для этого использую. Этим я и хочу поделиться с вами под катом.
С 2022 года многое изменилось. Сначала оригинальный Github Copilot появился в открытой бете, затем пошли ранние модели OpenAI – неряшливые, теряющие контекст, добиться от них внятного результата на длинной дистанции было невозможно. Но в течение этих лет нейронка перестала быть просто продвинутым автокомплитом, теперь это полноценный инструмент для решения задач. Главное – правильно эти задачи ставить. И вот тут, как я заметил, у многих, даже опытных программистов, возникают сложности и появляются вопросы в целеобразности использования нейронок для написания кода в принципе. Это и подтолкнуло меня написать пост.
Особенно полезным он будет для начинающих, которым, как и мне когда-то, интереснее "делать штуки", чем непосредственно писать код. В этом посте я покажу, как с помощью своих инструментов создать self-hosted решение, похожее на Telegra.ph, но с редактором на Markdown.
Подход, который я описываю дальше, можно использовать с разными моделями: ChatGPT, Claude, DeepSeek, даже с бесплатным GitHub Copilot в современном виде (хотя с ним это наиболее неудобно). Недавно я описывал свой опыт работы с Copilot на dev.to — это скорее мучение, чем работа.
Я рекомендую использовать Cursor, сейчас его можно попробовать в Pro версии в течение двух недель. Пока он предоставляет самый приятный и бесшовный опыт программирования с нейронками, что я встречал. Именно работу с ним, я и буду описывать дальше.
Системные требования
Для работы над проектом вам понадобятся:
Python версии выше 3.10
Pip для установки зависимостей
Git для работы с репозиторием
Docker Desktop (бесплатный план)
Cursor, или доступ к любому AI-чату
Утилита snap2txt, которую можно установить через pip install snap2txt
Prototype (база проекта)
Работа над проектом
Я бы хотел, чтобы эта часть была максимально понятна начинающим, поэтому некоторые вещи буду расписывать подробно. Если для вас это слишком, просто прокрутите ниже или посмотрите гифки.
1. Создаем проект из репозитория Prototype
Сначала копирую git clone с адресом репозитория базового проекта Prototype и создаю в рабочей папке проект с новым названием tapnote.
Prototype – это quick-start набор для проектов на Django в Docker-контейнере. Я использую Docker, а не venv или virtualenv, потому что Docker дает полную изоляцию на уровне ОС и гарантирует одинаковое окружение на всех машинах. Это удобно для быстрого развертывания на платформах вроде Railway.app или DO. Внутри Prototype – это Dockerfile и docker-compose с основными настройками, хелпер для работы с API OpenAI и shell-скрипт для запуска всего этого одной командой.
Для запуска setup.sh перехожу в новый каталог через cd tapnote и запускаю ./setup.sh. Через несколько секунд все готово.
2. Проверяем работу контейнера
В Docker Desktop появится новый контейнер с названием проекта. Если он успешно запущен, можно открыть вкладку 'web' и убедиться, что в логе нет ошибок. Также по адресу localhost:9009 в браузере откроется стандартная стартовая страница Django.
3. Открываем проект в Cursor и делаем предварительную настройку
Под предварительной настройкой я имею в виду инициализацию Git и создание рабочего контекста проекта. Для этого выполняю git init и делаю первый коммит. В этом проекте будет всего два коммита – до и после промпта. Для создания контекста использую инструмент snap2txt с параметром --il.
snap2txt – это Python-утилита, которая сворачивает весь проект в единый текстовый файл. Я сделал ее около полутора лет назад и пользуюсь почти каждый день. Она нужна, чтобы создать файл с контекстом проекта и подать его на вход нейронке вместе с задачей. Так ей сразу будет доступен полный контекст проекта, структура каталогов и файлов. Параметры --il и --wl означают вызов с ignore list или white list — это отдельные файлы в корне утилиты, где прописано, какие файлы добавлять в контекст, а какие нет. --il работает схоже с .gitignore, --wl — наоборот.
Теперь, когда файл с контекстом создан, открываю панель Composer внутри редактора и двойным кликом по project_contents.txt добавляю контекст проекта в Composer.
4. Детально описываем задачу, принимаем файлы и запускаем необходимые команды
Здесь я немного схитрил и вставил заранее подготовленный промпт в чат Composer. Моей задачей было показать создание проекта за один промпт, поэтому я немного отшлифовал его в процессе подготовки статьи. Но более простые проекты делаются простым описанием без предварительной подготовки. Для проекта вроде этого понадобится 2-3 итерации, чтобы поправить моменты, о которых вы не подумали сразу. Однако при грамотном проектировании можно создать сложный проект за один присест.
Для работы в Cursor и во внешнем чате понадобятся разные конфигурации запросов. Cursor напрямую взаимодействует с файлами проекта, поэтому ему нужно меньше пояснений касательно структуры файлов и формата ответов. Внешний же чат, только генерирует инструкции по созданию файлов в нужных каталогах и их содержимое. Кроме того, у каждой модели есть свои особенности: например reasoning-модели, вроде o1, часто лучше справляются с объемными задачами, но любят "размазывать" код и комментарии по ответу, что снижает читаемость. Это поведение можно обрабатывать дополнительными инсрукциями, но здесь я не буду подробно останавливаться на этих нюансах.
Идеальный промпт для этого проекта получился не сразу, и большую роль сыграла структура описания. Я выделил 3 большие группы с детальным описанием необходимых изменений в базовом проекте:
Так выглядит задача целиком:
После отправки задачи в чат Composer нужно подождать несколько секунд, пока он создаст и наполнит нужные файлы. После этого их нужно сохранить, нажав Accept в окошке со списком файлов внизу чата, и выполнить необходимые команды.
На команды хочу обратить отдельное внимание. Почему-то именно здесь Composer периодически ошибается. Иногда он дает команды, готовые к выполнению в контейнере через терминал – в этом случае нужно просто нажать Run в окошке с командами, и они выполнятся. В других случаях в этом окошке есть комментарии, и при запуске через кнопку команды не выполняются из-за того, что комментарии попадают на вход в терминал. Тогда их нужно копировать по одной и выполнять вручную. Иногда команды бывают без docker-compose, написанные для выполнения в виртуальной среде. В таком случае нужно открыть контейнер в Docker Desktop, скопировать и выполнить эти команды в таб Exec по одной.
5. Обновляем страницу в браузере, создаем тестовую заметку
После выполнения команд, если все миграции были успешно созданы, возвращаемся к веб-интерфейсу. Можно обновить стандартную страницу Django, если она открыта, или открыть сайт заново по тому же localhost:9009. Теперь видим <textarea> для маркдауна и кнопку 'Publish'. Заполняем тестовую заметку и публикуем ее. Все описанные в промпте элементы отрендерились как ожидается, код и картинки отображаются правильно. В этом проекте изображения не хранятся на диске, а подтягиваются из указанного источника – в данном случае с демо-страницы WordPress темплейта.
Проверяем функционал редактирования и заканчиваем работу над проектом.
6. Последний коммит
Теперь, когда все готово, можно сделать второй, заключительный, коммит. От инициализации проекта до готового прототипа прошло около трех минут в реальном времени.
Описанное в посте состояние проекта можно посмотреть здесь.
Markdown-редактор, кстати, за время подготовки статьи претерпел некоторые изменения и теперь умеет работать с расширенной разметкой и даже рендерить YouTube видео внутри поста. Этот проект хранится в отдельном репозитории с подробными инструкциями по использованию и развертыванию у себя.
Проект, который я показал в статье – всего лишь простой пример, который показывает как быстро можно пройти путь от идеи до рабочего решения, если правильно использовать современные инструменты. Если вы давно хотели сделать свой проект, но откладывали из-за необходимости погружаться в детали реализации – возможно, сейчас самое время попробовать.
Когда я думаю о том, что всего два с небольшим года назад представить себе такой подход к разработке было просто невозможно, когда все, что могла нейронка – это сгенерировать boilerplate-функцию, дух захватывает. Ведь мы только в начале пути. И когда Цукерберг говорит о том, что в 2025 году в фейсбуке mid-level код будут готовить AI-ассистенты, я абсолютно в это верю. Потому что это уже почти здесь.
Спс, было полезно почитать
Отдельное спасибо за подробное описание