Стек

Технологический стек, структура папок, деплой и особенности Next.js 16, на которые мы наступаем. Каверзы фреймворка — в mat-ucheniya/AGENTS.md.


Зависимости

ПакетВерсияРоль
next16.2.3App Router, server actions, unstable_cache
react / react-dom19.2.4UI
@supabase/supabase-js^2.103.0Клиент БД/Auth
@supabase/ssr^0.10.2SSR-хелперы (cookies, серверный клиент)
tailwindcss^4CSS-утилиты (v4, PostCSS-based)
@tailwindcss/typography^0.5.19Стили для markdown-контента
lucide-react^1.8.0Иконки
@fontsource-variable/manrope^5.2.8Основной шрифт (variable)
@fontsource-variable/jetbrains-mono^5.2.8Моноширинный (code/markdown)
react-markdown + remark-gfm^10.1 / ^4Рендеринг markdown в /docs
jose^6.2.3JWT-верификация для Telegram Mini App auth
vitest^4.1.5Тесты pure-helpers
tsx^4.19.2Запуск скриптов (scripts/*.ts)
aws4fetch^1.0.20Подпись запросов к R2 (бэкапы)

TypeScript strict включён. ESLint 9 с eslint-config-next.


Структура папок

mat-ucheniya/
├── app/                     # App Router: layouts, pages, server actions, API routes
│   ├── c/[slug]/            # Кампания: accounting, catalog, encounters, …
│   ├── tg/                  # Telegram Mini App (/tg)
│   ├── docs/[[...slug]]/    # Документация
│   ├── actions/             # Server actions (*.ts)
│   └── api/                 # Route handlers
├── components/              # React-компоненты
├── hooks/                   # Client hooks (use-form-draft.ts, …)
├── lib/                     # Чистые хелперы + Supabase-клиенты + queries
│   ├── __tests__/           # Vitest тесты
│   ├── supabase/            # admin.ts, server.ts, client.ts, proxy.ts
│   └── queries/             # Функции чтения из БД
├── scripts/                 # Seed/import/check скрипты (tsx)
├── supabase/
│   └── migrations/          # SQL-миграции (001–117+)
├── docs/                    # Документация (markdown, этот сайт)
├── proxy.ts                 # Auth proxy (Next.js 16: вместо middleware)
├── AGENTS.md                # Правила кода (обязательно читать)
├── STYLE.md                 # Дизайн-токены
└── vitest.config.ts

NPM-скрипты

СкриптЧто делает
npm run devNext.js dev server
npm run buildProduction build (= авторитетный type-check)
npm run typechecktsc --noEmit без сборки
npm run lintESLint
npm run testVitest (vitest run)
npm run seed-ownerСоздать owner-аккаунт
npm run seed-srdЗагрузить SRD-предметы
npm run seed-portraitsЗагрузить портреты PC
npm run import-electivesИмпорт факультативов

Server actions vs route handlers vs RPC

  • Server actions (app/actions/*.ts) — основной путь для мутаций из клиентских компонентов. Используют createAdminClient() (service role, RLS bypassed) и обязаны начинаться с auth-check (см. AGENTS.md).
  • Route handlers (app/api/*) — для внешних вызовов: Telegram webhooks, CLI-инвалидация сайдбара (/api/admin/invalidate-sidebar).
  • Postgres RPC (supabase.rpc(...)) — для сложных атомарных операций: loop-start setup, autogen-транзакции энкаунтера.
  • Прямые клиентские запросы — только read-only через lib/queries/; RLS защищает их по role из JWT.

Деплой

Прод — self-hosted на Hetzner (CPX32, Helsinki). Хостится через Dokploy: PR в main → CI gate → Dokploy строит Docker-образ прямо на боксе → деплой. Self-hosted Supabase: API db.theloopers.org, Studio только через SSH-туннель, порт 5432 закрыт наружу.

Staging — ветка staginghttps://staging.theloopers.org, облачная Supabase-копия прода. Staging можно ломать свободно — он для проверки перед PR.

Детали — process/git-and-staging.md.


Особенности Next.js 16

proxy.ts вместо middleware.ts — в Next.js 16 auth-proxy называется proxy.ts и экспортирует функцию proxy (не middleware). Файл лежит в mat-ucheniya/proxy.ts. Логика: refresh Supabase-cookie, редирект неаутентифицированных с /c/* на /login, редирект must_change_password/onboarding, запись cookie current_campaign_slug. Реализация сессионного обновления — lib/supabase/proxy.ts.

revalidateTag(tag, 'max') — второй аргумент (cache profile) обязателен при инвалидации unstable_cache; без него тег не сбрасывается. Подробнее — sidebar-cache.md.

Полный список каверзов — mat-ucheniya/AGENTS.md, раздел «This is NOT the Next.js you know».