раздел 05 · шаг 3/7

Шаг 3. React + Vite + Tailwind

Поднимаем фронт. Vite даёт быстрый dev-server, React 19 + TypeScript - типизированный UI, Tailwind 4 - стили без CSS-файлов, TanStack Query - кеш и состояние запросов.

Что делаем

  • Создаём проект во frontend/ через Vite
  • Настраиваем Tailwind 4
  • Поднимаем минимальный UI: список задач с инлайн-добавлением
  • Запускаем dev, видим заготовку

Промпт для Claude

Создай frontend во frontend/ на Vite + React 19 + TypeScript + Tailwind 4 + TanStack Query.

Стек:
- Vite (без SWC, обычный esbuild)
- React 19, TypeScript 5
- Tailwind CSS 4 (через @tailwindcss/vite плагин, без отдельного tailwind.config.js если можно)
- @tanstack/react-query 5 для fetch и кеша
- Без UI-библиотек - всё на кастомных компонентах с Tailwind

UI:
- Главная страница - список задач
- Инлайн-добавление сверху: input + Enter создаёт задачу через POST /api/tasks
- Каждая задача - строка с чекбоксом, заголовком, бейджем категории, кнопкой удалить
- Dark theme: фон bg-zinc-950, текст zinc-100
- Акценты эмеральд: emerald-400 для активных элементов, emerald-500 для кнопок
- Минимализм, без скругления больше rounded-lg, без теней
- Адаптив под мобилу

Backend живёт на http://localhost:8000.
Сделай util fetchApi с базовым URL и обработкой ошибок.
Используй QueryClient с дефолтным staleTime 30 сек.

Запиши команды запуска в frontend/README.md и в корневой README.md.

Что Claude создаст

Структура:

frontend/
├── public/
├── src/
│   ├── App.tsx                 # главная страница
│   ├── main.tsx                # точка входа, QueryClientProvider
│   ├── index.css               # @import "tailwindcss"
│   ├── lib/
│   │   └── api.ts              # fetchApi util
│   ├── components/
│   │   ├── TaskList.tsx
│   │   ├── TaskItem.tsx
│   │   └── TaskInput.tsx
│   └── types.ts                # временные типы (на шаге 4 заменим)
├── index.html
├── package.json
├── tsconfig.json
├── vite.config.ts              # с @tailwindcss/vite
└── README.md

package.json должен содержать:

{
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "@tanstack/react-query": "^5.0.0"
  },
  "devDependencies": {
    "@tailwindcss/vite": "^4.0.0",
    "@types/react": "^19.0.0",
    "@types/react-dom": "^19.0.0",
    "@vitejs/plugin-react": "^4.3.0",
    "tailwindcss": "^4.0.0",
    "typescript": "^5.6.0",
    "vite": "^6.0.0"
  }
}

Устанавливаем зависимости

cd frontend
pnpm install

Запуск

pnpm dev

В терминале:

  VITE v6.0.0  ready in 234 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose

Открываете http://localhost:5173. Видите заготовку: тёмный фон, поле ввода, пустой список.

Первая проверка работы

Включите бэк в одном терминале (uvicorn app.main:app --reload), фронт в другом (pnpm dev).

Вбейте в поле ввода "купить молоко", нажмите Enter. Задача должна:

  1. Уйти POST-запросом на http://localhost:8000/api/tasks
  2. Вернуться в ответе с id и created_at
  3. Появиться в списке через invalidate query

Если CORS-ошибка - значит, на шаге 2 бэк настроен на неправильный origin. Откройте backend/app/main.py, проверьте что в allow_origins есть http://localhost:5173.

скриншот

Что НЕ работает на этом шаге

  • Бэйджи категорий показывают только other - категоризация будет на шаге 5
  • TS-типы написаны руками (types.ts) - на шаге 4 заменим на сгенерированные
  • Нет состояний loading/error - тоже на шаге 4
  • Нет тестов - шаг 6

Сейчас задача - чтобы пользовательский поток работал. Чистоту наводим дальше.

Точка сохранения

cd ..
git add .
git commit -m "step 3: React + Vite + Tailwind frontend, basic task list"

Полезные ссылки