Меня зовут Арсений, мне 15 лет. У меня 99 пользователей, более 100 SQL‑миграций и приложение на Android и Windows. И, что не менее важно, — команда единомышленников и поддержка тех, кто верил в проект с самого начала.
Почему я вообще за это взялся
Всё началось с простого любопытства: а смогу ли я создать что‑то подобное с нуля? Социальная сеть казалась одной из самых сложных задач для программиста: realtime‑функционал, авторизация, модерация, шифрование, мобильное приложение… Я решил проверить себя — и взялся за дело.
Огромную роль сыграла поддержка друзей и знакомых: многие из них сразу заинтересовались идеей, стали первыми тестерами и давали обратную связь на каждом этапе. Отдельный вклад внесли те, кто помогал со стилями и UX — их взгляд сделал интерфейс гораздо приятнее и удобнее.
А ещё у меня есть наставник в программировании — именно он помог сделать первые шаги в разработке. Благодаря его поддержке и советам мы смогли реализовать первый пиксель‑батл — и этим опередили второй ивент в соцсети ИТД блогера Nowkie. Этот опыт дал мощный толчок и вдохновил на создание собственной платформы.
Стек технологий
Я не выбирал архитектуру на основе каких‑то глубоких теоретических выкладок — взял то, что смог понять и что не требовало вложений на старте:
-
React 18 + TypeScript + Vite — фронтенд. Использовал CSS Modules без UI‑библиотек, всё стилизовал вручную (огромная благодарность тем, кто помог с визуальной частью!).
-
Supabase self‑hosted (PostgreSQL + realtime + auth + storage) — поднял на VDS за 999 рублей в месяц.
-
Cloudflare Workers — для фоновых задач: импорта Telegram‑каналов, push‑уведомлений и платёжного webhook.
-
Capacitor — чтобы собрать Android‑приложение из того же React‑кода.
-
Electron — для десктопного приложения под Windows.
При этом я обошёлся без Next.js и бэкенда на Node.js: вся бизнес‑логика реализована в PostgreSQL через RPC‑функции и RLS‑политики.
Что получилось в итоге

Когда начинаешь делать соцсеть, кажется, что всё просто: посты, лайки, профили — что тут сложного? Но спустя полгода разработки список функций разрастается так, что ты словно проваливаешься в кроличью нору.
Сейчас в проекте есть:
Контент:
-
посты с текстом, фото, видео и голосовыми сообщениями;
-
Stories;
-
комментарии с вложенностью;
-
репосты с цитатой;
-
хэштеги;
-
треды.

Общение:
-
личные сообщения с E2E‑шифрованием (ECDH P‑256 + AES‑GCM);
-
групповые чаты с голосовыми сообщениями, файлами и реакциями;
-
Telegram‑каналы с импортом.

Безопасность и модерация:
-
трёхступенчатая очередь модерации;
-
автомодерация NSFW‑контента через TensorFlow/NSFWJS прямо в браузере;
-
фильтр мата;
-
система предупреждений;
-
бан на уровне RLS (не фронтенда);
-
аудит‑лог всех действий;
-
блокировки пользователей.
Монетизация:
-
подписка «Агора+» через YooKassa;
-
совместные подписки (split‑cost);
-
реферальная система: 15 приглашённых друзей дают месяц премиума;
-
трекер личных подписок (Netflix, Spotify и т. д.).
Соответствие 152‑ФЗ:
-
EXIF‑стриппинг при загрузке любого фото;
-
данные хранятся только на российской инфраструктуре;
-
приватность профиля;
-
E2E‑шифрование в личных сообщениях: сервер не видит содержимое.
Приложения:
-
Android (Capacitor) — с биометрией, нативными хаптиками и камерой;
-
Windows (Electron) — с трей‑иконкой, splash‑screen и автообновлением.
Про 100+ SQL‑миграций: уроки на ошибках
Это не хвастовство, а скорее признание: каждая миграция — либо новая функция, либо исправление того, что сломалось после предыдущей. Вот несколько примеров, которые научили меня думать наперёд:
-
Миграция 33 (security_fixes). Обнаружил, что RLS на таблице сообщений позволяет прочитать чужую переписку, если знаешь ID разговора. Фикс занял два часа, но чувство тревоги осталось.
-
Миграция 40 (ban_rls_server_side). Раньше проверка бана выполнялась на фронтенде. Это означало, что любой мог открыть DevTools, удалить проверку и писать заблокированным пользователям. После исправления PostgreSQL отклоняет запросы забаненного пользователя на уровне БД — до React дело вообще не доходит.
-
Миграция 95 (feed_rpc). Лента загружалась через 5 последовательных запросов, что на медленном соединении давало задержку 3–4 секунды. Переписал в одну RPC‑функцию — время загрузки сократилось до менее 400 мс. Но по пути столкнулся с ошибкой 42702:
column "post_id" is ambiguous. В PL/pgSQL имя параметра функции конфликтовало с именем колонки в подзапросе — такое не гуглится с первого раза.
Друзья и знакомые, которые тестировали проект, помогли выявить многие из этих проблем на ранних стадиях — их замечания и отчёты о багах сэкономили мне кучу времени.
E2E‑шифрование: задача, которую я не ожидал осилить
Сначала ECDH казался мне чем‑то непостижимым. Но задача была чёткой: сервер не должен иметь доступа к содержимому личных сообщений.
Итоговая схема:
-
При регистрации генерируется пара ключей ECDH P‑256.
-
Приватный ключ шифруется паролем пользователя через PBKDF2 → AES‑GCM и хранится в БД в зашифрованном виде. Так ключ доступен с любого устройства, но сервер его не знает.
-
Каждое сообщение шифруется с использованием общего секрета ECDH + AES‑GCM с уникальным IV.
-
В БД хранится строка вида
E2E:base64ciphertext— сервер видит только это.
Всё это реализуется через WebCrypto API прямо в браузере, без сторонних библиотек.
NSFW‑фильтрация без сервера
Нейросеть для определения неприемлемого контента работает прямо в браузере пользователя через TensorFlow.js + NSFWJS. Картинка проверяется до загрузки на сервер — так сервер вообще не получает NSFW‑контент.
Это решает сразу три проблемы:
-
снижает нагрузку на сервер;
-
устраняет задержку модерации;
-
минимизирует юридические риски.
Что оказалось самым сложным
Не алгоритмы и не шифрование. Самое трудное — это:
-
Realtime‑функционал. Уведомления, статус «онлайн», индикатор «печатает…», новые сообщения — всё это должно работать одновременно, без утечек памяти и зависших WebSocket‑соединений.
-
RLS в PostgreSQL. Row Level Security — мощная штука, но одна неправильная политика может привести либо к утечке данных, либо к неработоспособности запросов. У меня было и то и другое.
-
Мобильная клавиатура на Android. Звучит смешно, но настройка
adjustResizevsadjustPanотняла у меня несколько часов. Клавиатура перекрывала поле ввода, и это не фиксилось одной строчкой кода. -
Работа в одиночку. Когда фича не работает в 23:00 и ты один — не у кого спросить совета. Тут меня выручали друзья и наставник: они подбадривали, помогали искать решения и тестировали каждую новую версию.
Цифры
-
99 зарегистрированных пользователей (многие из них — мои знакомые и их друзья);
-
более 100 SQL‑миграций;
-
около 15 000 строк кода на TypeScript;
-
1 основной разработчик + неоценимая помощь друзей по стилям, UX и тестированию;
-
0 рублей на рекламу (рост — только за счёт сарафанного радио и поддержки окружения).
Что дальше
Проект жив и развивается. Сейчас я работаю над:
-
публикацией в Google Play;
-
улучшением онбординговой воронки: люди заходят, не понимают, что делать, и уходят.
Огромное спасибо:
-
моему наставнику — за первые шаги в программировании и вдохновение на создание пиксель‑батла, который стал отправной точкой;
-
друзьям и знакомым — за помощь со стилями, UX, тестированием и честной обратной связью;
-
всем, кто поддерживал проект с самого начала и верил в него.
Если вам интересно попробовать — заходите на агора.com.
А если вы школьник и думаете: «Это слишком сложно для меня», — нет. Просто начните. Первую версию я написал за три недели, не зная TypeScript. Всё остальное пришло по ходу работы — и, конечно, с поддержкой тех, кто рядом.
ссылка на оригинал статьи https://habr.com/ru/articles/1028768/