Что мы строим и зачем
Вы делаете одностраничный лендинг с формой заявки. Пользователь вводит имя, телефон и комментарий, а заявка сохраняется в таблицу leads в Supabase.
Это проект для новичка, который уже запускал npm-команды, но ещё не проходил полный путь: интерфейс, API, база и деплой.
Финальный результат:
- Публичный URL на Vercel.
- Рабочая форма с понятным UX.
- Серверная валидация и базовая антиспам-защита.
- Реальные записи в таблице leads.
Для кого этот проект
Подойдёт, если вы:
- Хотите первый полноценный проект для портфолио.
- Хотите практику с реальными данными, а не только с версткой.
- Используете Codex или Claude и хотите учиться управлять AI по этапам.
Что подготовить до старта
Инструменты и аккаунты
- Node.js 20+
- Git
- Аккаунт Supabase
- Аккаунт Vercel
- Codex или Claude
Границы V1
Держим проект простым:
- Одна страница.
- Одна форма.
- Один API endpoint: POST /api/leads.
- Одна таблица: leads.
Не добавляем в V1:
- Авторизацию и роли.
- CRM, email-цепочки и сложные интеграции.
- Админку и аналитику в реальном времени.
Самый простой стек
- Next.js (App Router)
- TypeScript
- Tailwind CSS
- Supabase (Postgres)
- Vercel
Пошаговая сборка
Этап 1. Каркас лендинга
Что делаем: создаём проект и 4 секции: hero, оффер, кейсы, CTA.
Промпт для Codex или Claude:
Создай минимальный Next.js (App Router) + TypeScript + Tailwind проект с одной страницей лендинга.
Секции: hero, оффер, кейсы, CTA.
В CTA добавь форму с полями: имя, телефон, комментарий.
Пока без API и без БД. Сделай адаптивную верстку mobile-first.
Не добавляй лишние страницы и интеграции.
Чекпоинт:
- npm run dev стартует без ошибок.
- http://localhost:3000 открывается.
- На мобильной ширине контент читается и не ломается.
Этап 2. Локальная форма и клиентская валидация
Что делаем: подключаем состояние формы и проверки до API.
Промпт для Codex или Claude:
Сделай controlled inputs для name, phone, comment.
Добавь клиентскую валидацию:
- name и phone обязательны,
- comment опционален,
- trim пробелов перед проверкой.
Показывай ошибки под полями.
Блокируй submit, если форма невалидна.
Сетевые запросы пока не добавляй.
Чекпоинт:
- Пустые обязательные поля не проходят.
- Ошибки исчезают после исправления.
- Кнопка отправки блокируется при невалидных данных.
Этап 3. API и server-side валидация
Что делаем: создаём POST /api/leads с надёжным контрактом ответа.
Промпт для Codex или Claude:
Создай API route POST /api/leads.
Добавь server-side валидацию: обязательные поля name и phone, trim, лимиты длины.
Сделай единый JSON-контракт:
- success: { ok: true }
- error: { ok: false, message: string }
Для невалидных данных возвращай 400, для неожиданных ошибок 500.
Пока без записи в базу.
Чекпоинт:
- Валидный curl-запрос получает 2xx и { ok: true }.
- Невалидный payload получает 400.
- Ответы предсказуемые, без технического мусора.
Этап 4. Подключение Supabase и запись лидов
Что делаем: создаём таблицу leads и вставку в API.
SQL для Supabase:
create table if not exists leads (
id bigint generated always as identity primary key,
created_at timestamptz not null default now(),
name text not null,
phone text not null,
comment text
);
Промпт для Codex или Claude:
Подключи Supabase в POST /api/leads.
Используй SUPABASE_URL и SUPABASE_SERVICE_ROLE_KEY только на сервере.
При валидном запросе добавляй запись в таблицу leads.
При ошибке БД возвращай { ok: false, message: "Не удалось сохранить заявку" } и код 500.
Не логируй секреты и не отправляй их в клиент.
Чекпоинт:
- Таблица leads создана.
- После отправки формы появляется новая строка в Supabase.
- Ошибки БД отдаются безопасно и понятно.
Этап 5. UX отправки: loading, success, error
Что делаем: делаем форму удобной и устойчивой.
Промпт для Codex или Claude:
Свяжи форму с POST /api/leads.
Добавь состояния:
- submitting: кнопка disabled и текст "Отправляем...",
- success: сообщение и очистка формы,
- error: данные остаются, есть повторная попытка.
Не меняй архитектуру и не добавляй новые страницы.
Чекпоинт:
- Нет двойной отправки.
- При успехе форма очищается.
- При ошибке введённые данные не теряются.
Этап 6. Частые ошибки AI и быстрый recovery
Что делаем: удерживаем AI в рамках задачи и умеем восстановиться.
Типичные ошибки AI:
- Добавляет лишний scope (CRM, auth, аналитика).
- Меняет контракт API в середине проекта.
- Переносит серверный код в клиент.
- Делает крупный рефакторинг без причины.
Промпт для возврата в рамки:
Вернись к V1-границам: одна страница, один endpoint POST /api/leads, одна таблица leads.
Не добавляй новых роутов, библиотек и интеграций.
Исправь только проблему: <вставьте проблему> .
Перед изменениями перечисли файлы, которые планируешь менять, и причину.
Чекпоинт:
- Изменения локальные и понятные.
- Контракт API не меняется.
- После фикса проходит предыдущий этапный чек.
Если AI ушёл не туда:
- Проверьте git status.
- Сохраните рабочие куски в backup/.
- Верните минимальный рабочий POST /api/leads.
- Проверьте curl.
- Подключайте Supabase обратно маленькими шагами.
Этап 7. Антиспам минимум и деплой
Что делаем: готовим прод-версию и проверяем end-to-end путь.
Промпт для Codex или Claude:
Добавь минимальную антиспам-защиту:
- honeypot поле,
- лимиты длины полей на сервере,
- отклонение явно мусорных payload.
Подготовь деплой-инструкцию на Vercel и проверь env-переменные.
Чекпоинт:
- npm run build проходит.
- В Vercel настроены SUPABASE_URL и SUPABASE_SERVICE_ROLE_KEY.
- В проде заявка доходит до таблицы leads.
Как запускать и проверять
Локально
npm install
npm run dev
Откройте http://localhost:3000, отправьте тестовую форму и проверьте таблицу leads.
В продакшене
- Подключите репозиторий к Vercel.
- Добавьте env-переменные.
- Нажмите Deploy.
- Сделайте smoke-test: отправка формы, success-сообщение в UI, новая запись в Supabase.
Definition of Done
Проект готов, если:
- Есть публичный URL на Vercel.
- Форма работает без перезагрузки страницы.
- Сервер валидирует данные.
- Валидные заявки сохраняются в leads.
- Ошибки не раскрывают внутренние детали и секреты.