Сделал SaaS для бьюти-салонов в одиночку: путь от идеи до App Store за полгода

Что в итоге получилось

Easy Busy — это календарь и CRM для бьюти-салонов и частных мастеров. То, чем мастер маникюра или администратор салона будет пользоваться каждый день вместо тетрадки, заметок в телефоне или сложного «энтерпрайз-софта», в котором половина кнопок не нужна.
Что есть на запуск:

- Мобильное приложение (iOS + Android), сделано на Expo / React Native.
- Веб-админка и публичная страница онлайн-записи для каждого салона.
- Шесть языков интерфейса: русский, английский, украинский, казахский, грузинский, арабский (с RTL).
- Авторизация через Google, Apple, телефон.
- Расписание сотрудников, клиенты, услуги, онлайн-запись с фирменным цветом салона.
- AI-подсказки внутри приложения (для пользователя — небольшой бонус, для меня — основной флекс).
Сейчас приложение проходит ревью в App Store, веб-часть и лендинг уже в проде, идёт SEO-разгон.
Это вторая попытка. Первая закопалась примерно через два месяца. Об этом тоже расскажу — это, кажется, самое полезное в статье.

Зачем это вообще

Я не из индустрии красоты. Я разработчик. Идея возникла из наблюдения: знакомая, которая работает мастером на дому, ведёт записи в трёх местах одновременно — в Telegram, в заметках iPhone и в голове. И постоянно ошибается с накладками.
Я открыл App Store и Google Play, посмотрел существующие решения для бьюти-салонов. Там два полюса:
1. **Огромные комбайны** под крупные сети с CRM, складами, маркетингом, аналитикой. Дорого, перегружено, UX из 2014 года.
2. **Полу-самоделки** от региональных команд. Часто без актуальных языков, без нормального онлайн-букинга, без современного UI.
Между ними — пустое место для «современный, простой, мультиязычный, для мастера и небольшой студии». Туда я и пошёл.

Первая попытка: как я закопался
Первые два месяца я делал ровно то, чего делать не надо.
**Ошибка №1. Архитектура «как у больших».** Микросервисы, очереди, отдельный сервис нотификаций, отдельный сервис расписания, шина событий. Для проекта, у которого ноль пользователей. Я честно потратил недели на инфраструктуру, которая никому не была нужна.
**Ошибка №2. Native iOS + Native Android.** Я решил, что Expo — это «для прототипов», и пошёл писать на Swift и Kotlin параллельно. В одиночку. На двух платформах. С нулевым опытом в SwiftUI. Это математически не работает.
**Ошибка №3. Дизайн в последнюю очередь.** Я начал с API и схемы БД. К моменту, когда я добрался до экранов, у меня уже были захардкоженные предположения о том, как всё устроено, — и они оказались неверными.
Через два месяца у меня был красивый бэкенд, два полусобранных нативных приложения, ноль рабочих сценариев и полное выгорание.
Перезапуск: что я поменял

Я закрыл репозиторий, выписал на бумаге, что именно я делаю не так, и начал заново. Главные решения:
1. **Один стек на всё, что можно.** Expo + React Native для мобилки. Next.js для веба. NestJS + Prisma для бэка. TypeScript везде. Один монорепо.
2. **Дизайн → код, а не наоборот.** Сначала Figma, потом схема БД под то, что нужно экранам. Не наоборот.
3. **Минимум сервисов.** Один API, одна Postgres, S3 для файлов, всё на одной машине в Hetzner. Никаких очередей, пока они реально не понадобятся.
4. **Деплой — `scp` и `docker compose up`.** Я долго стеснялся в этом признаться, но для проекта одного разработчика это работает лучше любого Kubernetes.
5. **Платные сервисы только там, где это окупается временем.** EAS для билдов, Sentry для крашей, S3 — всё.
Эта перезагрузка дала ускорение примерно в три раза. Не потому что Expo волшебный, а потому что я перестал бороться с самим собой.
Что оказалось сложнее, чем я думал

Мультиязычность
Шесть языков — это не «прогнал тексты через переводчик». Это:
- Согласование терминов с носителями языка (особенно болезненно с казахским и грузинским — там у бьюти-индустрии своя лексика, которой нет в общих словарях).
- RTL для арабского — это не «зеркальная вёрстка», это много мелких багов в стрелках, отступах, анимациях.
- Локали для дат, времени, валют. Каждая страна — свой формат.
- Имена пользователей: например, Google возвращает имя одним полем, и в разных культурах оно разбивается по-разному. Пришлось переделывать профиль два раза.
Онлайн-запись с фирменным цветом

Идея простая: у каждого салона есть свой brandColor, и публичная страница записи окрашивается в этот цвет. На дизайне — пять минут. В реализации — это:
- Контрастность текста при произвольном фоне (привет, WCAG).
- Состояния hover/active/disabled, которые должны выглядеть нормально на любом цвете.
- Тёмная тема, в которой brandColor нужно «приглушать», иначе он выжигает глаза.
В итоге сделал свой утилитный модуль, который из одного hex генерирует всю палитру состояний. Пишу это в статью, потому что почему-то почти никто из конкурентов так не делает — большинство публичных страниц записи выглядят как из 2010-х.
Geo-доступность

Из России и Беларуси домен `easybeezy.net` периодически плохо открывался. Решение оказалось проще, чем я боялся: Cloudflare Free перед сайтом. Один вечер настройки, минус большая часть жалоб.
Что я сделал не так и в этот раз
Чтобы статья не была хвастовством, честный список:
- **Слишком поздно занялся SEO лендинга.** Метатеги, JSON-LD, sitemap, FAQ-разметка — всё это должно было быть с первой публикации сайта, а не через несколько месяцев.
- **Слишком поздно подключил Sentry.** Из-за этого первые крашы в проде я ловил по скриншотам от тестеров.
- **Долго тянул с публикацией.** App Store ревью — это страшно только до первой подачи. После — это просто рутина с понятными правилами.
- **Не вёл публичный build-in-public.** В ретроспективе — зря. Аудитория, накопленная за время разработки, на старте дороже любых ads.
Стек, если кому-то интересно

- **Мобилка:** Expo (managed workflow), React Native, EAS Build, EAS Update для OTA.
- **Веб:** Next.js (App Router), Tailwind, i18n через локальные словари.
- **Бэкенд:** NestJS, Prisma, PostgreSQL.
- **Инфра:** один сервер Hetzner, Docker Compose, Cloudflare перед сайтом, S3-совместимое хранилище для файлов.
- **Сервисы:** Google/Apple Sign-In, OpenAI для AI-подсказок, Sentry для крашей, EAS для билдов, App Store + Google Play.
Никакой магии. Главное — что один человек реально может это всё поддерживать, потому что выбор стека сделан под этот сценарий, а не «как у Uber».
Что дальше

Ближайшие планы:
- Закрыть ревью в App Store и Google Play, выйти в публичный релиз.
- Запустить SEO-маховик: статьи в блоге, нишевые бьюти-площадки, кейсы.
- Сделать редизайн публичной страницы записи — это первое, что видит клиент салона, и сейчас она «нормальная», а должна быть «вау».
- Постепенно добавлять то, что реально просят пользователи. А не то, что мне кажется правильным.
Если вы делаете что-то похожее

Несколько вещей, которые я бы сказал себе год назад:
1. **Один стек, одна голова.** Не пытайтесь делать нативно на двух платформах в одиночку. Это не «компромисс на качестве» — это вопрос выживания проекта.
2. **Дизайн вперёд кода.** Даже если вы разработчик, а не дизайнер. Особенно если вы разработчик.
3. **Не строите инфраструктуру для воображаемого масштаба.** Один сервер и `docker compose` тащат намного дольше, чем кажется.
4. **Локализация — это продуктовое решение, а не задача переводчика.** Если выходите в несколько стран, закладывайте это в архитектуру с первого дня.
5. **App Store ревью — это не страшно.** Боится только тот, кто ещё не подавался.
Если интересно, как устроено что-то конкретное — спрашивайте в комментариях, отвечу подробно. И если вы мастер, администратор или владелец салона — напишите, какие у вас сейчас самые больные места в работе с записью. Это для меня сейчас важнее, чем любые звёзды на гитхабе.
---
*Easy Busy — easybeezy.net. Сайт, приложение, шесть языков, один разработчик.*

Начать дискуссию