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