Структура фронтенда
Структура проекта
Section titled “Структура проекта”frontend/├── public/│ └── locales/ # JSON файлы переводов (i18next)│ ├── en/│ └── ru/├── src/│ ├── app/ # Инициализация приложения│ │ ├── main.tsx│ │ ├── router.tsx # TanStack Router — все маршруты│ │ └── providers.tsx # QueryClient, i18n, Toaster и т.д.│ ││ ├── pages/ # Страницы (один файл = один маршрут)│ │ ├── landing/│ │ │ ├── index.tsx│ │ │ ├── sections/│ │ │ │ ├── Hero.tsx│ │ │ │ ├── Features.tsx│ │ │ │ ├── Pricing.tsx│ │ │ │ └── FAQ.tsx│ │ │ └── components/│ │ ├── auth/│ │ │ ├── login.tsx│ │ │ └── register.tsx│ │ ├── dashboard/│ │ │ ├── index.tsx # Обзор подписки│ │ │ ├── subscription.tsx # Детали + subscription link│ │ │ └── devices.tsx # Список устройств / сессий│ │ └── admin/│ │ ├── index.tsx # Dashboard с метриками│ │ ├── users/│ │ │ ├── index.tsx # Таблица пользователей│ │ │ └── [id].tsx # Детальная страница│ │ ├── nodes/│ │ │ ├── index.tsx│ │ │ └── [id].tsx│ │ ├── plans/│ │ │ └── index.tsx│ │ └── settings/│ │ └── index.tsx│ ││ ├── components/ # Переиспользуемые компоненты│ │ ├── ui/ # shadcn/ui компоненты (auto-generated)│ │ ├── layout/│ │ │ ├── DashboardLayout.tsx│ │ │ ├── AdminLayout.tsx│ │ │ └── LandingLayout.tsx│ │ └── shared/│ │ ├── TrafficChart.tsx│ │ ├── NodeStatusBadge.tsx│ │ ├── SubscriptionLinkCard.tsx│ │ └── DataTable.tsx # Переиспользуемая таблица с сортировкой│ ││ ├── api/ # API слой│ │ ├── client.ts # Axios instance + interceptors (refresh token)│ │ ├── auth.ts│ │ ├── users.ts│ │ ├── nodes.ts│ │ ├── plans.ts│ │ └── stats.ts│ ││ ├── hooks/ # Кастомные хуки (TanStack Query)│ │ ├── useAuth.ts│ │ ├── useNodes.ts│ │ ├── useSubscription.ts│ │ └── useRealtimeStats.ts # WebSocket хук│ ││ ├── store/ # Zustand stores│ │ ├── auth.store.ts│ │ └── ui.store.ts│ ││ ├── lib/ # Утилиты│ │ ├── utils.ts # cn(), formatBytes(), formatDate()│ │ └── constants.ts│ ││ └── types/ # TypeScript типы│ ├── api.ts # Типы ответов API│ └── models.ts # User, Node, Plan, Subscription...│├── index.html├── vite.config.ts├── tailwind.config.ts├── tsconfig.json└── package.jsonРоутинг
Section titled “Роутинг”TanStack Router с файловой структурой маршрутов. Защищённые маршруты через beforeLoad:
// Все /dashboard/* и /admin/* маршруты проверяют токен// /admin/* дополнительно проверяют role === 'admin'Маршруты
Section titled “Маршруты”| Путь | Компонент | Доступ |
|---|---|---|
/ |
LandingPage | Публичный |
/login |
LoginPage | Гость |
/register |
RegisterPage | Гость |
/dashboard |
DashboardOverview | Auth |
/dashboard/subscription |
SubscriptionPage | Auth |
/admin |
AdminDashboard | Admin |
/admin/users |
UsersPage | Admin |
/admin/users/:id |
UserDetailPage | Admin |
/admin/nodes |
NodesPage | Admin |
/admin/nodes/:id |
NodeDetailPage | Admin |
/admin/plans |
PlansPage | Admin |
/sub/:token |
— | Публичный (subscription endpoint) |
Auth flow
Section titled “Auth flow”1. POST /api/v1/auth/login → { access_token, refresh_token }2. access_token хранится в памяти (Zustand)3. refresh_token — в httpOnly cookie4. Axios interceptor: если 401 → POST /api/v1/auth/refresh → повторяет запрос5. При выходе → DELETE /api/v1/auth/logout (инвалидирует refresh в БД)Realtime метрики (WebSocket)
Section titled “Realtime метрики (WebSocket)”В AdminDashboard и NodeDetailPage подключается WebSocket:
ws://api/admin/ws/statsСервер пушит каждые 5 секунд JSON с текущими метриками по всем нодам. Хук useRealtimeStats обновляет локальный стейт, графики перерисовываются автоматически.
Subscription Link
Section titled “Subscription Link”Пользователь получает ссылку вида:
https://your-domain.com/sub/TOKENПри GET-запросе бэкенд генерирует и отдаёт application/x-www-form-urlencoded или base64 YAML — формат, который понимают все популярные VPN-клиенты.