Веб-приложение и публичная витрина SoundBox: лендинг о продукте и собственном производстве, страница покупки франшизы, а также MVP для бронирования звукоизолированных кабинок по Москве.
# Установка зависимостей
npm install
# Запуск (frontend + backend одновременно)
npm run dev- Frontend: http://localhost:5173 (или следующий свободный порт)
- API Server: http://localhost:3001
Проект деплоится как full-stack Node-приложение: Vite собирает фронтенд в dist, а server.js отдаёт API и готовый сайт.
- Загрузите проект в GitHub.
- Откройте Render → New → Blueprint.
- Выберите репозиторий SoundBox.
- Render прочитает
render.yamlи сам создаст web-service на планеstarter, потому что для SQLite нужен persistent disk. - Build command:
npm install && npm run build. - Start command:
npm start.
В render.yaml уже настроены:
JWT_SECRET— генерируется автоматически.DB_PATH=/var/data/cabins.db— SQLite хранится на постоянном диске.UPLOADS_DIR=/var/data/uploads— аватарки пользователей тоже хранятся на диске./api/health— health-check для хостинга.
Локальные файлы базы cabins.db, cabins.db-shm, cabins.db-wal и папка uploads не нужно коммитить: на хостинге база создастся и заполнится стартовыми кабинками автоматически.
Если нужен полностью бесплатный демо-деплой, можно убрать блок disk из render.yaml и заменить DB_PATH/UPLOADS_DIR на локальные пути, но данные пользователей и бронирований могут сбрасываться при рестарте сервиса.
- Публичный лендинг — рассказывает кто мы, что делаем и как MVP связан с сетью кабинок
- Собственное производство — вынесено в отдельный публичный блок на лендинге
- Страница франшизы — пакеты запуска, состав франшизы и связь с MVP
- Калькулятор точки — оценка оборота по количеству кабинок и загрузке
- Заявка на франшизу — публичная форма сохраняет лид в SQLite
- Регистрация — создайте аккаунт с именем, email и паролем
- Вход — авторизация через email и пароль
- JWT токен — автоматическое сохранение сессии (7 дней)
- Валидация — проверка заполненности полей, минимальная длина пароля
- Приветствие — персонализированное с аватаром из инициалов
- О сервисе — описание и список удобств (Wi-Fi, климат, зарядка, монитор)
- Как это работает — пошаговая инструкция из 4 шагов
- Кнопка «Забронировать кабинку» — переход к карте
- Активные бронирования — карточки с countdown-таймером в реальном времени
- Кнопка «Открыть кабинку» — появляется только когда наступает время брони (с glow-анимацией)
- Автоблокировка — после окончания брони кабинка автоматически блокируется
- Отмена бронирования — до начала брони можно отменить
- История бронирований — все прошлые и отменённые бронирования
- 10 кабинок — реальные локации по Москве (Арбат, Москва-Сити, Парк Горького, Китай-город, Белорусская, Таганка, Полянка, Павелецкая, Менделеевская, ВДНХ)
- Тёмная тема — карта CartoDB Dark Matter
- Пульсирующие маркеры — анимированные иконки кабинок
- Счётчик кабинок — в правом верхнем углу
- Легенда — цветовые обозначения (свободна / занята)
- Детали кабинки — название, адрес, описание, рейтинг, цена, удобства
- Выбор даты — календарь с блокировкой прошлых дат
- Слоты по часам — кабинки работают 24 часа, бронирование доступно круглосуточно
- Занятые слоты — отображаются красным для всех пользователей
- Проверка конфликтов — невозможно забронировать занятое время
- Confetti — праздничная анимация при успешном бронировании
- Автоматический переход — на dashboard после бронирования
- Тёмная тема — deep purple (#7C4DFF) + cyan (#00E5FF)
- Glassmorphism — полупрозрачные карточки с backdrop-blur
- Анимированный фон — частицы на странице входа
- Framer Motion — плавные page transitions, staggered lists, spring modals
- Micro-animations — hover effects, pulsing markers, countdown timers
- Адаптивный дизайн — mobile (375px+), tablet (768px+), desktop (1280px+)
- Fullscreen модальное окно на мобильных устройствах
- Кастомный scrollbar в стиле темы
| Компонент | Технология |
|---|---|
| Frontend | React 18 + Vite |
| UI | Material UI (MUI) v7 |
| Анимации | Framer Motion |
| Карта | React-Leaflet + Leaflet |
| Уведомления | react-hot-toast |
| Confetti | canvas-confetti |
| Даты | date-fns |
| Backend | Node.js + Express |
| База данных | SQLite (better-sqlite3) |
| Авторизация | JWT + bcryptjs |
Cabins/
├── server.js # Express API сервер
├── package.json
├── index.html
├── vite.config.js
└── src/
├── main.jsx # React entry point
├── App.jsx # Routing + providers
├── api.js # HTTP клиент для API
├── theme.js # MUI тема (dark mode)
├── index.css # Глобальные стили
├── context/
│ └── AuthContext.jsx # Контекст авторизации
└── pages/
├── LandingPage.jsx # Публичный лендинг
├── FranchisePage.jsx # Страница покупки франшизы
├── LoginPage.jsx # Вход / Регистрация
├── DashboardPage.jsx # Личный кабинет
└── MapPage.jsx # Карта + бронирование
| Метод | Путь | Описание |
|---|---|---|
| POST | /api/register |
Регистрация |
| POST | /api/login |
Авторизация |
| GET | /api/me |
Данные текущего пользователя |
| GET | /api/cabins |
Список кабинок |
| GET | /api/cabins/:id/bookings |
Бронирования кабинки |
| POST | /api/bookings |
Создать бронирование |
| GET | /api/my-bookings |
Мои бронирования |
| POST | /api/bookings/:id/unlock |
Открыть кабинку |
| POST | /api/bookings/:id/cancel |
Отменить бронирование |
| POST | /api/franchise-leads |
Создать заявку на франшизу |
- Зарегистрируйтесь — введите имя, email и пароль
- Изучите кабинет — прочитайте описание и инструкцию
- Нажмите «Забронировать кабинку» — откроется карта Москвы
- Выберите кабинку — нажмите на маркер на карте
- Выберите дату и время — красные слоты заняты, серые — прошли
- Подтвердите бронирование — нажмите «Забронировать»
- Дождитесь времени — следите за countdown-таймером на dashboard
- Откройте кабинку — нажмите зелёную кнопку «Открыть кабинку»
- После окончания — кабинка автоматически заблокируется