Разработка · 6 мин чтения

Supabase панель администратора на React: подключение и настройка

Supabase панель администратора на React - связка, которую я в этом году собирал для трёх разных проектов: интернет-магазина, внутренней CRM логистической компании и сервиса бронирования. Задача каждый раз одна и та же - дать менеджерам рабочий интерфейс для заказов, товаров и пользователей, не поднимая отдельный бэкенд с нуля. Supabase закрывает базу данных на Postgres, аутентификацию, права доступа и хранилище файлов, а React берёт на себя интерфейс. На выходе - рабочая панель за 2-3 недели вместо месяца на классическом стеке вроде Laravel или Django.

Зачем Supabase для админ-панели, а не самописный бэкенд

Supabase поднимает Postgres и сразу генерирует REST и GraphQL API поверх таблиц - не нужно писать контроллеры для базовых операций чтения и записи. Аутентификация идёт в комплекте: email и пароль, магическая ссылка, OAuth через Google или GitHub. Для внутренней панели обычно хватает почты и пароля с приглашением по ссылке.

Row Level Security - главное, за что я выбираю Supabase для админок. Правила доступа описываются на уровне строк таблицы, а не размазываются по коду бэкенда: менеджер видит только заказы своего региона, оператор склада - только товары своей категории, и это настраивается в базе, а не в трёх местах фронтенда.

Realtime-подписки закрывают ещё одну задачу - обновление статусов на лету, без ручного рефреша страницы. Для панели заказов это ощущается как отдельная фича, хотя по факту - одна строчка кода.

Если в проекте сложная бизнес-логика - многошаговые согласования, интеграция с эквайрингом вроде Т‑Банка с обработкой вебхуков и возвратов, синхронизация с 1С - Supabase такое тянет с оговорками. Для таких случаев я обычно закладываю отдельный бэкенд на Laravel (от 100 000 ₽), а Supabase оставляю только под данные и авторизацию.

Настройка проекта Supabase: таблицы, RLS и ключи API

Создаю проект на supabase.com, выбираю регион ближе к пользователям панели - для российских проектов обычно Frankfurt или Singapore, задержка ощутимо ниже, чем на американских дата-центрах.

В Table Editor завожу таблицы под сущности панели: orders, products, profiles. Для каждой сразу включаю Row Level Security - по умолчанию Supabase создаёт таблицу с выключенным RLS, и это ловушка, в которую попадают чаще, чем кажется. Видел проект, где таблица с email и телефонами клиентов неделю висела в открытом доступе именно из-за этого - RLS просто забыли включить после создания таблицы.

Дальше - ключи. В настройках проекта их два: anon (публичный, безопасен для фронтенда) и service_role (полный доступ в обход RLS). Service_role используется только на сервере - в Edge Functions или на своём бэкенде, никогда не в React-коде, даже если «это же внутренняя панель для своих». Утечка такого ключа через собранный бандл открывает всю базу целиком.

Для каждой таблицы сразу пишу политики доступа: кто читает, кто пишет, при каком условии. Без политик при включённом RLS таблица просто недоступна никому - это защита по умолчанию, а не баг конфигурации.

Подключение Supabase-клиента к React-проекту

Ставлю официальный клиент и создаю файл с инициализацией - обычно src/lib/supabase.js. Ключи храню в переменных окружения, а не в коде, чтобы развести dev и prod проекты Supabase без правки исходников.

npm install @supabase/supabase-js

import { createClient } from '@supabase/supabase-js'

const supabase = createClient(
  import.meta.env.VITE_SUPABASE_URL,
  import.meta.env.VITE_SUPABASE_ANON_KEY
)

export default supabase

Для входа в панель использую signInWithPassword - простой email и пароль подходят для внутреннего инструмента лучше, чем OAuth: не нужно объяснять бухгалтеру, что такое вход через Google. Сессию Supabase хранит в localStorage и обновляет токен сама, поэтому на фронтенде остаётся только проверка - есть активная сессия или нет - и редирект на страницу логина при её отсутствии.

const { data, error } = await supabase.auth.signInWithPassword({
  email,
  password,
})

if (error) {
  setError('Неверный логин или пароль')
}

Бесплатный материал

🎁 Полезный скрипт в подарок

Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.

Без спама. Отписка в 1 клик.

CRUD-операции и realtime-обновления в панели

Базовые операции - чтение списка, обновление статуса, удаление записи - ложатся в несколько строк без отдельного API-слоя. Для панели заказов беру список с сортировкой по дате, для карточки - один запрос по id.

Обновление статуса заказа менеджером - самый частый сценарий. В паре проектов на update я вешаю realtime-подписку, которая через n8n (автоматизация от 25 000 ₽) отправляет вебхук в Telegram-бота на aiogram, и ответственный сотрудник получает уведомление о смене статуса без захода в панель. Похожая схема стояла у меня для интеграции с трекингом СДЭК - как только заказ переходил в статус «передан в СДЭК», бот в Telegram присылал трек-номер клиенту.

const { data: orders } = await supabase
  .from('orders')
  .select('id, status, total, created_at')
  .order('created_at', { ascending: false })

await supabase
  .from('orders')
  .update({ status: 'shipped' })
  .eq('id', orderId)

supabase
  .channel('orders-changes')
  .on('postgres_changes', { event: 'UPDATE', schema: 'public', table: 'orders' }, (payload) => {
    console.log('Заказ обновлён', payload.new)
  })
  .subscribe()

Роли и права доступа в Supabase панели

Для панели с несколькими ролями - админ, менеджер, оператор склада - завожу таблицу profiles с полем role, привязанную к auth.users по id. Политики RLS дальше проверяют роль текущего пользователя через вложенный запрос к profiles или через кастомный JWT claim, если ролей много и подзапрос в каждой политике начинает бить по производительности.

Пример условия в политике на обновление заказов - доступ разрешён, только если у текущего пользователя в profiles стоит role = 'admin' или role = 'manager'. Оператор склада с ролью warehouse такую строку изменить не может, даже если знает id записи и дёргает API напрямую в обход интерфейса.

Проверяю права всегда с чужого аккаунта, а не только по коду фронтенда - RLS должен резать доступ на уровне базы. Если политика неправильная, а фронт просто «не показывает» кнопку удаления, это не защита, а фасад, который обходится одним запросом через devtools.

Supabase против альтернатив: что выбрать для админ-панели

Перед стартом обычно сравниваю четыре варианта - вот как они выглядят на практике по срокам и гибкости.

Вариант Запуск Гибкость ролей Когда выбрать
Supabase 2-3 недели RLS из коробки, свой сервер не нужен Стандартный CRUD, MVP, внутренние панели
Firebase 2-3 недели Security Rules, менее гибко для сложных ролей Мобильные проекты, простая логика
Свой бэкенд на Laravel от 4-6 недель Полный контроль над логикой Сложная бизнес-логика, интеграции с 1С и эквайрингом
No-code (Tilda + скрипты) 1-2 недели Ограниченная Простая витрина без сложной админки

Если логика панели выходит за рамки CRUD - нужны отчёты с агрегацией по нескольким источникам, интеграция с 1С или сложные роли с делегированием - соберу CRM или админ-панель на React под ключ, с архитектурой под конкретные процессы, а не подгонкой под ограничения одного сервиса.

Кастомный CRM/админ-интерфейс

Админка / CRM

от 100 000 ₽

Подробнее →

Частые вопросы

Сколько стоит подключить Supabase к готовой React-панели?

Зависит от объёма таблиц и ролей. Если каркас панели уже есть и нужно только развернуть базу, RLS и авторизацию - такая доработка укладывается в стоимость кастомного скрипта от 3 000 ₽. Полноценная CRM или админ-панель на React с нуля, с ролями, CRUD-интерфейсами и интеграциями - от 100 000 ₽. На консультации (от 3 000 ₽) обычно за час прикидываю точный объём под конкретный проект.

Нужен ли отдельный бэкенд, если использую Supabase?

Для большинства внутренних панелей - нет, автосгенерированного API и Edge Functions хватает. Отдельный бэкенд на Laravel (от 100 000 ₽) добавляю, когда бизнес-логика тяжелее CRUD: сложные расчёты, синхронизация с внешними системами вроде 1С или банковского эквайринга, где нужен полный контроль над транзакциями.

Как защитить админ-панель от доступа обычных пользователей?

Основная защита - RLS-политики на уровне базы, а не проверки в React-компонентах. Роль пользователя храню в отдельной таблице profiles и проверяю в каждой политике на select, insert, update и delete. Дополнительно закрываю саму страницу входа по домену или IP на уровне хостинга, если панель не должна быть публично доступна вообще.

Можно ли перенести данные с Supabase на свой сервер позже?

Да, под капотом обычный Postgres, экспорт делается стандартным pg_dump без привязки к проприетарному формату. Переносил так один проект на выделенный сервер, когда команда выросла и потребовался больше контроля над бэкапами - заняло около дня вместе с переносом Edge Functions на отдельный воркер.

Есть задача?

Обсудим в мессенджере

Расскажите, что нужно сделать — отвечу в течение 4 часов в рабочее время. Первая консультация бесплатно.

Самозанятый Калинкин Н. А. · работаю с физлицами и юрлицами

Продолжая пользование настоящим сайтом Вы выражаете своё согласие на обработку Ваших персональных данных (файлов куки) с использованием Yandex.Metrika.
Понятно