Недавно к нам пришёл клиент за разработкой платформы для стартап-акселератора. И было у клиента одно важное и непоколебимое требование: чтобы в качестве системы управления контентом выступал Notion. Рассказываем и показываем, как подходили к задаче, боролись со спам-аккаунтами, немного разочаровались в Notion и решили чуть больше приблизиться к эталонной разработке по SCRUM.
Небольшой оффтоп
Проект, о котором мы рассказываем, под NDA. Поэтому не сможем делиться настоящими ссылками и скринами, зато подойдём с технической стороны. Расскажем про то, как подружили Next.js, Notion, Supabase и Drizzle ORM. Но сначала, введём в контекст проекта — с чем столкнулись в ходе разработки и что получилось в итоге.
Интересный факт: мы впервые использовали связку Notion и Supabase в качестве CMS-ки и базы данных. И если API всем привычного Notion мы уже трогали для внутренних задач, то Supabase был для нас чем-то новеньким
Проект клиента связан с криптокошельками, стартапами и проектом от Telegram
Звучит так, будто мы взялись за работу из-за последних новостей с Павлом Дуровым, но на самом деле — нас зацепила задача с интеграциями.
С помощью платформы пользователи продвигают свои стартапы на зарубежном рынке
Сначала пользователи могут авторизоваться через телеграм-кошелёк, опубликовать информацию о своём стартапе, обозначить цели и планы. А потом поучаствовать в программах сообщества, найти партнёров, единомышленников, менторов и, самое крутое, инвесторов.
Что-то на бизнесовом 💸💅
Не будем погружаться в детали вёрстки, здесь всё по классике: использовали компонентный подход, собрали экраны, протестировали. Сделали всё быстро и красиво по дизайн-макетам. Поэтому перейдём к более интересному — интеграциям.
С самого начала поняли, что одним Notion тут не обойтись, поэтому совместно с клиентом решили пойти таким путём:
- Большая часть информации должна храниться и легко редактироваться в Notion.
- Связка самого пользователя и кошелька — в Supabase. В итоге 38 таблиц получилось, требования к функциональности слегка выросли...
В Notion клиент работает со статическим и динамическим контентом
Чтобы не смешивать данные, клиент распределил его по двум таблицам. В первой он хранит весь контент сайта: тексты, заголовки, картинки и прочее. А во второй — нечувствительные данные о пользователе: токен, имя, название стартапа, страну, соцсети.
Таблица со статическим контентом выглядит, как типичная база данных
Допустим, чтобы обновить текст на странице «О нас», нужно выбрать её в Notion и занести в таблицу нужный текст.
После зайти по нашей специальной ссылке и обновить контент. Так новый текст появится на сайте.
Вся прелесть в том, что контент не появляется на сайте сам по себе, что помогает публиковать контент без ошибок
Таблица с динамическим контентом отличается проверкой данных
Как мы говорили выше, пользователи регистрируются через свой кошелёк в телеграме. А в таких «криптокошельковых темах» навалом спама, от которого нам нужно как-то защищаться. И решили мы это с помощью штатной проверки.
Администратор со стороны клиента вручную проверяет данные в таблице с динамическим контентом и оставляет за собой выбор — пропустить пользователя дальше или нет.
Все важные поля для проверки видны в рамках одного экрана, поэтому обработать их в Notion занимает пару минут.
Если всё хорошо → администратор пропускает пользователя дальше
Если администратор замечает спам → угадайте, что будет
Чтобы контент появлялся на сайте, мы написали вебхук — код, который отслеживает изменения на одном сайте и передаёт данные на другой.
Каждую минуту вебхук заходит в таблицу и проверяет обновления статусов по программам, проектам и профилям. Если находит новое — переносит на сайт
Отлично, с таблицами разобрались. Теперь перейдём к тому, как мы изучали документацию и почему разочаровались в Notion.
Изучили API обоих сервисов, чтобы понять, хватит ли этого для наших задумок
Сразу зайдём с полезного и оставим ссылки на документации:
Notion API: https://developers.notion.com/
Supabase Docs: https://supabase.com/docs
Из первой документации мы узнали, что в Notion ограниченное количество запросов — 3 запроса в секунду. Нам показалось, что этого мало для постоянного обновления динамического контента.
Представьте, если на сайт придёт несколько сотен пользователей и захочет обновить информацию у себя в профиле одновременно. Скорее всего, из-за такого количества данные просто не будут отдаваться и сохраняться. А мы всё-таки хотим, чтобы платформа держала нагрузку и в таблицы сохранялась вся-вся информация.
Чтобы динамические данные обновлялись постоянно, нам нужен ещё один сервис, который может принимать больше запросов. И мы остановились на Supabase.
Supabase — это крутой open-source аналог Firebase
С его помощью можно управлять базами данных в облаке, подключать аутентификацию, организовать ограничение скорости запросов и много чего ещё.
В Supabase мы сохраняем ID и данные зарегистрированного пользователя
Здесь речь идёт уже про токены, а не данные из личного кабинета. При регистрации пользователь получает уникальный номер, который нам нужно сохранить в отдельную таблицу.
Токены также отсматриваются администраторами со стороны клиента. Они проверяют информацию из таблицы Notion и смотрят на наличие спама — бывает такое, что пользователи оставляют одну информацию в кабинете, а токен никак не относится к этому профилю.
Если данные совпадают → администратор пропускает пользователя дальше
Если администратор замечает спам → не пропускает и удаляет токен пользователя
Штатная проверка помогла клиенту выявить подозрительные моменты и уменьшить количество спама
Если в Notion были вполне предсказуемые ограничения, то в Supabase не оказалось транзакций
Если кратко, транзакции гарантируют выполнение запросов. Это как с банковскими переводами — если вы переводите деньги с одной карты на другую, но у вас недостаточно средств, банк выдаст ошибку и отменит операцию.
В нашем случае может возникнуть ситуация, когда пользователь заполняет данные профиля и сохраняет их на сайте. Если с нашей стороны происходит ошибка, то действие отменяется и данные не сохраняются. В итоге, данные в одной таблице сохраняются, а в другой — нет.
Для решения проблемы с транзакциями, мы использовали прослойку, которая помогает проще работать с данными
Каждому действию мы присвоили своё состояние — «в процессе», «успешно», «неудачно» и говорили сервису, что делать в случае ошибки.
- Когда пользователь заполняет и сохраняет данные на сайте, прослойка сначала обрабатывает их, а потом проверяет ошибки. То есть, находится «в процессе»
- Если с информацией всё хорошо и нет ошибок, сервис обновляет статус на «успешно» и сохраняет данные на сайте
- Если видит ошибку — ничего не сохраняет и присваивает статус «неудачно»
Так мы можем создавать, читать, изменять и удалять данные пользователей
Кратко: какие данные и в какой базе мы храним
В Notion: хранятся все данные, которые относятся к контентной части сайта + информация о пользователе из личного кабинета.
В Supabase: хранятся данные, которые относятся непосредственно к профилям зарегистрированных пользователей.
А сверху наша интеграция выглядит так:
С технической частью закончили, давайте вернёмся к истории, как мы подходили к процессу работы с клиентом.
Работали в режиме продуктовой команды и регулярно делали релизы с готовым функционалом
Сначала построили процесс так, как делаем обычно — делили весь объём работы на двухнедельные спринты и выгружали результат на stage-сервер, чтобы клиент видел результат. При этом какая-то функциональность была «в процессе» и на сервер попадал весь объём, который успели сделать за две недели. Это даёт максимальную прозрачность.
В процессе мы с клиентом поняли, что хотим приблизиться к эталонной разработке по SCRUM. Поэтому после каждого спринта приносили полностью готовый продукт к релизу.
И про прозрачность мы тоже не забыли — добавили клиента в проект на гитхабе, так что текущий результат можно было наблюдать хоть каждый день.
В итоге: раз в 2 недели у нас был полностью рабочий продукт, но с ограниченной функциональностью
Результаты
- Настроили работу с данными, чтобы клиент не отходил от привычных ему сервисов
- Выстроили прозрачную работу с клиентом, чтобы он каждый день мог смотреть на результаты работы
- Разобрались с новым сервисом Supabase. Теперь знаем все его плюсы и минусы для работы с данными
Клиент остался доволен результатом и даже успел презентовать сайт на конференции. Фоточки не покажем, но там всё красиво получилось.
Технологии проекта
Основной фреймворк для фронтенд и бэкенд: Next.js
Базы данных: Notion, Superbase
ORM: Drizzle