Почему 90% промтов дают мусор
LLM не видит ваш кодовую базу, не знает дизайн-систему и не понимает неявных требований доступности. Она предсказывает токены, а не проектирует архитектуру.
Типичный запрос «сделай карточку товара» выдает <div class="card"> с хардкодом пикселей, без TypeScript-интерфейсов, без стейтов загрузки и ошибок, с инлайн-стилями вместо CSS-переменных.
Рабочий промт — это техническое задание в сжатом виде. Он закрывает пробелы контекста до генерации, а не в code-review после.
Формула «Контекст — Ограничения — Компонент»
1. Контекст среды
Стек (React/Vue/Svelte), версия, UI-кит (Tailwind, CSS Modules, Styled Components), настройка TypeScript (strict mode), линтеры. Укажите файл tsconfig.json при необходимости.
2. Жесткие ограничения
«Никаких инлайн-стилей», «Используй только токены из theme.colors», «Совместимость с SSR», «Покрый доступность по WCAG 2.1 AA», «Макс. 150 строк». Запреты работают лучше пожеланий.
3. Спецификация компонента
Props-интерфейс, варианты (variant/size), стейты (loading/disabled/error), слоты для композиции, forwardRef, побочные эффекты. Опишите API, который хотите получить, а не верстку.
Паттерн «Composite»: Форма авторизации с валидацией
Versus: Плохой промт vs Архитектурный промт
❌ Плохой промт
"Сделай таблицу пользователей с сортировкой и пагинацией. Используй React и Tailwind."
Что получится:
- Массив данных захардкожен в компоненте
- Сортировка только клиентская, ломается на 10k строк
- Нет скелетонов загрузки, нет ошибок
- Пагинация — просто кнопки Prev/Next без URL sync
- Заголовки колонок не типизированы
- Доступность: ноль, табы не работают
✅ Архитектурный промт
"DataTable<T> generic component.
Props: columns: ColumnDef<T>[], data: T[],
fetchFn: (params) => Promise<{data: T[], total: number}>,
sortMode: 'client' | 'server',
pageSize: number, pageSizeOptions: number[].
Features:
- TanStack Table v8 (headless)
- Server-side sort/pagination/filter via fetchFn
- URL sync (nuqs or searchParams)
- Row selection (checkbox) + bulk actions toolbar
- Skeleton rows (shadcn/ui pattern)
- Error boundary + retry button
- Column resizing, pinning, visibility toggle
- Full keyboard nav + ARIA grid pattern
- Virtualization @tanstack/react-virtual for >100 rows
Types: Export ColumnDef, DataTableProps, ToolbarActions."
Продвинутый уровень: Дизайн-токены как источник истины
JSON для LLM (не CSS)
Не просите «использовать переменные». Дайте токены в JSON — модель точно скопирует имена и значения.
{
"colors": {
"primary": "#D80621",
"primaryForeground": "#FFFFFF",
"muted": "#F5F5F5",
"mutedForeground": "#737373",
"destructive": "#B50518",
"border": "#E5E5E5"
},
"radius": { "sm": "4px", "md": "8px", "lg": "12px", "full": "9999px" },
"spacing": { "1": "4px", "2": "8px", "3": "12px", "4": "16px", "6": "24px" }
}
Промт для темизации
Добавьте в контекст — получите компоненты, готовые к dark mode и ребрендингу за минуты.
// Темизация через CSS Variables (Tailwind v3.4+)
// Токены из JSON выше → tailwind.config.ts → CSS vars
Добавь в промт:
"Все цвета ТОЛЬКО через CSS variables:
- bg-primary → var(--color-primary)
- text-primary-foreground → var(--color-primary-foreground)
- border → var(--color-border)
Dark mode: data-theme="dark" на html.
В dark токены меняются: primary → #E53348, muted → #262626.
Компонент НЕ должен импортировать токены напрямую.
Только через tailwind-классы или style={ { '--color-primary': tokens.primary } } для инлайн-критических мест."
Итеративный цикл: «Сгенерируй → Проверь → Исправь промт»
Генерация
Запускаете архитектурный промт. Получаете черновик.
Линт + Типы + Тесты
Прогоняете tsc --noEmit, ESLint, Prettier, юнит-тесты (Vitest/RTL). Собираете ошибки в список.
Промт-исправление
Не правьте код вручную. Пишите follow-up: «Ошибка TS2322 в строке 45: Prop ‘onClick’ ожидает MouseEvent, приходит void. Исправь тип handler’а в интерфейсе Props.»
Коммит промта
Успешный follow-up добавляете в базовый промт как новое ограничение. База знаний растет, качество следующего компонента выше.
Промт — это не запрос. Промт — это контракт.
Каждый раз, когда вы копируете сгенерированный код в проект без правок — вы выигрываете час. Когда правите — теряете. Инвестируйте 10 минут в промт, чтобы сэкономить часы ревью. Лучший код — тот, который не пришлось переписывать.