Документация
Полное руководство по шаблону: от установки до production. Технические спеки в папке docs/ репозитория дополняют эту страницу.
Содержание
Быстрый стартСтруктура проектаПеременные окруженияБаза данныхАутентификацияПодписки и YooKassaAI-агентыАналитикаАдмин-панельТестированиеДеплойБлог (Velite)Справочник командБыстрый старт
Micro SaaS Starter — шаблон для запуска коммерческого веб-приложения на React Router 8, PostgreSQL, Better Auth, Mantine и YooKassa. Ниже — минимальный путь от клонирования до работающего dashboard.
Склонируйте репозиторий и выполните npm install
Скопируйте .env.example в .env и заполните DATABASE_URL и BETTER_AUTH_SECRET
Поднимите PostgreSQL и выполните npm run db:push
Запустите npm run dev и откройте http://localhost:5173
Зарегистрируйтесь через /auth/signup и откройте /dashboard
Для оплаты подключите тестовый магазин YooKassa (YOOKASSA_SHOP_ID, YOOKASSA_SECRET_KEY). Для AI-агентов — DEEPSEEK_API_KEY. Без этих ключей остальные части приложения работают: auth, демо-агенты, аналитика.
Структура проекта
Маршруты разделены на публичные (marketing) и защищённые (app). Публичные страницы — лендинг, блог, документация, privacy — живут под layout _marketing.tsx без проверки сессии. Всё внутри приложения — под _app.tsx с обязательной авторизацией.
Серверный код помечайте суффиксом .server.ts и импортируйте только из loaders, actions и других server-модулей. Клиентский бандл не должен тянуть подключение к БД или секреты.
Переменные окружения
Все секреты и URL задаются через .env. В production используйте переменные хостинга, не коммитьте .env в git.
APP_URL / BETTER_AUTH_URL должен совпадать с доменом, на котором открывают приложение. Иначе ссылки в письмах сброса пароля и redirect после оплаты будут неверными.
База данных
Схема описана в app/lib/db/schema.ts через Drizzle ORM: пользователи и сессии Better Auth, подписки, платежи, события аналитики, учёт запусков агентов, очередь pg-boss.
npm run db:push — синхронизация схемы в dev (быстро, без истории)
npm run db:generate — сгенерировать SQL-миграцию после изменения schema.ts
npm run db:migrate — применить миграции (production)
npm run db:studio — веб-UI для просмотра таблиц
Подключение централизовано в app/lib/db/db.server.ts. Для операций «списать квоту + записать usage» используйте db.transaction — это предотвращает race condition при параллельных запросах к агентам.
Аутентификация
Better Auth обрабатывает регистрацию, вход, сброс пароля и сессии в PostgreSQL. Конфигурация — app/lib/auth/auth.server.ts. API-эндпоинты — /api/auth/*.
Валидация форм — Zod-схемы в app/lib/validation/auth.schemas.ts. Защищённые маршруты проверяют сессию в loader _app.tsx. Админские страницы дополнительно сверяют email со списком ADMIN_EMAILS.
При успешном signup и login отправляются аналитические события signup_completed и login_completed, а анонимный visitorId связывается с userId (stitch).
Подписки и YooKassa
Тарифы описаны в app/lib/config/plans.ts: Daily (тест вебхуков), Pro и Enterprise с месячной и годовой оплатой. Цены, интервалы и agentRunsIncluded настраиваются в одном файле.
Пользователь выбирает план на /billing или /premium
Создаётся платёж в YooKassa, редирект на страницу оплаты
Webhook /api/yookassa/webhook подтверждает оплату и активирует подписку
Cron и loader проверяют expiresAt и инициируют продление
Для локальной отладки webhook используйте тестовый магазин YooKassa и проброс туннеля (ngrok) на localhost. В production принимайте webhook только с IP-адресов провайдера.
Страница /billing показывает текущий план, дату продления, историю платежей и остаток квоты агентов (AgentUsageMeter).
AI-агенты
Production-агенты доступны на /agents: support (поддержка, возвраты, KB) и incident (SRE on-call, расследование). Построены на Vercel AI SDK v7 с ToolLoopAgent и human-in-the-loop (toolApproval) для опасных действий.
Конфигурация — app/lib/ai/agents/config.ts
API — POST /api/agents/:slug (стриминг, учёт квоты)
Демо без списания квоты — /demo/:slug на mock-данных
Одобрение крупных возвратов и remediation — в UI чата
Каждый тариф включает agentRunsIncluded запусков за период подписки. Учёт в app/lib/usage/usage.server.ts: reserve → commit/release. При исчерпании квоты API возвращает 402 с предложением апгрейда.
Добавление своего агента: скопируйте support-agent.ts, определите инструменты с Zod-схемами, зарегистрируйте slug в config.ts.
Аналитика
First-party аналитика без сторонних скриптов. События пишутся в PostgreSQL через React Router instrumentation (сервер + клиент) и ручные track-вызовы.
Посетитель идентифицируется cookie analytics_vid и analytics_sid. После входа visitorId связывается с userId. Дашборд — /admin/analytics (DAU, воронка, топ страниц, журнал).
Песочница /analytics-sandbox — для отладки track() без искажения production-метрик. Подробнее: docs/analytics.md в репозитории.
Админ-панель
Раздел /admin доступен только пользователям из ADMIN_EMAILS. Включает сводку метрик, управление пользователями и аналитический дашборд.
Daily digest — email-отчёт админам за вчера (cron через pg-boss). Требует настроенный SMTP. Трафик админов исключён из аналитики, чтобы разработка не искажала метрики.
Тестирование
Перед PR прогоните npm run typecheck и npm run lint. Seed-данные для integration-тестов — tests/helpers/seed.ts. E2E использует TEST_BILLING_MOCK для мока оплаты без реальной YooKassa.
Деплой
npm run build && npm run start — production-сборка
Примените db:migrate на production БД (не db:push)
Зарегистрируйте webhook YooKassa на /api/yookassa/webhook
Убедитесь, что pg-boss workers стартуют (entry.server.tsx)
Настройте HTTPS, алерты на 5xx и бэкапы PostgreSQL
Staging: отдельный инстанс с тестовым магазином YooKassa. После выката пройдите smoke test: регистрация → оплата → сообщение агенту → проверка /admin/analytics.
Блог (Velite)
Статьи блога — Markdown (.md) и MDX (.mdx) в content/blog/. Velite собирает две коллекции (posts и postsMdx) в .velite/ с типами Post и PostMdx. Локальные картинки копируются в public/static/; для placeholder можно указать внешний URL.
Markdown: content/blog/my-post.md — content рендерится в HTML на этапе сборки
MDX: content/blog/my-post.mdx — code компилируется в React; компоненты вроде BlogCallout подключаются в BlogMdxContent
Опционально cover: https://… в frontmatter — обложка над текстом статьи
npm run content:build — пересобрать контент вручную
RSS, sitemap и prerender подхватывают .md и .mdx автоматически