Что нужно
Инструмент Зачем Стоимость Claude Code Агент, пишет и запускает код Pro $20/мес (токены отдельно) или Max $100/мес Codex CLI Альтернативный агент от OpenAI ChatGPT Plus/Pro/Team включён VS Code Редактор, где хранится проект бесплатно Supabase База данных и авторизация бесплатно до лимита VPS Сервер для деплоя от $6/мес OpenRouter API для AI-функций в сервисе от $10 пополнение GitHub Хранение кода и деплой бесплатно
Claude Code и Codex — взаимозаменяемы. Логика работы та же, различаются только команды установки и название файла с инструкциями (CLAUDE.md или AGENTS.md). Далее в тексте будет указано где они расходятся.
Блок 1. Инструменты
Установить агента
Claude Code:
npm install -g @anthropic-ai/claude-code
claude # запустится браузерная авторизация
Codex CLI:
npm install -g @openai/codex # именно @openai/codex, не просто codex
codex auth # браузерная авторизация через ChatGPT
Важно: пакет без @openai/ — это несвязанный проект 2012 года. Он установится без ошибок но ничего полезного не сделает.
После установки запустите агента в любой папке:
claude # для Claude Code
codex # для Codex
Агент видит все файлы в текущей папке, может их создавать, редактировать и запускать команды в терминале.
Как работает связка VS Code + агент
VS Code — редактор. Там хранится код и видно что происходит. Агент запускается в встроенном терминале (Ctrl+ на Windows/Linux, Cmd+ на Mac).
Рабочий цикл выглядит так:
- Открыли папку проекта в VS Code
- Открыли терминал, запустили claude или codex
- Написали задачу текстом
- Агент предложил изменения — вы проверили и подтвердили
- Открыли браузер на localhost:3000 — проверили результат
- Написали следующую задачу
По умолчанию Claude Code спрашивает разрешение перед каждым изменением файла. Codex работает аналогично. Если хочется чтобы агент работал без постоянных подтверждений — в Claude Code это флаг --dangerously-skip-permissions, в Codex — режим --full-auto. Для обучения лучше оставить подтверждения включёнными — так лучше понимаешь что происходит.
Блок 2. Спека и флоу
Спека — это текстовый файл с описанием сервиса. Главный урок вайбкодинга: чем точнее описана задача, тем меньше итераций нужно. Не «сделай форму заявок», а полное описание кто пользуется, что делает и что происходит в каждом состоянии.
Попросите агента помочь написать спеку в диалоге:
Я хочу сделать форму для сбора заявок с простой админкой.
Задавай мне вопросы по одному, я буду отвечать.
По ходу записывай всё в файл SPEC.md.
Когда соберёшь достаточно информации — покажи итоговый файл.
Агент будет уточнять детали. Отвечайте конкретно. В конце у вас будет файл — основа для всей дальнейшей работы.
Что должно быть в спеке
Вот шаблон который работает. Это не формальный документ — просто ответы на конкретные вопросы:
# SPEC.md
## Что это
Форма для приёма заявок на консультацию.
Гость заполняет форму → заявка сохраняется →
владелец видит все заявки в закрытой админке.
## Пользователи
- Гость — заполняет форму, не регистрируется
- Админ — логинится, видит все заявки, меняет статус
## Флоу гостя
1. Открывает страницу → видит форму
2. Вводит имя, email, текст запроса → нажимает «Отправить»
3. Видит экран благодарности: «Свяжемся в течение дня»
## Флоу админа
1. Открывает /admin → редиректит на /admin/login если не залогинен
2. Вводит email и пароль → попадает в список заявок
3. Видит заявки: имя, email, текст, дата, статус (новая / в работе / закрыта)
4. Нажимает на заявку → может изменить статус
## Экраны и состояния
### Форма (/):
- Состояние: обычное — форма заполнена частично или пуста
- Состояние: отправка — кнопка неактивна, показывает «Отправляю...»
- Состояние: ошибка валидации — подсветить незаполненные поля, текст ошибки
- Состояние: ошибка сервера — «Что-то пошло не так, попробуйте позже»
- Состояние: успех — скрыть форму, показать сообщение
### Список заявок (/admin):
- Состояние: загрузка — скелетон строк
- Состояние: пусто — «Заявок пока нет»
- Состояние: список — таблица с сортировкой по дате (новые сверху)
## Что НЕ входит в первую версию
- Уведомления на email при новой заявке
- Поиск и фильтрация заявок
- Несколько админов
- Удаление заявок
## Стек
Next.js App Router, TypeScript, Tailwind CSS, Supabase
Раздел «Что НЕ входит» — один из важнейших. Без него агент начинает добавлять функции которые не просили, а вы теряете время на их проверку.
Описание состояний экранов — сила дизайнера
Обычный разработчик напишет в промпте «сделай форму» и не подумает про empty state, ошибку валидации и состояние загрузки. Дизайнер думает именно так — экранами и состояниями. Это ваше преимущество.
Чем подробнее описаны состояния в спеке — тем меньше будет правок после. Агент реализует ровно то что написано.
Блок 3. Интерфейс
Создать проект
Попросите агента:
Создай новый Next.js-проект в папке request-form.
Стек: TypeScript strict mode, Tailwind CSS, App Router.
После создания запусти dev-сервер и убедись что localhost:3000 открывается.
Или сами:
npx create-next-app@latest request-form --typescript --tailwind --app
cd request-form
npm run dev
Создать файл с инструкциями для агента
Это аналог брифа — агент читает его в начале каждой сессии. Для Claude Code это CLAUDE.md, для Codex — AGENTS.md. Структура одинаковая:
# AGENTS.md (или CLAUDE.md)
## Контекст
Читай SPEC.md перед началом любой задачи.
Если что-то не описано в SPEC.md — спроси, не придумывай.
## Стек
- Next.js App Router, TypeScript strict mode
- Tailwind CSS — никаких произвольных hex-значений, только классы Tailwind
- Supabase — auth и база данных через @supabase/ssr
## Правила
- Каждый экран в отдельном компоненте
- Все состояния из SPEC.md обязательны: загрузка, ошибка, пусто
- После изменений запусти npm run build — убедись что TypeScript не ругается
- Не добавляй фичи которых нет в SPEC.md
## Структура
src/
app/ — роуты
components/ — компоненты
lib/ — утилиты, supabase-клиент
Собирать интерфейс по одному экрану
Не давайте задачу «собери весь интерфейс сразу». Лучше по одному экрану — так проще проверить каждый результат.
Задача на форму:
Прочитай SPEC.md.
Создай главную страницу src/app/page.tsx с формой заявки.
Поля: Имя (обязательное), Email (обязательное, валидация формата),
Текст запроса (обязательное, минимум 10 символов).
Кнопка «Отправить».
Состояния кнопки: обычное / «Отправляю...» с disabled во время запроса.
Состояния формы: пустая → валидация → успех (скрыть форму, показать текст)
→ ошибка сервера (toast или текст под кнопкой).
Пока используй console.log вместо реального запроса — реальный добавим позже.
Адаптивно: мобильный и десктоп.
После того как форма выглядит правильно — проверяйте конкретно. Не «что-то не так», а точное описание:
Кнопка «Отправить» на мобильном слишком мелкая — менее 44px высотой.
Сообщение об ошибке валидации появляется только после нажатия кнопки,
а нужно при потере фокуса (onBlur) на каждом поле.
Задача на страницу успеха:
После отправки формы скрой её и покажи блок с текстом:
«Спасибо! Свяжемся с вами в течение дня.»
И ссылку «Отправить ещё одну заявку» которая возвращает форму.
Задача на админку:
Создай страницу src/app/admin/page.tsx.
Таблица заявок: колонки — Имя, Email, Дата, Статус, Действие.
Статус: три варианта — «Новая», «В работе», «Закрыта».
Сортировка: новые сверху.
Состояния: загрузка (скелетон на 5 строк), пусто («Заявок пока нет»), список.
Пока используй моковые данные — массив из 3 объектов.
Реальные данные подключим когда настроим Supabase.
Блок 4. Деплой — сразу, не в конце
Деплоить нужно как только есть первый рабочий экран. Не ждите пока всё готово. Ранний деплой показывает реальное поведение на сервере и помогает поймать проблемы которые не видны локально.
Vercel — одна команда
npm install -g vercel
vercel
Vercel спросит несколько вопросов и задеплоит. Бесплатно для личных проектов. Каждый push в GitHub — автоматически новая версия.
VPS — агент делает сам
Купите VPS: DigitalOcean от $6/мес, Timeweb от 200 руб/мес, Selectel. Нужен Ubuntu 22/24.
Задача для агента:
Задеплой этот Next.js-проект на мой VPS.
IP: [адрес]
Пользователь: root
Пароль: [пароль]
Что нужно сделать:
— Установить Node.js 20, nginx, PM2
— Запушить проект в новый GitHub-репозиторий [ссылка]
— Склонировать на сервер, запустить npm install и npm run build
— Запустить через PM2 на порту 3000
— Настроить nginx как reverse proxy: все запросы → localhost:3000
— Выписать SSL-сертификат через Let's Encrypt для домена [домен]
— PM2 в автозапуске при перезагрузке сервера
После каждого шага сообщай результат.
Агент выполнит всё последовательно. Если на каком-то шаге упадёт ошибка — опишет её и предложит решение.
Блок 5. База данных и авторизация
Подключить Supabase
Зарегистрируйтесь на supabase.com, создайте новый проект. В настройках (Settings → API) скопируйте Project URL и anon key.
Задача агенту:
Подключи Supabase к проекту.
Project URL: [вставить]
Anon key: [вставить]
Нужно:
1. Установить @supabase/ssr и @supabase/supabase-js
2. Создать src/lib/supabase/client.ts — браузерный клиент
3. Создать src/lib/supabase/server.ts — серверный клиент для App Router
4. Добавить переменные в .env.local:
NEXT_PUBLIC_SUPABASE_URL=...
NEXT_PUBLIC_SUPABASE_ANON_KEY=...
5. Убедиться что .env.local есть в .gitignore
Создать таблицы
Создай SQL-миграцию для таблицы requests в Supabase.
Поля:
- id: uuid, primary key, default gen_random_uuid()
- name: text, not null
- email: text, not null
- message: text, not null
- status: text, not null, default 'new',
check (status in ('new', 'in_progress', 'closed'))
- created_at: timestamptz, default now()
Включи Row Level Security (RLS):
- Вставка (insert): разрешить всем (анонимным тоже)
- Чтение (select): только авторизованным пользователям
- Обновление (update): только авторизованным
Дай мне готовый SQL для выполнения в Supabase Dashboard → SQL Editor.
Скопируйте SQL, откройте Supabase Dashboard → SQL Editor → New query → вставьте и запустите.
Подключить авторизацию в админку
Добавь авторизацию для раздела /admin через Supabase Auth.
Нужно:
1. Страница /admin/login:
— Форма: email + пароль
— Кнопки «Войти» и «Зарегистрироваться»
— При ошибке: показать текст ошибки под формой
— При успехе: редирект на /admin
2. Middleware (middleware.ts в корне):
— Любой запрос на /admin/* — проверить сессию
— Если нет сессии — редирект на /admin/login
3. Кнопка «Выйти» на странице /admin
— При нажатии: signOut → редирект на /admin/login
После этого создайте тестового пользователя в Supabase Dashboard → Authentication → Users → Add user.
Заменить моковые данные на реальные
Форма → реальная отправка:
Форма на главной странице сейчас делает console.log.
Замени на реальную отправку в Supabase.
Используй Server Action (файл src/app/actions.ts):
— Принимает: name, email, message
— Валидирует: все поля обязательные, email — валидный формат
— Вставляет в таблицу requests
— Возвращает: { success: true } или { error: 'текст ошибки' }
В форме: при ошибке — показать текст пользователю,
при успехе — переключить в состояние успеха.
Админка → реальные данные:
Страница /admin сейчас показывает моковые данные.
Замени на загрузку из Supabase.
Список заявок — серверный компонент, запрос через серверный клиент.
Сортировка: created_at DESC.
Изменение статуса — Client Component с Server Action:
— Выпадающий список: Новая / В работе / Закрыта
— При изменении: обновляет запись в базе,
перезагружает данные через revalidatePath('/admin')
Блок 6. AI-функции и интеграции
OpenRouter — один API для всех моделей
OpenRouter даёт доступ к Claude, GPT, Gemini и десяткам других моделей через единый API. Удобен для AI-функций в сервисе: не нужно заводить несколько подписок.
Зарегистрируйтесь на openrouter.ai, пополните баланс, скопируйте ключ.
Добавь в .env.local:
OPENROUTER_API_KEY=sk-or-...
Создай src/lib/openrouter.ts:
async function generateReply(
customerName: string,
customerMessage: string
): Promise
Функция отправляет запрос к OpenRouter.
Модель: anthropic/claude-sonnet-4
Системный промпт: «Ты помощник по работе с клиентами.
Пиши вежливо, по-русски, кратко — 2-3 предложения.»
Пользовательский промпт: «Напиши черновик ответа клиенту [имя],
который написал: [сообщение]»
При ошибке запроса — вернуть null, не бросать исключение.
Добавить в админку:
В таблицу заявок добавь кнопку «Черновик ответа» рядом с каждой заявкой.
При нажатии:
— Кнопка показывает спиннер
— Вызывает generateReply с именем и текстом заявки
— Показывает результат в модальном окне с кнопками «Скопировать» и «Закрыть»
— Кнопка «Скопировать» копирует текст в буфер, меняет текст на «Скопировано ✓» на 2 секунды
Telegram-уведомления о новых заявках
Создайте бота через @BotFather в Telegram, получите токен. Узнайте свой chat ID через @userinfobot.
При успешной вставке заявки в Supabase отправляй уведомление в Telegram.
В Server Action после INSERT добавь:
fetch('https://api.telegram.org/bot[токен]/sendMessage', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chat_id: '[chat_id]',
text: `Новая заявка от ${name}\nEmail: ${email}\n\n${message}`
})
})
Запрос асинхронный — не await, не блокирует ответ пользователю.
Ошибка отправки не влияет на сохранение заявки.
Блок 7. Тесты
Тесты нужны чтобы знать — новое изменение не сломало то что уже работает. Особенно важно когда проект растёт.
Unit-тесты через Vitest
Установи Vitest и напиши тесты для основных функций.
Что тестировать:
1. Валидация формы (src/lib/validate.ts — создай если нет):
— Пустое имя → ошибка 'Введите имя'
— Невалидный email → ошибка 'Введите корректный email'
— Сообщение короче 10 символов → ошибка 'Слишком короткое сообщение'
— Все поля заполнены корректно → возвращает null (нет ошибок)
2. generateReply из openrouter.ts:
— Замокай fetch
— Успешный ответ → возвращает строку
— Ошибка сети → возвращает null, не бросает исключение
После написания запусти npx vitest run — все тесты должны пройти.
E2E-тест через Playwright
Установи @playwright/test и напиши e2e тест:
1. Открыть главную страницу
2. Заполнить форму: имя «Тест», email «test@example.com»,
сообщение «Тестовое сообщение для проверки»
3. Нажать «Отправить»
4. Проверить что появился текст «Спасибо»
5. Проверить что форма больше не видна
Тест должен использовать тестовую базу (задай через env SUPABASE_URL_TEST)
или мокать Server Action.
Pre-commit хук — тесты перед каждым коммитом
Настрой pre-commit хук через husky и lint-staged:
Перед каждым коммитом:
1. npx vitest run — unit-тесты
2. npm run build — проверка TypeScript и сборки
Если что-то упало — коммит не проходит, показывает какой тест провалился.
Блок 8. Портфолио и кейс
Что показывать
Сервис в продакшене — это уже кейс. Но для портфолио важно показать мышление, а не только результат.
Структура кейса для вайбкодинга:
## Задача
Что хотел сделать и зачем — одним абзацем.
## Как описывал задачу
Покажите первую и финальную версию промпта на одну фичу.
Что уточнялось, от чего отказались и почему.
## Что было нетривиально
Один-два момента где агент не справился с первого раза.
Что именно не так и как переформулировали задачу.
## Результат
Ссылка на живой сервис.
Скриншот или короткое видео.
Разница между сильным кейсом и слабым — в разделе «как описывал задачу». Два похожих по результату сервиса, но один показывает процесс мышления — и это тот который запомнят.
Типичные проблемы
Агент ходит по кругу с одной ошибкой. Не давайте ему больше итераций с той же формулировкой. Откройте новую сессию, опишите только конкретную ошибку: текст из консоли, файл, строку. Без контекста всего проекта.
После изменений сломалось что работало. Запустите npx vitest run. Если тестов нет — попросите агента написать тест на сломавшееся место, потом починить его.
Агент добавляет фичи которые не просили. В AGENTS.md/CLAUDE.md добавьте явное правило: «Не добавляй ничего чего нет в SPEC.md. Если считаешь нужным — спроси прежде чем делать».
Суpabase выдаёт ошибку Row Level Security. Значит политика RLS не разрешает операцию для текущего пользователя. Опишите агенту: что за операция, авторизован ли пользователь, и текст ошибки. Агент поправит политику.
Контекст теряется между сессиями. SPEC.md и AGENTS.md/CLAUDE.md решают это. В начале новой сессии: «Прочитай SPEC.md и AGENTS.md. Кратко — что уже сделано, что осталось».
Итог
Артефакт Где лежит Описание сервиса SPEC.md Правила для агента AGENTS.md или CLAUDE.md Интерфейс src/app/ и src/components/ База данных и авторизация Supabase AI-функции src/lib/openrouter.ts Тесты Vitest + Playwright Сервис в продакшене VPS или Vercel
Главное изменение после первого запущенного сервиса: перестаёшь думать «нужен разработчик» и начинаешь думать «нужна спека».
Источник и полная версия: VibeCode Wiki