Иногда нужен один пароль. Сгенерировать, скопировать, жить дальше. На практике оказываешься в мини-CRM своих секретов: подписки, синки, тариф «счастливый сейф на всю жизнь», автозаполнение, которое просит ещё одно разрешение.
Я хотел по-простому. Так появился PassWave: генератор с опциональным хранилищем. Без карты на входе. Карточка проекта здесь.
Сначала думал делать Telegram Mini App. Потом понял, что PWA универсальнее: ставится на телефон и десктоп, работает оффлайн, не привязана к мессенджеру. Telegram-версию оставил на полке. Если спросят, достану. Пока не спрашивали так, чтобы ради этого держать второй контур.
Стек: Next.js 16, React 19, TypeScript, Tailwind CSS 4, Supabase, FSD. От идеи до прода две недели. FSD на таком размере выглядит театрально. Без него за те же две недели вырастает свалка хуков. Папки дешевле театра.
Что уехало в прод
Шифрование на клиенте. Сервер видит непрозрачный blob и не обязан понимать, что внутри. Ноль байт открытого текста на диске бэкенда, по крайней мере так было задумано. Пароли генерируются нормальной криптой, не Math.random из подворотни. Фраза-ключ только у человека. Потерял, не восстановлю. Зато и я содержимое не вижу.
Полный оффлайн: генерация и локальное хранилище без сети. Синхронизация между устройствами по желанию, не «мы уже всё унесли, надеемся, вы не против». Регистрация не обязательна. Можно жить только локально и никому не рассказывать, что у вас есть ящик для паролей.
С первого дня несколько языков, в итоге семь. Пресеты, режим «не путай O и 0, I и l». Парольные фразы для тех, кто хочет помнить, а не копировать. Пакетная генерация, когда наводишь порядок сразу. QR, чтобы не слать секрет себе в мессенджер. Тёмная тема, конечно.
Автозаполнения и расширений не делал. Чем меньше кода между человеком и паролем, тем меньше мест, где можно ошибиться. Расширение в браузере это ещё один жилец в доме, которого надо кормить обновлениями. Я и так не кормил axios вовремя.
Это не замена менеджеру на тысячу записей. Карманный мультитул: сгенерировать, сохранить несколько важных, уйти. Фрилансеру, который каждую неделю заводит новый сервис, такого ящика хватает. Тому, у кого семейный сейф на 400 аккаунтов, нет. Им я это и не продавал.
Планы, которые так и не понадобились: лёгкий импорт, больше словарей для фраз, автозамок при сворачивании. Весна пришла раньше, чем словари.
Supabase здесь курьер: auth, хранение blob, синхронизация. Он не читатель. Я выбрал его, чтобы не писать свой бэкенд для ящика, который человек может вообще не включать. Локальный режим должен работать, даже если облако завтра ляжет. Облако, как выяснилось, может лечь и по другой причине.
Апрель 2026
Весной 2026 сервис взломали. Вектор: уязвимость в axios, через неё добрались до бэкенда. Зашифрованные blob'ы на сервере атакующий получил.
Технически без фразы-ключа содержимое бесполезно. Сам факт, что кто-то прошёл в бэкенд, уже провал. Архитектура «сервер ничего не читает» не отменяет дыру, через которую в сервер входят. Я не хотел держать сервис, в который перестал верить.
Снёс всё, пока не стало хуже.
Zero-knowledge не освобождает от бэкенда. Зависимости это поверхность атаки. Особенно в сайд-проекте, где обновления ставишь когда вспомнил. Pet-проект с живыми пользователями уже продукт. Относиться к нему как к игрушке нельзя.
Перезапуска нет. Если когда-нибудь, только схема с минимальной поверхностью и жёстким пайплайном зависимостей. Не тот же ящик с той же дырой, только свежее покрашенный. Serverless, меньше долгоживущего бэкенда, обновления не «когда вспомнил». Пока это запись на будущее, не обещание даты.
Как я держу бэкенд под собой: Self-host Supabase.

