В этой статье я расскажу, как делал свой проект социальной сети для сферы искусства havidea.ru от идеи до релиза. Расскажу о технической части, о мотивации и самоорганизации, какими инструментами пользуюсь в процессе разработки, о проблемах в работе со сферой искусства, с которыми я столкнулся почти сразу после запуска. Проект пережил реинкарнацию, т.е. был первый вариант, который я забросил и финальный, второй, который ушел в релиз.

В сфере веб-разработки я работаю немногим более трех лет. Проект поднимался в одиночку в свободное от основной работы время и главной целью было — выпустить продукт в установленные сроки (6 мес.).

Вдохновение, идея, исследование


Будучи подростком, я начал увлекаться музыкой, живописью. Чуть позже загорелся 3D графикой и даже успел заработать на 3D моделях первые копейки. Еще пару лет спустя всерьез занялся фото- и видеосъемкой и в этот же период на уроках вокала (и такое было в моей жизни, да) познакомился с будущей женой — актрисой. Все это подтолкнуло сделать какой-нибудь проект для поддержки “веселых” судеб творческих людей. Иии? Социальная сеть? Почему бы и нет? Но это же хейтят, мол, соц. сети умирают. У кого-то умирают, а у меня получится, верно? И вообще, если есть обоснованная идея и концепция, почему бы не воплотить это в веб-страницу? Загуглив список социалочек, наткнулся на интересный вариант — stage32. На мой взгляд, это единственная серьезная зарубежная площадка, собиравшая сообщество причастных к кинопроизводству. В России аналогов на то время (начало 2017 г.) я не нашел (плохо искал?). Решено. Сделаю свой сервис, опираясь на лучшие образы, практики и UX уже существующих соц. сетей, но с уклоном к сфере театра, кино и искусства в целом.

Идеология проекта


Некоммерческий, без рекламы, максимально полезный для самих участников. Свободный, без слежки, без метрик. Защита пользовательских данных.

Первый вариант (2017 г.)


Любой проект должен начинаться с постановки и ответа на вопросы: для кого? Для чего? Какую проблему это решает (цель)? Какие есть альтернативы? Какие преимущества можно предложить? После четких и лаконичных ответов, я составляю список функциональности будущего проекта. Далее определяюсь с костяком: убираю все хотелки и фантазии из общего списка функционала и оставляю только самое необходимое — то, без чего приложение не будет функционировать. От минимального функционала подбираю стек. Ищу примеры реализации. На этом этапе уже есть общая картина: что делать, для чего и как. Весь процесс, комментарии и мысли записываю в блокнот, чтобы повторно не решать то, от чего ранее отказался.

Проектировать UI начинаю с листка бумаги и карандаша. Любой листок, который есть под рукой, идет в дело, пока мысль не убежала. Определяюсь со страницами и провожу вторую грубую итерацию уже в электронном виде (проще что-то изменить):

Изображение наброска страниц
image

Далее прорабатываю эскизы детально. Вот, например, самый первый вариант страницы профиля:

Изображение страницы профиля
image

Посты, комменты, лайки, альбом с фотографиями — все по классике. Из нового:
расширенный профиль для актеров, поиск по профессиям и навыкам.

Для разметки макета использовал modulargrid.org:

Изображение страницы профиля с модульной подложкой
image

Я экспериментировал с 12, 15 колоночными сетками, но остановился на 12. Хочу отметить, что верстка по модульной сетке штука неоднозначная. Вам не всегда удастся вписать информацию в блоки, потому что интерфейсы — это графическое отображение данных. Я исхожу из принципов Data-Driven design, т.е. основное назначение интерфейсов — представлять данные и удобные варианты взаимодействия с ними. Именно поэтому дизайнер != веб-дизайнер. Вернувшись к проблеме модульной сетки скажу, что она лишь помогает в первоначальном расположении блоков, а финальный вариант должен утвердиться с помощью тренированного глаза. К тому же, в любой сущности должна быть изюминка или отхождение от правил, чтобы добавить живости.

Пара набросков главной страницы:

Набросок главной страницы 1
image

Набросок главной страницы 2
image

Некоторые решения выглядят не совсем удачными и убираются/правятся при верстке. На этапе проектирования надо давать себе свободу и не выводить все до идеала.

Страница входа:

Изображение страницы входа
image

После набросков десктопной версии, уделяю внимание мобильной. Графическая часть готова? Нормас. Пора кодить.

Frontend первого варианта.

В качестве бэкграунда для главной страницы я использовал библиотеку Three.js для работы с WebGL. Треугольники свободно плавают и “следят” за мышкой. Забегая вперед скажу, что в реинкарнации я отказался от Three.js и сделал на css + png, потому как библиотека весит ~570кб и использовать ее для одного несложного эффекта показалось расточительством. В разработке я придерживаюсь установок: минимализм, производительность, легкость поддержки. Так как социальными сетями примерно на 3/4 пользуются с мобильных, то был отдан приоритет легковесности и скорости. Как библиотеку UI компонентов взял Bootstrap 4. Без jquery, только css. Я пробовал обертку bootstrap-vue, но как-то не зашло. Бросались в глаза невалидные html теги и хотелось свободы кастомизации. Как вы могли догадаться, фреймворк Vue. Хотелось изначально заложить хорошую индексацию поисковиками, поэтому докрутил Nuxt.

Backend первого варианта.

Laravel. Для one-man проектов vue + laravel = must have. Скорость разработки, большое сообщество, куча готовых пакетов. Архитектура API-first (бэкенд изначально разрабатывается как API).
Какое API без документации? ApiDoc отличная штука, которая умеет генерировать документацию из PHPDoc. Роутинг кастомизировал и вынес файлы роутов из единого api.php, т.е. один файл, один роут. Для удобства и для генерации документации. Вдохновение черпал из Apiato. Неплохой starter kit для API, напичканный разными паттернами проектирования и оригинальным архитектурным Porto, призванным разбить приложение на модули, но по сути ведущий к монолиту. Судя по реп��зиторию, проект заброшен более года назад. Скорее всего, по причине активного распространения микросервисной архитектуры.

Отдых, прокачка скиллов


Шел 2018 год. В первой версии я успел реализовать регистрацию, аутентификацию, страницу профиля с редактированием, страницу настроек. Времени по вечерам было немного. Тогда я только начинал путь vue, да и ssr на nuxt капризничал. В итоге, через 4-5 месяцев сдулся. Это был амбициозный проект и не хватило скилла его поднять, не упав самому. За 2018 год я сильно подтянулся как full stack разработчик, освоил docker и в начале 2019 начал все с нуля. Ну, почти с нуля.

Второй вариант (2019 г.), релиз


Frontend второго варианта.

От nuxt ssr я отказался — прослойка из node.js требует дополнительного внимания, да и не видел в нем нужды конкретно на этом проекте. Bootstrap заменил на Quasar — полноценный vue UI (и не только) framework (почему взял его расскажу ниже). Интерфейсы полностью переделал, ушел от вк-стайл концепции. Теперь insta-стайл. Добавил возможность создания трех типов публикаций: фото, видео и текст. В макете использовал 24 колоночную сетку. Сейчас сервис выглядит так:

Финальный вариант первого экрана
image

Да, можно сделать верхнее меню прозрачным. Но нужно уметь хотелкам сказать “нет”. Главную страницу я в итоге нарисовал заново. Поэтому, не стоит вдаваться в детали раньше, чем будет полная картина. Рано или поздно вы захотите все изменить и не важно, насколько прекрасным было решение. Конечно же, сайт полностью адаптирован:

Страница профиля на мобильном
image

Про TypeScript. Я пробовал его внедрить, но в последствии вырезал, потому что строгая типизация требует больше времени на расстановку типов, интерфейсов. Я пришел к выводу, что TS без strict режима не имеет смысла. Оно и верно — зачем типизация без указания типов. В strict режиме приходится описывать абсолютно все и это как минимум +30% к срокам разработки. А если у вас не утверждена схема обмена данными с бэкендом, то придется постоянно отвлекаться на мелкие правки. Местами вам понадобится игнорить ошибки компилятора добавлением комментария @ts-ignore в код только потому, что вы не ответственны за сторонний код, который не полностью поддерживает TS. Кроме того, вся выгода от TS раскрывается в сложных логических расчетах, т.е. типизировать .vue файлы оказывается несколько избыточным. Буду рад услышать комментарии по этой теме.

Когда фронт был готов на 90%, я задонатил Browserstack и протестировал приложение на Safari. Не жалею потраченных денег, потому как удалось пофиксить парочку простых, но критичных багов. Минутка бомболейло. Safari, когда вы уже начнете думать о пользователях и разработчиках? Годами не исправляете баги. Особенно залипающий скролл в модалке. Я не нашел 100% работающего способа, как заставить Safari корректно скроллить контент в модальном окне. Буду рад, если кто сталкивался и подскажет решение.

Помимо основного приложения, сделал еще и простенькую админку со своим апи:

Screenshot админки
image

В админке ничего примечательного. Просто UI покрытие для некоторых фич, из-за которых лень лезть в базу и править данные руками.

Backend второго варианта.

Laravel. Обязательная валидация всех входящих данных, cors заголовки, дополнительные заголовки безопасности secure-headers, следование RESTful спецификации (как-нибудь попробую JSON-RPC), Fractal для трансформации отдаваемых данных на фронт. Try-catch всего, чтобы пользователь не давил мышку, а получил внятную причину ошибки. Автоматические дампы обеих баз данных с помощью db-dumper. Какого-либо автоматизированного тестирования не писал, ибо ограничен по времени. Надо подкачаться и попробовать TDD, может получится не сильно увеличивать сроки разработки или даже сократить.

Отдельно хочется сказать, что я избегаю использования абстракций на начальных этапах проектирования, если без них сейчас можно обойтись. Их преждевременное использование ведет к усложнению модуля приложения, который может быть никогда не использован. Решайте проблемы по мере поступления. Да, соблюдать баланс между архитектурой и сроками не просто и это приходит только с опытом, но лучше потратить время на продумывание базы данных, а переписать код приложения можно в любое время. Самый важный ресурс, который у нас ест�� — это время. Лучше выпустить не идеальный продукт и быть первым, чем потом догонять конкурентов. А они будут.

Проблема, стагнация


Запуск состоялся в конце мая. Я начал заниматься рекламой и почти сразу наткнулся на похожий сервис. Да, они по сути реализовали такую же идею. Года на 2 раньше. Надо было лучше исследовать рынок и мониторить его постоянно на предмет новых сервисов. Но проблема даже не в этом. В процессе дискуссий, размышлений и просто жизненного опыта я пришел к выводу, что проблема трудоустроенности людей искусства намного глубже и, возможно, специализированной социальной сетью не помочь. Это рыночная проблема нехватки рабочих мест. В каком направлении развивать продукт я точно не знаю. Сейчас проект переживает стагнацию.

Под капотом


Технологии, вошедшие в релиз
  • Vue
  • Quasar (UI библиотека vue компонентов). Это офигенный, легкий, красивый и минималистичный фреймворк и самое главное — mobile и desktop pixel perfect. Да, я пробовал vuetify 2 beta. Но как по мне, vuetify для мобилок не подходит и в целом его API и документация более запутанные, чем у Quasar. Также, у Quasar есть ряд плагинов и импортируемых функций. Например, работа с датами, touch событиями, определение платформы по user-agent, программные dialogs (модалки), работа с DOM и скроллингом: все это сужает круг зависимостей в package.json.
  • Laravel
  • Docker / docker-compose. Описывать docker-compose.yml не буду, но приведу несколько моментов: разделение контейнеров по network’ам. У меня их две: web и app; самостоятельные инструменты (Portainer, Traefik) в отдельных docker-compose, чтобы не падало основное приложение при перезапуске.
  • Redis. Объектное хранилище с функционалом очередей. Если для очередей нужно что-то помощнее, попробуйте RabbitMQ.
  • MySQL
  • Mongodb. В монге храню публикации, комменты, медиа-файлы, уведомления — все самые объемные данные. Монга проще масштабируется, чем мускул.
  • Nginx
  • Traefik. Очень дружелюбный и простой в настройке reverse-proxy для docker окружения (и не только). Плюс сам получает ssl сертификаты let’s encrypt. Раньше использовал Certbot, а теперь вообще не парюсь с дополнительными зависимостями.
  • Portainer. Контейнеры поднимаю руками через docker-compose, но иметь наглядный интерфейс по их состоянию очень полезно. Туда же падают логи из stdout / stderr. Если бюджет позволяет, то для логов можно поставить какой-нибудь ELK.
  • ElasticSearch. Спасибо Laravel сообществу, что есть Scout драйвер для ES (Scout сам обновляет данные в индексах-базах эластика). Кстати, не забывайте закрывать сервис с внешки. Один из вариантов это сделать — в докер-контейнере прописать ports: «127.0.0.1:9200:9200» (заметка: для безопасности лучше не использовать стандартный 9200 порт). В эластике два индекса: по профилям и по публикациям. Настроен hunspell для русской морфологии.


Примечательные сервисы
  • AWS Saas. Хотел поставить Minio S3, но в бюджет совсем не вписывается.
  • Mailgun. У Laravel из коробки есть интеграция с этим сервисом. Очень удобный, со своим интерфейсом и (!) очередями.
  • Sentry.io Saas. Можно поставить как self-hosted. Супер удобный и полезный инструмент отладки. Подключил и фронт и бэк к нему. Настроил релизы. Все runtime ошибки отслеживаются и вовремя обнаруживаются посредством, например, уведомлений на почту. Красота.


Полезные инструменты
  • Trello — удобные канбан доски. У меня такой набор: сделать, готово, тестирование, обсуждение, отмена.
  • Browserstack — тестирование на iOS, “любимом” Safari.
  • Gitlab — репозитории и ci/cd. CD как таковой не настраивал — свой gitlab runner не поднимал, а давать коннектиться по ssh гитлабовским раннерам как-то стремно. Devops не моя сильная сторона, к тому же. По части CI — сборка фронта, пуш в репозиторий gitlab. Переменные храню здесь же в разделе ci/cd -> variables, которые пробрасываются на этапе сборки.


Итог


Несмотря на сложившуюся ситуацию с моими представлениями на особенности рынка сферы искусства, я нисколько не жалею несколько сотен затраченных часов. Процесс завораживал, давал кучу опыта и не только программерского. Я сделал сервис таким, каким задумывал и горжусь финальной реализацией. Мною двигала вера в то, что я смогу помочь творческим людям. Это было главной мотивацией. Может, изначальный некоммерческий подход поставил проект в сложное положение? Есть (спорное) мнение, что надо начинать либо бизнес, либо ничего. Как это ни печально, но иногда лучше вовремя остановиться, чем делать то, во что не веришь. Если п��идет новое понимание в какую сторону двигаться, то продолжу развивать. Буду польщен вашими мнениями.