Skip to content

Архитектура Worker24

Worker24 — веб-приложение для изучения испанского языка, ориентированное на русскоязычных пользователей. Пользователи просматривают каталог учебных карточек, изучают фразы в интерактивном режиме, отслеживают прогресс и создают/редактируют карточки с помощью AI-ассистента.

Документ описывает текущую реализацию: стек, структуру репозитория, потоки данных, модель данных, аутентификацию, AI-интеграции и деплой.


  1. Обзор системы
  2. Технологический стек
  3. Структура репозитория
  4. Архитектура фронтенда
  5. Архитектура бэкенда
  6. Модель данных
  7. Аутентификация и авторизация
  8. Каталог карточек и гостевой режим
  9. AI-редактор карточек
  10. Синхронизация прогресса и настроек
  11. Внешние интеграции
  12. Инфраструктура и деплой
  13. Режимы разработки
  14. Ограничения и архитектурные решения

flowchart TB
    subgraph Client["Браузер (React SPA)"]
        UI[Страницы и виджеты]
        State[Zustand + TanStack Query]
        AuthClient[Supabase Auth Client]
        UI --> State
        State --> AuthClient
    end

    subgraph Railway["Railway"]
        API[Hono API :3001]
        Static[Статика Vite :PORT]
    end

    subgraph Supabase["Supabase (внешний)"]
        PG[(PostgreSQL)]
        Auth[Auth + JWKS]
        Storage[Storage Buckets]
    end

    subgraph OpenAI["OpenAI API"]
        Chat[gpt-4o-mini]
        Image[gpt-image-1]
        STT[gpt-4o-transcribe]
    end

    Client -->|REST + SSE| API
    Client -->|JWT login| Auth
    API -->|Prisma| PG
    API -->|Admin API| Auth
    API -->|Upload| Storage
    API --> Chat
    API --> Image
    API --> STT
    Static --> Client

Основные пользовательские сценарии

Section titled “Основные пользовательские сценарии”
Сценарий Маршрут Описание
Каталог / Бесконечная прокрутка карточек, фильтры, поиск, прогресс-бар
Изучение /card/:id Оверлей с разбором фразы, примерами, практикой и AI-чатом
Создание /create Новая карточка через AI-чат
Вход /login Регистрация и авторизация
Настройки /settings Тема, язык интерфейса, аккаунт

Два пакета, один продукт

Section titled “Два пакета, один продукт”

Репозиторий не является npm-workspace монорепо. Корневой package.json оркестрирует фронтенд и бэкенд через префиксные скрипты (npm run server:dev, npm run dev:all).

graph LR
    Root["/ (worker24)"] --> FE["src/ — React SPA"]
    Root --> BE["server/ — Hono API"]
    Root --> Docs["docs/"]
    BE --> Prisma["server/prisma/"]

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

Section titled “2. Технологический стек”
Категория Технология Назначение
UI React 19 Компонентная модель
Сборка Vite 8 Dev-сервер, HMR, production build
Маршрутизация React Router 7 SPA-роутинг
Серверное состояние TanStack Query 5 Кэш карточек, infinite scroll
Клиентское состояние Zustand 5 (+ persist) Auth, прогресс, настройки
Стили Tailwind CSS 4 + shadcn/ui UI-компоненты
i18n Собственный реестр ru / en / es
AI-чат Vercel AI SDK (@ai-sdk/react) Стриминг чата редактора
Auth @supabase/supabase-js Сессии, JWT
Тесты Vitest + Testing Library Unit-тесты
Категория Технология Назначение
HTTP Hono 4 REST API, CORS, middleware
Runtime Node.js 20+ @hono/node-server
ORM Prisma 6 Схема, миграции, запросы
Auth verify jose JWT через Supabase JWKS
AI Vercel AI SDK + @ai-sdk/openai Чат, tools, изображения, STT
Dev tooling Mastra Агент для локальной разработки (не prod)
Компонент Провайдер
База данных Supabase PostgreSQL
Аутентификация Supabase Auth
Файлы Supabase Storage
Хостинг API + SPA Railway (2 сервиса)
LLM / STT / Image OpenAI

3. Структура репозитория

Section titled “3. Структура репозитория”
WORKER24/
├── src/ # Фронтенд (React SPA)
│ ├── app/ # Bootstrap: router, providers, auth/theme/locale sync
│ ├── pages/ # Страницы маршрутов
│ ├── widgets/ # Составные UI-блоки (TopBar, FilterBar, …)
│ ├── features/ # Фичи: auth, card-creator, progress, settings, …
│ ├── entities/ # Домен «карточка»: api, hooks, model, ui, lib
│ ├── shared/ # api client, i18n, theme, config, ui
│ ├── components/ # shadcn/ui + json-render renderer
│ ├── lib/ # json-render catalog/registry
│ └── data/ # Mock-данные каталога (только mock-режим)
├── server/ # Бэкенд API
│ ├── src/
│ │ ├── index.ts # Точка входа Hono
│ │ ├── routes/ # REST-модули
│ │ ├── middleware/ # Auth, resolveCatalogUser
│ │ ├── lib/ # Auth, Prisma, catalog, AI, storage
│ │ └── mastra/ # Mastra-агент (dev)
│ └── prisma/ # schema, migrations, seed
├── docs/ # Документация (этот файл, RAILWAY.md)
├── dist/ # Vite build output
├── index.html # SPA shell
├── vite.config.ts # Proxy /api → localhost:3001
├── railway.toml # Конфиг фронтенд-сервиса
└── package.json # Корневые скрипты

Слои фронтенда (Feature-Sliced Design)

Section titled “Слои фронтенда (Feature-Sliced Design)”
flowchart TB
    subgraph Pages["pages/"]
        CatalogPage
        StudyPage
        CreatorPage
    end

    subgraph Widgets["widgets/"]
        TopBar
        FilterBar
        CatalogTopActions
    end

    subgraph Features["features/"]
        Auth
        CardCreator
        Progress
        Settings
        CardFilter
        StudyMode
    end

    subgraph Entities["entities/"]
        Card["card (api, hooks, model, ui)"]
    end

    subgraph Shared["shared/"]
        ApiClient
        I18n
        Theme
        Config
    end

    Pages --> Widgets
    Pages --> Features
    Widgets --> Features
    Features --> Entities
    Features --> Shared
    Entities --> Shared

Правило зависимостей: слой может импортировать только из слоёв ниже себя (pageswidgetsfeaturesentitiesshared).


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

Section titled “4. Архитектура фронтенда”
sequenceDiagram
    participant main as main.tsx
    participant App as App.tsx
    participant Providers as AppProviders
    participant Router as RouterProvider

    main->>App: render
    App->>Providers: QueryClientProvider
    App->>App: ThemeSync
    App->>App: LocaleSync
    App->>App: AuthBootstrap
    App->>Router: маршруты

Файлы:

  • src/main.tsx — монтирование React
  • src/app/App.tsx — композиция провайдеров
  • src/app/router.tsx — маршруты
  • src/app/AuthBootstrap.tsx — инициализация Supabase-сессии
Path Компонент Особенности
/ CatalogPage Infinite scroll, фильтры, восстановление скролла
/card/:id StudyPage Оверлей CardEditorOverlay, AI-чат в режиме edit
/create CreatorPage AI-чат в режиме create
/login LoginPage signIn / signUp
/settings SettingsPage Тема, locale, аккаунт
flowchart LR
    subgraph ServerState["Серверное состояние"]
        TQ[TanStack Query]
        Cards["cardApi.getAll / getById / getTags"]
        TQ --> Cards
    end

    subgraph ClientState["Клиентское состояние (Zustand)"]
        AuthStore["authStore — token, user"]
        ProgressStore["progressStore — completedCardIds"]
        SettingsStore["settingsStore — theme, locale"]
    end

    subgraph Ephemeral["Эфемерное (React state)"]
        CreatorDraft["creatorDraft — черновик AI"]
        ChatMessages["messages — история чата"]
    end

    AuthStore -->|Bearer JWT| Cards
    ProgressStore -->|sync| API
    SettingsStore -->|sync| API
Concern Хранилище Персистентность
Сессия authStore В памяти (+ Supabase session)
Каталог карточек TanStack Query In-memory cache
Прогресс progressStore localStorage + API sync
Настройки settingsStore localStorage + API sync
Черновик редактора React useState Только в сессии

Repository pattern для карточек

Section titled “Repository pattern для карточек”

src/entities/card/api/cardApi.ts выбирает реализацию по режиму:

const repository = env.useMockData ? mockCardRepository : httpCardRepository;
  • Mock: данные из src/data/ (in-memory)
  • Live: HTTP-запросы через src/shared/api/client.ts с Authorization: Bearer

src/shared/api/client.ts — обёртка над fetch:

  • Базовый URL из VITE_API_URL
  • Автоматическая подстановка JWT из authStore
  • Единая обработка ошибок

Конфигурация окружения

Section titled “Конфигурация окружения”

src/shared/config/env.ts:

Переменная Значение по умолчанию Эффект
VITE_USE_MOCK_DATA true (если не "false") Mock-режим
VITE_API_URL "" URL бэкенда
VITE_SUPABASE_URL "" Supabase project URL
VITE_SUPABASE_ANON_KEY "" Публичный anon key

isApiEnabled = useMockData === false && apiUrl задан


server/src/index.ts — единый Hono-приложение:

flowchart TB
    Index["index.ts"] --> CORS
    CORS --> Health["GET /health"]
    CORS --> Auth["/auth"]
    CORS --> Cards["/cards"]
    CORS --> Creator["/creator"]
    CORS --> Progress["/users/me/progress"]
    CORS --> Profile["/users/me/profile"]
    CORS --> Settings["/users/me/settings"]

    Index --> Startup["ensureGuestCatalog()"]

При старте асинхронно вызывается ensureGuestCatalog() — гарантирует наличие системного гостевого каталога.

Mount Файл Auth Описание
GET /health index.ts Health check
POST /auth/register routes/auth.ts Регистрация через Supabase Admin
GET /cards routes/cards.ts Опционально Список карточек (пагинация, поиск, теги)
GET /cards/:id routes/cards.ts Опционально Одна карточка
GET /cards/tags routes/cards.ts Опционально Теги и счётчики
GET /cards/:id/practice-choices routes/cards.ts Опционально Варианты для практики
POST /creator/chat routes/creator.ts AI-чат (SSE stream)
POST /creator/transcribe routes/creator.ts Голос → текст
GET /users/me/progress routes/progress.ts Обязательно Список завершённых карточек
POST /users/me/progress/:cardId routes/progress.ts Обязательно Отметить карточку
PUT /users/me/progress routes/progress.ts Обязательно Bulk sync
GET /users/me/profile routes/profile.ts Обязательно Профиль
PUT /users/me/profile routes/profile.ts Обязательно Обновление + аватар
GET /users/me/settings routes/settings.ts Обязательно Настройки
PUT /users/me/settings routes/settings.ts Обязательно Обновление настроек
flowchart TD
    Request["HTTP Request"] --> MW{Middleware}

    MW -->|"/cards/*"| ResolveCatalog["resolveCatalogUser"]
    ResolveCatalog -->|Bearer JWT valid| AuthUser["userId = claims.sub"]
    ResolveCatalog -->|No token / invalid| GuestUser["userId = GUEST_USER_ID"]

    MW -->|"/users/me/*"| RequireAuth["requireAuth"]
    RequireAuth -->|JWT valid| AuthUser2["userId = claims.sub"]
    RequireAuth -->|Invalid| Error401["401 Unauthorized"]

    MW -->|"/creator/*"| NoAuth["Без auth middleware"]

resolveCatalogUser (server/src/middleware/resolveCatalogUser.ts):

  • С JWT → верификация + ensureUserProfile + личный каталог
  • Без JWT → гостевой userId

requireAuth (server/src/middleware/requireAuth.ts):

  • Строгая проверка JWT для персональных данных
Модуль Назначение
auth.ts JWT verify (JWKS), upsert профиля, клонирование каталога
prisma.ts Singleton Prisma Client
supabase.ts Admin client для регистрации и Storage
guestUser.ts Системный гостевой пользователь
catalogSeeder.ts Seed и clone каталога
catalog/ Базовые карточки + generated topics (~2350 шт.)
cardQueries.ts Поиск (pg_trgm), фильтры, пагинация
creatorSystemPrompt.ts System prompt для AI
creatorDraftSchema.ts Zod-схема патча черновика
generateCardImage.ts OpenAI Images API
creatorImageStorage.ts Upload в Supabase Storage
avatarImageStorage.ts Upload аватаров
transcribeAudio.ts OpenAI STT
corsOrigins.ts CORS whitelist

erDiagram
    User ||--o{ Card : owns
    User ||--o{ Tag : owns
    User ||--o{ UserProgress : tracks
    User ||--o| UserSettings : has
    Card ||--o{ CardTag : has
    Tag ||--o{ CardTag : labels
    Card ||--o{ UserProgress : completed_in

    User {
        string id PK "Supabase UUID"
        string email UK
        string name
        string avatar_url
        datetime created_at
    }

    Card {
        int id PK
        string user_id FK
        string title
        string subtitle
        string level
        string time
        string category
        string phrase
        string translation
        text note
        string image_url
        datetime created_at
    }

    Tag {
        int id PK
        string user_id FK
        string name
    }

    CardTag {
        int card_id PK,FK
        int tag_id PK,FK
    }

    UserProgress {
        string user_id PK,FK
        int card_id PK,FK
        datetime completed_at
    }

    UserSettings {
        string user_id PK,FK
        string theme
        string locale
    }

Схема: server/prisma/schema.prisma

  1. User.id = UUID из Supabase Auth (не auto-increment)
  2. Карточки и теги привязаны к userId — у каждого пользователя свой каталог
  3. Пароли не хранятся в Prisma (удалены в миграции 20250623120000)
  4. Поиск — GIN-индексы pg_trgm на title, phrase, translation (миграция 20250625140000)
URL Порт Назначение
DATABASE_URL 6543 (transaction pooler) Runtime API
DIRECT_URL 5432 (session pooler) Prisma migrations

RLS-политики в репозитории не определены — авторизация на уровне приложения (фильтрация по userId в запросах).


7. Аутентификация и авторизация

Section titled “7. Аутентификация и авторизация”
sequenceDiagram
    participant Browser
    participant Supabase as Supabase Auth
    participant API as Hono API
    participant DB as PostgreSQL

    Browser->>API: POST /auth/register {email, password, name}
    API->>Supabase: admin.createUser()
    API->>DB: ensureUserProfile(sub, email)
    API->>DB: ensureUserCatalogFromGuest(guest → new user)
    API-->>Browser: { ok: true }
    Browser->>Supabase: signInWithPassword()
    Supabase-->>Browser: access_token (JWT)
    Browser->>API: GET /cards (Authorization: Bearer)
    API->>API: verifySupabaseToken(JWKS)
    API->>DB: cards WHERE user_id = sub
sequenceDiagram
    participant Browser
    participant Supabase as Supabase Auth
    participant API as Hono API

    Browser->>Supabase: signInWithPassword()
    Supabase-->>Browser: session.access_token
    Browser->>Browser: authStore.set(token, user)
    Browser->>API: GET /users/me/profile
    API->>API: JWT verify + ensureUserProfile
    API-->>Browser: { user }
    Browser->>Browser: mergeAndSyncProgress()
    Browser->>Browser: mergeAndSyncSettings()

Верификация JWT на сервере

Section titled “Верификация JWT на сервере”

server/src/lib/auth.ts:

  1. Загрузка JWKS с {SUPABASE_URL}/auth/v1/.well-known/jwks.json
  2. Проверка через jose.jwtVerify (issuer + audience "authenticated")
  3. Upsert User + UserSettings в Prisma
  4. При первом входе — клонирование гостевого каталога
Ресурс Гость Авторизованный
Каталог /cards Общий гостевой каталог Личная копия каталога
Прогресс Только localStorage localStorage + сервер
Настройки Только localStorage localStorage + сервер
Профиль / аватар Только свой
Creator /creator Доступен всем Доступен всем
Переменная Где Экспозиция
VITE_SUPABASE_ANON_KEY Frontend build Публичная (by design)
SUPABASE_SERVICE_ROLE_KEY Server only Никогда на клиент
OPENAI_API_KEY Server only Только серверные вызовы
DATABASE_URL Server only Prisma connection

8. Каталог карточек и гостевой режим

Section titled “8. Каталог карточек и гостевой режим”

Системный пользователь без Supabase-аккаунта:

GUEST_USER_ID = "00000000-0000-4000-8000-000000000001"

Файл: server/src/lib/guestUser.ts

flowchart LR
    Seed["catalogSeeder"] --> GuestCatalog["Гостевой каталог<br/>~2350 карточек"]
    GuestCatalog --> GuestUser["GUEST_USER_ID"]
    GuestUser -->|Без JWT| Anonymous["Анонимный браузер"]
    GuestUser -->|При регистрации| Clone["cloneUserCatalog"]
    Clone --> NewUser["Новый пользователь"]

Источники данных каталога

Section titled “Источники данных каталога”
Расположение Когда используется
server/src/lib/catalog/ Production API, seed, Railway
src/data/ Mock-режим фронтенда

Данные дублируются намеренно: API-сервис на Railway собирается независимо от фронтенда (docs/RAILWAY.md).

Состав каталога:

  • base-cards.ts — базовые карточки с Unsplash-изображениями
  • generated-topics.ts — сгенерированные темы
  • buildCardCatalog.ts — сборка полного каталога

Размер по умолчанию: TOTAL_CARDS = 2350 (src/shared/config/constants.ts). Для нагрузочного тестирования: SEED_TOTAL_CARDS=15000.

sequenceDiagram
    participant Browser
    participant API
    participant DB

    Browser->>API: GET /cards?q=...&tags=...&page=1&limit=25
    API->>API: resolveCatalogUser → userId
    API->>DB: card.findMany(WHERE user_id, ILIKE search, tags)
    DB-->>API: cards + total
    API-->>Browser: { items, total, page, limit }

Поиск: ILIKE + pg_trgm GIN-индексы (server/src/lib/cardQueries.ts).


Редактор карточек — центральная AI-фича. Поддерживает:

  • Текстовый чат с ассистентом (русский UI, испанский контент)
  • Tool calls для обновления черновика
  • Генерацию иллюстраций
  • Голосовой ввод (STT)

Важно: черновики AI не сохраняются в базу данных. Сохранение новых карточек через API пока не реализовано.

sequenceDiagram
    participant UI as CreatorChat
    participant Hook as useCardEditorChat
    participant API as POST /creator/chat
    participant OpenAI
    participant Storage as Supabase Storage

    UI->>Hook: handleSubmit(message)
    Hook->>API: { messages, draft, mode }
    API->>OpenAI: streamText(gpt-4o-mini, tools)

    alt updateCardDraft tool
        OpenAI-->>API: tool call
        API-->>Hook: SSE data-draft { patch }
        Hook->>Hook: mergeCreatorDraft()
    end

    alt generateCardImage tool
        OpenAI-->>API: tool call
        API-->>Hook: SSE data-image-status: generating
        API->>OpenAI: Images API
        API->>Storage: upload (или data URL)
        API-->>Hook: SSE data-image + data-draft { image }
        API-->>Hook: SSE data-image-status: idle
    end

    OpenAI-->>Hook: text stream (assistant message)
Tool Схема Действие
updateCardDraft creatorDraftPatchSchema Патч текстовых полей → data-draft SSE
generateCardImage generateCardImageInputSchema OpenAI image → Storage → data-image SSE

Файлы:

  • server/src/routes/creator.ts — эндпоинты
  • server/src/lib/creatorSystemPrompt.ts — system prompt
  • src/features/card-creator/lib/useCardEditorChat.ts — фронтенд-хук
  • src/features/card-creator/lib/mergeCreatorDraft.ts — слияние патчей
sequenceDiagram
    participant Browser
    participant API as POST /creator/transcribe
    participant OpenAI

    Browser->>Browser: MediaRecorder → audio blob
    Browser->>API: multipart/form-data (audio file)
    API->>OpenAI: transcription (gpt-4o-transcribe)
    OpenAI-->>API: text
    API-->>Browser: { text }
    Browser->>Browser: append to chat input

Лимит: 25 MB (MAX_TRANSCRIBE_BYTES).

flowchart LR
    subgraph Production["Production path"]
        HonoCreator["Hono /creator/chat"]
        AISDK["Vercel AI SDK"]
        HonoCreator --> AISDK
    end

    subgraph DevOnly["Dev tooling"]
        MastraServer["mastra dev :4111"]
        CardAgent["cardCreatorAgent"]
        MastraServer --> CardAgent
    end

    HonoCreator -.->|не связан| MastraServer

Mastra-агент (server/src/mastra/) не подключён к production-роутам. Запуск: npm run mastra:dev.

Инфраструктура для AI-генерируемого UI (@json-render/*):

  • src/lib/json-render/catalog.ts
  • src/lib/json-render/registry.tsx
  • src/components/json-render/GenerativeUiRenderer.tsx

GenerativeUiRenderer не используется ни на одной странице — подготовленная, но неактивная возможность.


10. Синхронизация прогресса и настроек

Section titled “10. Синхронизация прогресса и настроек”
stateDiagram-v2
    [*] --> LocalOnly: Гость / mock
    [*] --> LocalAndRemote: Авторизованный

    LocalOnly: Zustand persist (localStorage)
    LocalAndRemote: localStorage + API

    LocalAndRemote --> MergeOnLogin: mergeAndSyncProgress()
    MergeOnLogin: union(local, remote) → PUT /users/me/progress

    LocalAndRemote --> MarkComplete: POST /users/me/progress/:cardId

Файлы:

  • src/features/progress/model/progressStore.ts
  • src/features/progress/lib/progressSync.ts
  • server/src/routes/progress.ts

Аналогичная схема:

  1. Локально в Zustand + localStorage (worker24-settings)
  2. При логине: mergeAndSyncSettings() — загрузка с сервера
  3. При изменении: syncSettingsToServer()PUT /users/me/settings

Темы определены в src/shared/theme/definitions.ts. Locale: ru (default), en, es.


flowchart TB
    subgraph Worker24
        FE[Frontend]
        API[API]
    end

    subgraph Supabase
        Auth[Auth]
        PG[(PostgreSQL)]
        Storage[Storage]
    end

    subgraph OpenAI
        ChatAPI[Chat Completions]
        ImageAPI[Images API]
        STTAPI[Transcription]
    end

    subgraph External
        Unsplash[Unsplash URLs]
    end

    FE -->|signIn/signUp| Auth
    API -->|Admin API| Auth
    API -->|Prisma| PG
    API -->|Upload| Storage
    API --> ChatAPI
    API --> ImageAPI
    API --> STTAPI
    Seed[Seed data] -.->|image URLs| Unsplash
Сервис Использование Ключевые файлы
Supabase Auth Login, JWT, регистрация src/shared/lib/supabase.ts, server/src/lib/supabase.ts
Supabase PostgreSQL Все данные server/prisma/schema.prisma
Supabase Storage Аватары, AI-изображения creatorImageStorage.ts, avatarImageStorage.ts
OpenAI Chat AI-ассистент карточек server/src/routes/creator.ts
OpenAI Images Иллюстрации карточек server/src/lib/generateCardImage.ts
OpenAI STT Голосовой ввод server/src/lib/transcribeAudio.ts
Unsplash URL в seed-данных server/src/lib/catalog/base-cards.ts

Вебхуки, платёжные системы, email-сервисы и аналитика не используются.


12. Инфраструктура и деплой

Section titled “12. Инфраструктура и деплой”
flowchart TB
    subgraph Railway
        subgraph APIService["API Service (server/)"]
            Build1["npm install && npm run build"]
            Start1["prisma migrate deploy && node dist/index.js"]
            Health1["GET /health"]
        end

        subgraph WebService["Frontend Service (root)"]
            Build2["npm install && npm run build"]
            Start2["npx serve dist -s -l $PORT"]
            Health2["GET /"]
        end
    end

    subgraph External
        Supabase[(Supabase)]
        OpenAI[OpenAI]
    end

    User((Пользователь)) --> WebService
    WebService -->|VITE_API_URL| APIService
    APIService --> Supabase
    APIService --> OpenAI

Конфигурация:

  • server/railway.toml — API
  • railway.toml — Frontend
  • docs/RAILWAY.md — пошаговая инструкция

Frontend (bake-time, Vite):

Переменная Обязательна (prod)
VITE_USE_MOCK_DATA false
VITE_API_URL URL API-сервиса
VITE_SUPABASE_URL Да
VITE_SUPABASE_ANON_KEY Да

Backend (server/.env.example):

Переменная Обязательна
DATABASE_URL Да
DIRECT_URL Да
SUPABASE_URL Да
SUPABASE_SERVICE_ROLE_KEY Да
OPENAI_API_KEY Да (для creator)
CORS_ORIGIN Да (prod)
CREATOR_IMAGE_BUCKET Опционально
AVATAR_IMAGE_BUCKET Опционально
Terminal window
# Оба сервиса параллельно
npm run dev:all
# Или раздельно:
cd server && npm run dev # API :3001
npm run dev # Vite :5173, proxy /api → :3001
# Первичная настройка БД
npm run db:setup

Vite proxy (vite.config.ts):

/api/* → http://localhost:3001/* (rewrite убирает /api)

Автоматических пайплайнов (.github/workflows) в репозитории нет. Тестирование — локально через npm test (Vitest).


flowchart TD
    Env["VITE_USE_MOCK_DATA"]

    Env -->|не равно false| Mock["Mock Mode"]
    Env -->|false и задан API URL| Live["Live Mode"]

    Mock --> MockRepo["mockCardRepository"]
    Mock --> MockData["Локальные данные src/data"]
    Mock --> NoAPI["Без API и Supabase"]

    Live --> HttpRepo["httpCardRepository"]
    Live --> API["Hono API"]
    Live --> SupabaseAuth["Supabase Auth"]
Аспект Mock Mode Live Mode
Каталог src/data/ in-memory API + PostgreSQL
Auth Опционально (Supabase) Supabase + JWT
Прогресс Только localStorage localStorage + sync
AI Creator Работает (нужен API) Полный стек
Запуск Только npm run dev npm run dev:all + .env

14. Ограничения и архитектурные решения

Section titled “14. Ограничения и архитектурные решения”
Решение Обоснование
Supabase Auth + Prisma ORM Auth делегирован Supabase; данные через Prisma без RLS
Гостевой каталог Полный UX без регистрации; auth даёт личную копию
Per-user catalog clone Изоляция данных; каждый пользователь владеет своими карточками
Дублирование seed-данных Независимая сборка API на Railway
Vercel AI SDK (не Mastra) в prod Прямой контроль над стримингом и tools в Hono
Zustand persist + API sync Офлайн-прогресс для гостей; merge при логине
Ограничение Статус
AI-черновики не сохраняются в БД Нет POST /cards
json-render не используется в UI Инфраструктура готова
Mastra не в production Только mastra dev
Нет CI/CD Ручной деплой на Railway
Нет backend-тестов Только frontend Vitest
Cross-package import в seed seedConfig.ts импортирует TOTAL_CARDS из src/

Диаграмма зрелости компонентов

Section titled “Диаграмма зрелости компонентов”
quadrantChart
    title Зрелость компонентов
    x-axis Низкая интеграция --> Высокая интеграция
    y-axis MVP --> Production-ready
    quadrant-1 Зрелые core-фичи
    quadrant-2 Требуют доработки
    quadrant-3 Эксперименты
    quadrant-4 Инфраструктура

    Каталог: [0.85, 0.9]
    Auth: [0.8, 0.85]
    Прогресс: [0.75, 0.8]
    AI Creator: [0.7, 0.75]
    Настройки: [0.7, 0.8]
    json-render: [0.1, 0.2]
    Mastra: [0.15, 0.25]
    CI/CD: [0.2, 0.3]
    Save Card API: [0.0, 0.1]

  • Деплой на Railway
  • Prisma-схема: server/prisma/schema.prisma
  • Примеры env: .env.example, server/.env.example

Документ актуален для версии 0.1.0. При изменении архитектуры обновляйте соответствующие разделы и диаграммы.