
Помню, как год назад я сидел и смотрел на вакансии джунов. Там везде: React, TypeScript, FastAPI, REST API, деплой, CI/CD. Каждое слово звучало как что-то из другой реальности. Я читал туториалы, смотрел видосы, но всё казалось нереальным.
Потом решил: хватит учиться, надо делать. Сделал простой веб-чат на React + TypeScript и FastAPI. Ничего сложного - просто список сообщений, возможность отправить новое. Но самое важное - он работает на реальном хостинге. Фронт на Vercel, бэк на Render, и всё это можно открыть по ссылке.
В этой статье хочу рассказать, как я его делал, какие проблемы возникли (спойлер: их было много) и что в итоге получилось. Репозиторий здесь: https://github.com/ph0que/telegram-chat-app. Это не конкурент Telegram'у, но для первого проекта - сойдёт.
Идея и цель пет‑проекта
Идея была простая: сделать страницу, на которой можно смотреть сообщения и отправлять новые. Но я не хотел просто написать код и забросить его в папку на компе. Хотелось пройти весь цикл: от планирования (сделал PLAN.md с задачами) до деплоя на реальный хостинг. Разобраться с Git (а это оказалось сложнее, чем казалось), залить всё на GitHub, настроить Vercel и Render, получить рабочую ссылку. Такой подход помог мне почувствовать себя не просто учеником, а разработчиком. Ещё сделал README с инструкциями по запуску и REVIEW.md с ретроспективой - чтобы зафиксировать, что получилось, а что нет.
Архитектура: один фронт, один бэк
Стек я выбрал из того, что встречается в вакансиях: React 18 + TypeScript + Vite на фронте, Python 3.12 + FastAPI на бэке. Почему именно это? Потому что это те технологии, которые постоянно мелькают в требованиях к джунам. Захотелось попробовать их в деле, а не только читать о них.
Общаются фронт и бэк через REST API. Всё просто: GET /messages возвращает список, POST /messages добавляет новое сообщение. Никаких сложных эндпоинтов - это же учебный проект, не продакшен-сервис.
Проект разбит на frontend/ и backend/. Плюс файлы для документации: PLAN.md (что собираюсь делать), README.md (как запустить), REVIEW.md (что получилось). Такая структура помогает потом не потеряться: открываешь репозиторий спустя неделю - и сразу понятно, кто где.
Фронтенд: страница чата на React + TypeScript
На фронте одна страница: список сообщений, карточка сообщения и инпут для отправки. При загрузке страницы сообщения грузятся с бэка, а после отправки нового фронт делает POST-запрос и обновляет список.
Для стилей взял Tailwind CSS - сделал интерфейс с градиентом, разделением своих и чужих сообщений, плавными анимациями. Конечно, это не вершина UI-дизайна, но гораздо лучше, чем я ожидал от своего первого проекта.
Бэкенд: FastAPI, простые ручки и CORS
Бэкенд - простое FastAPI-приложение, которое хранит сообщения в памяти (список словарей). Запускается через Uvicorn, локально работает на http://127.0.0.1:8000. По GET / отдаёт {"message": "Telegram Chat API is running"}.
Особая история - CORS. Когда фронт задеплоился на Vercel, а бэк на Render, браузер начал ругаться и блокировать запросы. Пришлось настраивать CORS-middleware в FastAPI и добавлять домен Vercel в список разрешённых.
Деплой: Vercel для фронта и Render для бэка
С самого начала было важно не просто написать код, а реально выкатить всё в продакшен. Выбрал Vercel для фронта и Render для бэка. Бэк на Render запускается через uvicorn как Web Service, а фронт на Vercel собирается Vite'ом (команда npm run build, выход в dist).
Ключевой момент - переменная окружения VITE_API_URL на фронте. В ней URL бэка на Render. Vercel подставляет её при сборке, и React уже знает, куда слать запросы. Открываешь страницу на Vercel - общаешься с бэком на Render.
Git, node_modules и другие «простые» грабли
Первые проблемы пришли не из кода, а из Git. Untracked файлы, изменения в virtualenv, случайные папки. Особенно запомнился момент: локально всё работает, а на GitHub нет node_modules. Пришлось понять, что эти директории и не должны попадать в репозиторий - они подтягиваются через npm install.
Были и более хитрые косяки. Например, когда git status показывал изменения только в мусорных файлах. Или когда нужный main.py с правками CORS не был закоммичен, и Render запускал старую версию.
Все эти "мелочи" научили следить за статусом репозитория и понимать, какие файлы реально участвуют в сборке.
CORS‑драма и чувство «победы»
Самый яркий момент - когда задеплоенный фронт на Vercel падал с CORS-ошибкой. Мне пришлось лезть в DevTools, смотреть заголовки, постепенно править FastAPI-конфиг, пока браузер наконец не сказал "окей, это легальный кросс-доменный запрос". Когда всё заработало - чат подтягивал сообщения, позволял отправлять новые, и после обновления страницы все оставались на месте - это было чувство победы.
Что получилось
В итоге получился маленький, но рабочий чат: фронт и бэк разделены, код на GitHub, фронт крутится на Vercel, бэк на Render, CORS настроен, документация описывает текущее состояние. Для моего первого веб-проекта это нормальный результат, который можно показать в резюме.
Самое главное - я понял, что даже простой учебный чат может научить всему циклу разработки, от git-хаоса до работающего прод-URL. И это чувство "я реально что-то выкатил" стоит всех мучений с CORS и деплоем.
