Skip to main content
Этот раздел описывает, как устроена платформа Exode изнутри: на каких технологиях она построена, как организован фронтенд, какие платформы поддерживаются и как приложение обменивается данными с сервером через GraphQL. Материал рассчитан на разработчиков и интеграторов, которые подключают внешние сервисы, пишут кастомный код или работают с API школы.
Для повседневной работы владельцу школы этот раздел не нужен — все настройки доступны в интерфейсе. Документация полезна, если вы интегрируете школу с внешними системами (CRM, аналитика, боты) или разрабатываете собственные скрипты.

Технологический стек

Клиентское приложение — это single-page application на React с полной типизацией и SSR-серверной частью.

Поддерживаемые платформы

Один и тот же код собирается под несколько платформ. Платформа определяется на этапе сборки и в рантайме. Определение платформы и окружения выполняется через сторы (ConfigStore.isDesktop, RouterStore.type) и компонент Platform.If. Продукт также разворачивается в двух режимах — открытый маркетплейс (MarketplacePlatform) и отдельная школа (SchoolPlatform).

Архитектура фронтенда

Код организован по доменам. Ключевые директории:

Как устроены страницы

Все страницы следуют единому шаблону на базе системы компонентов Page.*. Типичная страница разбита на файлы: сам компонент страницы, index.tsx (реэкспорт для ленивой загрузки), graphql.tsx (операции), store.tsx (стор страницы, если нужен) и папку views/ с под-компонентами.
  • Page.Wrapper — корневой контейнер: восстановление скролла, safe area, тема.
  • Page.Header / Page.MainHeader — заголовок страницы с кнопками действий.
  • Page.ContentPage.RowPage.Section — область контента.
  • Page.Context — правое контекстное меню (только на десктопе).

Маршрутизация

Маршрутизация построена на кастомном роутере (@exode-team/router). Маршруты описаны в src/router/routes/ и поддерживают:
  • URL-параметры: :id, :page([0-9]+);
  • регулярные выражения для валидации;
  • типы маршрутов: tab, modal, fullscreen, iframe.
Страницы подгружаются лениво через lazyWithRetry(() => import(...)). Для навигации используется компонент Link или программный вызов Router.pushPage(...).

Управление состоянием

Состояние хранится в MobX-сторах, сгруппированных по доменам (core, user, platform, preference). Сторы конкретных страниц лежат рядом со страницей (pages/**/store.tsx). Компоненты, читающие сторы, оборачиваются в observer().

GraphQL

Взаимодействие с сервером идёт через единый GraphQL-эндпоинт с помощью Apollo Client.
  • Схема — источник истины (schema.gql в корне проекта).
  • Операции описываются в graphql.tsx рядом со страницей или доменом.
  • Из операций генерируются типизированные хуки (useXxxQuery, useXxxMutation) командой yarn graphql:build.
  • Кэш обновляется вручную по паттерну readQuery → изменение → writeQuery с теми же переменными, с синхронным обновлением полей count, items, page/pages.
Эндпоинт задаётся переменной окружения REACT_APP_GRAPHQL_CSR_URL. Подробнее о внешних запросах, ключах и авторизации — в разделе API.
Если вам нужно расширить интерфейс без изменения кода платформы — используйте кастомный код, а для реакции на события школы — вебхуки.