Современный интерфейс мессенджера на TypeScript, Handlebars и Vite.
Репозиторий содержит фронтенд GilgaChat: экран авторизации, переиспользуемые компоненты и страницы, которые можно развивать в полноценный мессенджер.
Демо: https://maximste.github.io/GilgaChat/
GilgaChat — учебный фронтенд-проект, в котором показано, как собрать небольшую компонентную систему без тяжёлого фреймворка.
Вместо React/Vue используются:
- TypeScript — типизация.
- Handlebars — шаблоны; вложенные блоки подключаются через зарегистрированные хелперы (
registerComponent). - Vite — сборка и dev-сервер.
- SCSS — стили.
В приложении навигация идёт по pathname (History API: history.pushState / событие popstate), пути заданы в src/shared/config/routes.ts (APP_PATHS) и учитывают base Vite при деплое под префиксом (например GitHub Pages). Есть layout мессенджера (сайдбар и основная область: заглушка или экран переписки), формы входа и регистрации, экран настроек профиля, страницы ошибок 404 и 500. Интерфейс строится на базовом классе Block (шаблон + DOM + жизненный цикл) и переиспользуемых UI-блоках.
Проект организован по Feature-Sliced Design (FSD): слои shared, features, widgets, pages, app. Подробнее — в docs/FSD.md.
Точка входа
Для неавторизованного пользователя стартовый экран — Вход по пути / (на GitHub Pages с base: '/GilgaChat/' это будет …/GilgaChat/). Отдельной «демо-главной» со списком всех маршрутов нет; переходы — через формы, сайдбар и appHref() из APP_PATHS.
Layout мессенджера (маршрут /messenger)
Слева: сайдбар с названием приложения и выпадающим меню, поиском, списком личных сообщений (аватар, имя, превью последнего сообщения, индикатор статуса), списком групп (иконка, название, превью) и блоком текущего пользователя (имя, статус, ссылка на настройки).
Справа: пока чат не выбран — заглушка NoChatStub («Выберите чат»); после выбора диалога в списке — ChatPage: шапка с действиями, лента сообщений (даты и входящие/исходящие сообщения), индикатор набора, внизу MessageComposer для ввода и отправки (поле ввода с name="message"). У чатов без сообщений в ленте показывается вложенная заглушка «Нет сообщений». Список чатов и сценарии создания/участников идут через HTTP API (shared/lib/api, контроллер chatsController). Для выбранного чата с числовым идентификатором лента сообщений подгружается и обновляется через WebSocket (история get old, broadcast новых сообщений); при отсутствии chatId или без сессии возможна демо-лента из моков (createDemoChatTimeline).
Авторизация и профиль
Вход (логин) — маршрут / (APP_PATHS.login): форма с логотипом, полями email/пароль и ссылкой «Забыли пароль?».
Регистрация — маршрут /sign-up (APP_PATHS.signUp): форма (login, display_name, email, имя, фамилия, телефон, пароль).
Профиль / настройки — маршрут /settings (APP_PATHS.settings): карточка профиля с аватаром (смена через выбор файла, загрузка через API), блок Profile Information (login, display name, email, имя, фамилия, телефон). Кнопка «Edit Profile» открывает форму редактирования (данные пользователя и опционально смена пароля: current password, new password). Сбои запросов (сохранение профиля, аватар, выход и т.п.) показываются тостом об ошибке в правом верхнем углу, а не через window.alert.
Клиентская валидация полей на формах входа, регистрации и редактирования профиля.
Страницы ошибок
404 — маршрут /404: «Oops! You're Lost in Cyberspace» с изображением, подсказками и кнопками «Take Me Home» / «Go Back». Неизвестный pathname обрабатывается роутером и приводит к этому экрану.
500 — маршрут /500: «Houston, we have a problem!» с карточками статуса и кнопками «Try Again» / «Go Home».
Переиспользуемые UI-компоненты
Среди блоков в shared/ui: Button, Input, Label, Link, FormField, IconButton, Textarea, Search, атомы сайдбара (SidebarAvatar, SidebarPrimaryLine и др.), модуль toast — императивный вызов showErrorToast(message) и компонент ErrorToast на базе Block (шаблон .hbs, стили toast.scss): стек уведомлений в правом верхнем углу, автоскрытие и кнопка закрытия. У типичного компонента: класс на TypeScript, шаблон .hbs, стили SCSS; родительские шаблоны вставляют дочерние блоки через registerComponent.
Layout’ы
MainLayout — шапка и область контента для экранов входа, регистрации, настроек профиля и страниц ошибок.
MessengerLayout — сайдбар и основная область мессенджера.
ChatPage (виджет) — ChatHeader, ChatThread (строки ленты ChatTimelineRow + индикатор набора), ChatFooter с MessageComposer.
Разработка и деплой
Dev-сервер Vite с hot reload, сборка TypeScript + Vite.
В корне есть netlify.toml: сборка npm run build, публикация каталога dist/ (актуальность деплоя на Netlify смотрите в панели проекта).
GitHub Actions для CI (в т.ч. Jest, тесты по спринтам для внешнего чек-листа).
ESLint, Stylelint, Prettier, Jest, husky (pre-commit: линтеры и тесты).
- Язык: TypeScript
- Сборка и dev-сервер: Vite
- Шаблоны: Handlebars
- Стили: SCSS
- Деплой: GitHub Pages — основной публичный билд. Netlify: конфигурация в
netlify.toml; URL и статус сборки в кабинете Netlify.
Макет в Figma: GilgaChat UI
- Node.js: 22.x (рекомендуется, совпадает с настройками CI)
- npm: поставляется с Node.js
git clone https://github.com/maximste/GilgaChat.git
cd GilgaChat
npm installЗапуск dev-сервера:
npm run devСборка для продакшена:
npm run buildЛокальный просмотр продакшен-сборки:
npm run previewСборка и просмотр одной командой:
npm run startИспользуется Jest; файлы *.test.ts лежат рядом с модулями в src/.
npm test # один прогон всех тестов
npm run test:watch # перезапуск при измененияхПроверка типов и линтеров: npm run prebuild, npm run lint.
.
├── index.html # Подключение src/app/index.ts
├── public
│ └── images/ # Статика (логотип, изображение для 404)
├── src
│ ├── app/ # Точка входа, класс App, Router (pathname), registerComponent для виджетов
│ ├── pages/ # Страницы и setup-функции (auth, register, profile, messenger, not-found, server-error)
│ ├── widgets/
│ │ ├── mainLayout/ # Шапка + контент (вход, регистрация, настройки, ошибки)
│ │ ├── messengerLayout/ # Сайдбар + область под чат / заглушку
│ │ ├── sidebar/ # Сайдбар: секции чатов, список, панель пользователя, событие выбора чата
│ │ ├── chatPage/ # ChatPage, ChatHeader, ChatThread, ChatTimelineRow, ChatFooter
│ │ ├── messageComposer/ # Поле ввода и отправка сообщения (событие в чат)
│ │ └── noChatStub/ # Заглушка «чат не выбран» / пустая область
│ ├── features/
│ │ ├── auth/ui/ # Форма входа
│ │ ├── registration/ui/ # Форма регистрации
│ │ └── editProfile/ui/ # Форма редактирования профиля
│ ├── entities/ # user (заглушка под рост домена)
│ └── shared/
│ ├── ui/ # block, button, input, label, link, formField, iconButton, textarea, search, toast, sidebar/*
│ ├── styles/ # global, variables, _colors, _buttons, …
│ └── lib/ # api (authApi, chatsApi, userApi, ApiError), types, utils (в т.ч. HTTPTransport), mocks, validation
├── docs/
│ └── FSD.md # Слои FSD и правила импортов
├── vite.config.ts # Конфиг Vite (base, build, preview port: 3000)
├── netlify.toml # Netlify: команда сборки, каталог публикации dist
└── .github/workflows/ # CI (тесты по спринтам), деплой на GitHub Pages из ветки deploy
Кратко о слоях и импортах — в docs/FSD.md.
Точка входа — src/app/index.ts: глобальные стили, регистрация общих и виджетных блоков, создание App. После DOMContentLoaded инициализируется сессия (initAuthSession), создаётся Router (createAppRouter), подключаются внутренние ссылки SPA (setupSpaLinks), вызывается router.start() — по window.location.pathname (с учётом base) выбирается маршрут и монтируется соответствующий Block в контейнер #app.
Роутинг
Регистрация маршрутов — в src/app/router/createAppRouter.ts (связка APP_PATHS ↔ блоки из routeBlocks и страниц из pages/). Перед отрисовкой вызывается authResolvePath (authResolvePath.ts): гостю доступны только / и /sign-up; остальные пути перенаправляются на /. Авторизованный пользователь с / или /sign-up перенаправляется на /messenger.
/messenger— MessengerLayout и setupMessengerChatPage: справа сначала NoChatStub, после выбора чата в сайдбаре — ChatPage./,/sign-up,/settings,/404,/500— MainLayout и контент экрана (формы авторизации, профиль, ошибки).- Неизвестный pathname — страница 404 (см.
notFoundPathв роутере).
Форма редактирования профиля открывается по клику «Edit Profile» внутри экрана /settings.
Ошибки запросов
Сообщения об ошибках сети и ответов API (вход, регистрация, мессенджер — поиск пользователей, создание чатов, профиль, выход) выводятся через showErrorToast из @/shared/ui/toast (внутри — ErrorToast как Block). Глобальный window.alert для этих сценариев не используется.
Проект изначально был учебным по спринтам, поэтому могут встречаться ветки вроде sprint_1, sprint_2 и т.п.
Workflow GitHub Actions запускает автоматические тесты для этих веток при pull request в main.
Для своей разработки или open-source можно оставить этот workflow или настроить свою стратегию веток.
Актуальная версия проекта раздаётся с GitHub Pages (см. раздел ниже). Конфигурация для Netlify в репозитории сохранена, но из-за проблем с работой сервиса Netlify проект там не деплоится; ссылка gilgachat.netlify.app может вести на неактуальную версию.
Соберите проект локально:
npm run buildРезультат сборки попадает в dist/. Содержимое public/ (например, images/) копируется в dist/.
Раздавать можно вручную: содержимое dist/ подойдёт для любого статического хостинга (GitHub Pages, Vercel, nginx и т.д.).
- В репозитории: Settings → Pages.
- В блоке Build and deployment выберите Source: GitHub Actions.
- Ветка deploy: при каждом пуше в неё workflow
.github/workflows/deploy-pages.ymlзапускает сборку на GitHub (Node.js 22,npm ci,npm run build,BASE_PATH=/GilgaChat/) и публикует каталогdist/на GitHub Pages.
Сайт будет доступен по адресу вида https://<username>.github.io/<repo>/. Для SPA важно задать base в vite.config.ts равным '/<repo>/' (например, '/GilgaChat/'), иначе pathname-маршруты (/messenger, /settings, …) и статика будут отдаваться с неправильного пути.
Перезагрузка (F5) и тот же экран: в dev и vite preview запросы к вложенным путям переписываются на index.html (middleware в vite.config.ts). На GitHub Pages серверных rewrite нет: в dist кладётся 404.html — копия index.html. Для «виртуальных» URL вроде /GilgaChat/messenger хостинг отдаёт этот HTML (механизм платформы для «не найденного файла»), браузер загружает то же приложение, Router по location.pathname снова показывает нужный экран. Переходы по ссылкам и «Назад»/«Вперёд» — в клиенте (History API, setupSpaLinks).
Сделано: переход на FSD и Block, экран мессенджера с сайдбаром и выбором чата, ChatPage (лента, MessageComposer, отправка сообщений на клиенте), валидация форм входа / регистрации / редактирования профиля, страницы регистрации и профиля, 404/500, линтинг и соглашения по коду, роутинг по pathname (History API) с редиректами по сессии, редиректы и заголовки для Netlify, автодеплой на GitHub Pages из ветки deploy. Клиентский слой shared/lib/api (обёртка над HTTPTransport, модули authApi, chatsApi, userApi, тип ApiError) и связка с контроллерами приложения; пользовательские ошибки запросов — тосты (showErrorToast / ErrorToast).
Ближайший спринт: отправка сообщений в чате с использованием WebSocket (сейчас отправка реализована только на клиенте, без канала к серверу в реальном времени).
Дальше: восстановление пароля, доработка чата (загрузка ленты с сервера, вложения, поиск по чату), при необходимости — единый перехват ошибок, повтор запросов и более детальные сценарии ответов API.
Позже: расширение бэкенд-API и сценариев вокруг чата (по мере готовности сервера).
Проект создан в учебных целях и пока не содержит явной open-source лицензии.
Если планируете использовать его в продакшене или как основу для open-source проекта, добавьте файл лицензии (например, MIT) по своему выбору.