CarPool - mobile-first MVP сервиса совместных поездок для повторяющихся маршрутов по Бишкеку.
Текущее продуктовое описание зафиксировано в docs/mvp.md.
- водитель создает запланированную поездку
- пассажир находит поездку и бронирует место
- водитель подтверждает или отклоняет бронь
- обе стороны получают уведомления по email и в Telegram
- после завершения поездки обе стороны могут оставить отзыв
Маршрут в MVP задается водителем как точка A и точка B на карте. Интерфейс показывает между ними простую линию, без live tracking и без сложного matching по геометрии дороги.
Первая версия не включает онлайн-оплату, live tracking, нативные мобильные приложения и сложный matching по геометрии маршрута.
- весь пользовательский интерфейс должен быть на русском языке
- статусы, ошибки, email и Telegram-уведомления тоже должны быть на русском
- код, Prisma-модели, названия сущностей и технические идентификаторы остаются на английском
- базовый словарь пользовательских текстов лежит в
src/lib/content/ru.ts
next-authс JWT-сессией; вjwt-колбэке пользователь находится/создаётся в нашей таблицеUserпо email, так что и Google, и dev-вход мапятся на одну запись- Google sign-in — основной (продакшн) способ. Появляется на странице входа, когда заданы
GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET - Email-вход (по email + имя) остаётся как dev-фолбэк и доступен только при
NODE_ENV !== production— удобно тестировать без OAuth - заблокированные/ограниченные пользователи (
UserStatus) не пускаются вsignIn-колбэке - после первого входа — onboarding профиля
- Google Cloud Console → APIs & Services → Credentials → Create OAuth client ID → тип Web application.
- Authorized redirect URI:
<NEXTAUTH_URL>/api/auth/callback/google(локально —http://localhost:3000/api/auth/callback/google). - Скопируй Client ID/Secret в
.env(GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET), перезапусти dev-сервер.
- Next.js 16 с App Router и TypeScript
- Prisma ORM
- PostgreSQL
- Tailwind CSS
- Mapbox для точки A, точки B и базовой линии маршрута
- Telegram Bot API и email для уведомлений
- Vercel и managed Postgres для деплоя
- Скопируй
.env.exampleв.env. - Укажи корректный
DATABASE_URL. - Добавь
NEXTAUTH_URLиNEXTAUTH_SECRET. - Установи зависимости через
npm install. - Сгенерируй Prisma client командой
npm run prisma:generate. - Запусти приложение через
npm run dev.
Поднять весь локальный стек:
npm run docker:upЕсли нужна только PostgreSQL для Prisma или DBeaver:
npm run docker:dbПосле запуска доступны:
- приложение Next.js на
http://localhost:3000 - PostgreSQL на
localhost:5432
Полезные команды:
npm run docker:logsдля просмотра логов контейнеровnpm run docker:downдля остановки стека
При первом npm run docker:up контейнер app установит npm-зависимости внутри Docker volume, поэтому первый старт может занять больше времени.
Если package-lock.json изменился или внутри volume не хватает пакета вроде next-auth, dev-контейнер автоматически выполнит npm ci повторно и обновит зависимости.
Параметры PostgreSQL для DBeaver:
- host:
localhost - port:
5432 - database:
carpool - user:
postgres - password:
postgres
npm run devзапускает development servernpm run lintзапускает ESLintnpm run prisma:generateпересобирает Prisma clientnpm run db:pushприменяет текущую Prisma schema к базеnpm run db:studioоткрывает Prisma Studio
Уведомления пишутся в БД всегда и видны во вкладке «Уведомления». Внешняя доставка включается, когда заданы переменные окружения; без них всё работает как in-app лента.
Доставка выбирается на пользователя: если он привязал Telegram — шлём в Telegram, иначе fallback на email (Resend). Бот может писать только тем, кто сам нажал Start, поэтому привязка идёт через одноразовый токен.
Настройка бота:
-
Создай бота у @BotFather, получи token и username.
-
Заполни
.env:TELEGRAM_BOT_TOKEN,TELEGRAM_BOT_USERNAME,TELEGRAM_WEBHOOK_SECRET. -
Подними публичный URL (прод-домен или
ngrok http 3000локально). -
Зарегистрируй вебхук (одноразово):
curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/setWebhook" \ -d "url=https://<твой-домен>/api/telegram/webhook" \ -d "secret_token=$TELEGRAM_WEBHOOK_SECRET"
-
В приложении: «Кабинет» → «Подключить Telegram» → откроется бот → Start. После этого
chat_idсохранится и уведомления пойдут в Telegram.
Сделано:
- Auth (next-auth, JWT): Google sign-in + dev-фолбэк по email, блок неактивных
- Google OAuth настроен локально (
.env+ redirect URI) - Профиль пользователя и onboarding
- Профиль водителя и машина
- Создание поездки (с картой), список и фильтры, страница поездки
- Бронирование, подтверждение/отклонение водителем
- Отмена брони, отмена поездки, завершение поездки
- «Мои поездки» и «Мои брони»
- Отзывы и рейтинг водителя
- Уведомления: in-app лента + бейдж, email (Resend), Telegram-бот
- Напоминания о выезде (Vercel Cron)
- Базовая админка (пользователи, поездки, жалобы) + жалобы от пользователей
- Уникальность контактов (
@unique) восстановлена, дубли почищены - Observability: Sentry (ошибки) + PostHog (аналитика) — включаются по env, no-op без ключей
Осталось:
- Деплой на Vercel: прод-БД, env-переменные, прод-redirect для Google, cron-расписание (Pro для частого запуска)
- PostHog —
NEXT_PUBLIC_POSTHOG_KEY(+ опц.NEXT_PUBLIC_POSTHOG_HOST). Инициализируется на клиенте, шлёт$pageviewпри смене роута; без ключа выключен. - Sentry —
SENTRY_DSN(сервер) +NEXT_PUBLIC_SENTRY_DSN(клиент). Подключён в runtime-режиме безwithSentryConfig, ловит ошибки только приNODE_ENV=production. Для загрузки source maps позже можно добавитьSENTRY_AUTH_TOKENи обёртку конфига.