Интеграция Notion с Express и React

Зачем использовать Notion как CMS
Notion предоставляет гибкую систему баз данных, удобный веб-интерфейс и API для автоматизации. Это делает Notion удобным вариантом для приложений, которым нужна простая CMS без развёртывания собственной панели управления. Кратко:
- Подходит для быстрых MVP и внутренних инструментов.
- Упрощает редактирование контента для нетехнических сотрудников.
- Позволяет хранить структуры данных и извлекать их через API.
Определение: Notion API — HTTP API и официальная библиотека клиента, которая позволяет читать и записывать страницы и базы данных Notion программно.
Важно: Notion хорош для контента и управления, но не заменяет полнофункциональные headless CMS для высоконагруженных публичных сайтов без дополнительных оптимизаций.
Быстрый обзор архитектуры
- Клиент (React) — форма и отображение данных, отправляет POST/GET на ваш сервер.
- Сервер (Express) — хранит токен интеграции, валидацию, взаимодействует с Notion через клиентскую библиотеку @notionhq/client.
- Notion Database — место хранения строк (страниц) с полями, такими как Fullname, CompanyRole, Location.
1. Создание интеграции Notion (Internal Integration)
- Перейдите на страницу интеграций Notion, войдите в свой аккаунт и нажмите New Integration.
- Дайте имя интеграции, выберите права доступа (Capabilities) и нажмите Submit.
- Скопируйте секретный Internal Integration Token и сохраните его в безопасном месте.
Совет: выдавайте интеграции минимально необходимые права (Least Privilege). Если интеграция только пишет в конкретную базу — не давайте глобальных прав на чтение всех страниц.
2. Создание базы данных Notion и подключение интеграции
- В рабочем пространстве Notion нажмите New Page и создайте базу данных (Table).
- Настройте столбцы (поля) таблицы: Fullname (Title), CompanyRole (Rich Text), Location (Rich Text).
- Откройте базу как полноэкранную страницу, чтобы увидеть URL и найти database_id.
- Database ID — строка в URL между последним слэшем и вопросительным знаком.
- Подключите интеграцию к базе: в правом верхнем углу нажмите три точки, затем Add connections и выберите интеграцию.
Важно: без подключения база не будет доступна интеграции даже при наличии токена.
3. Создание Express-сервера
В корне проекта создайте папку сервера и установите зависимости:
npm install @notionhq/client cors body-parser dotenvСоздайте .env в корне сервера и добавьте:
NOTION_INTEGRATION_TOKEN = 'your Integration secret token'
NOTION_DATABASE_ID = 'database ID'Откройте index.js и добавьте следующий код (пример рабочей реализации):
const express = require('express');
const {Client} = require('@notionhq/client');
const cors = require('cors');
const bodyParser = require('body-parser');
const jsonParser = bodyParser.json();
const port = process.env.PORT || 8000;
require('dotenv').config();
const app = express();
app.use(cors());
const authToken = process.env.NOTION_INTEGRATION_TOKEN;
const notionDbID = process.env.NOTION_DATABASE_ID;
const notion = new Client ({auth: authToken});
app.post('/NotionAPIPost', jsonParser, async(req, res) => {
const {Fullname, CompanyRole, Location} = req.body;
try {
const response = await notion.pages.create({
parent: {
database_id: notionDbID,
},
properties: {
Fullname: {
title: [
{
text: {
content: Fullname
},
},
],
},
CompanyRole: {
rich_text: [
{
text: {
content: CompanyRole
},
},
],
},
Location: {
rich_text: [
{
text: {
content: Location
},
},
],
},
},
});
res.send(response);
console.log("success");
} catch (error) {
console.log(error);
}
});
app.get('/NotionAPIGet', async(req, res) => {
try {
const response = await notion.databases.query({
database_id: notionDbID,
sorts: [
{
timestamp: 'created_time',
direction: 'descending',
},
]
});
res.send(response);
const {results} = response;
console.log("success");
} catch (error) {
console.log(error);
}
});
app.listen(port, () => {
console.log('server listening on port 8000!');
});Что делает серверный код
- Инициализирует клиент Notion с токеном интеграции.
- POST /NotionAPIPost: создаёт новую страницу в базе данных с указанными свойствами.
- GET /NotionAPIGet: запрашивает записи из базы данных и сортирует их по времени создания.
Рекомендации по улучшению:
- Добавьте валидацию входных данных и возврат понятных кодов ошибок клиенту.
- Обрабатывайте исключения и возвращайте HTTP-статусы (400/401/500).
- Логирование ошибок в централизованный сервис (Sentry, Logstash).
- Реализуйте ограничение частоты запросов (rate limiting) и повторную попытку (retry) при сетевых ошибках.
4. Создание React-клиента
В корне проекта создайте React-приложение и установите Axios:
npm install axiosЗамените содержимое src/App.js этим кодом:
import React, { useState} from 'react';
import Axios from 'axios';
function App() {
const [name, setName] = useState("");
const [role, setRole] = useState("");
const [location, setLocation] = useState("");
const [APIData, setAPIData] = useState([]);
const handleSubmit = (e) => {
e.preventDefault();
Axios.post('http://localhost:8000/NotionAPIPost', {
Fullname: name,
CompanyRole:role,
Location:location
}).catch(error => {
console.log(error);
});
Axios.get('http://localhost:8000/NotionAPIGet')
.then(response => {
setAPIData(response.data.results);
console.log(response.data.results);
}).catch(error => {
console.log(error);
});
};
return (
API DATA
{
APIData.map((data) => {
return (
Name: {data.properties.Fullname.title[0].plain_text}
Role: {data.properties.CompanyRole.rich_text[0].plain_text}
Location: {data.properties.Location.rich_text[0].plain_text}
)
})
}
);
}
export default App; Пояснение:
- Компонент использует useState для управления формой.
- При отправке формы сначала POST, затем GET для обновления списка.
- В реальном приложении лучше держать порядок: дождаться ответа POST, затем запросить свежие данные.
Практические рекомендации и распространённые ошибки
- Неправильный database_id: убеждайтесь, что вы копируете ID без лишних символов.
- Токен интеграции не действует, если интеграция не подключена к базе.
- Ошибки CORS: позаботьтесь, чтобы сервер выставлял корректные заголовки Access-Control-Allow-Origin.
- Обработка пустых полей в ответах Notion: rich_text и title могут быть пустыми массивами — проверяйте существование перед доступом.
Пример безопасного доступа:
const getPlainText = (prop) => {
if (!prop) return '';
if (prop.title && prop.title.length) return prop.title[0].plain_text || '';
if (prop.rich_text && prop.rich_text.length) return prop.rich_text[0].plain_text || '';
return '';
}Безопасность и эксплуатация
- Храните секреты в переменных окружения или в секретном хранилище (HashiCorp Vault, AWS Secrets Manager).
- Ограничьте доступ к серверу и используйте HTTPS в продакшене.
- Регулярно вращайте (rotate) интеграционные токены.
- Логи не должны содержать секретные значения.
- Применяйте CORS и CSRF-защиту.Важно контролировать права интеграции и давать минимально необходимые разрешения.
Критерии приёмки
- Форма в React отправляет запрос и отвечает кодом 200 при успешной записи.
- Запись появляется в базе Notion и отображается на клиенте после обновления.
- Сервер возвращает понятные ошибки для неверного payload и для проблем авторизации.
- Логи ошибок доступны в системе мониторинга и не содержат токена.
Тесты и кейсы приёма
- Позитивный сценарий: отправить валидные данные → проверить появление записи в Notion.
- Негативный сценарий: отправить пустые поля → сервер возвращает 400.
- Сценарий отказа авторизации: неверный токен → 401 и понятный лог.
- Интеграционный тест: end-to-end тест, который использует тестовую базу в Notion (изолированную).
Мероприятие при инциденте (Runbook)
- Симптом: пользователи не видят новые записи.
- Шаг 1: проверить логи сервера на ошибки 4xx/5xx.
- Шаг 2: проверить статус токена и подключение интеграции к базе в Notion.
- Шаг 3: выполнить тестовый запрос к Notion API с curl или Postman и проверить ответ.
- Шаг 4: при утечке токена — немедленно отозвать токен, сгенерировать новый и обновить переменные окружения.
Пример проверки curl:
curl -X GET "https://api.notion.com/v1/databases/{database_id}/query" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Notion-Version: 2022-06-28"(Проверьте актуальную версию заголовка Notion-Version в официальной документации.)
Карта принятия решений (Mermaid)
flowchart TD
A[Нужно использовать Notion?] -->|Внутренний инструмент, быстрый MVP| B[Использовать Notion]
A -->|Высокая нагрузка, сложная схема| C[Рассмотреть специализированный headless CMS]
B --> D[Настроить интеграцию и базу]
D --> E[Сервер на Express + клиент React]
E --> F[Добавить безопасность и мониторинг]Роли и чеклисты
Разработчик фронтенда:
- Реализовать форму с валидацией.
- Обработать ошибки API и состояния загрузки.
- Тестировать рендер свойств Notion (проверять пустые массивы).
Разработчик бэкенда:
- Безопасно хранить токены.
- Валидировать входящие данные.
- Логировать ошибки и ответы API.
DevOps:
- Хранение секретов, HTTPS, мониторинг.
- Настроить CI/CD, секреты в окружении.
Продукт/Контент-менеджер:
- Настроить поля базы данных.
- Описать правила ввода данных и права доступа.
Миграции и изменения схемы
- Изменения структуры свойств (переименование поля) ломают существующий код — документируйте схему и вносите изменения поэтапно.
- Для сложных миграций создайте скрипт, который читает старые страницы и создаёт новые с новой структурой.
Совместимость и ограничения
- Notion API может иметь ограничения по скорости запросов — реализуйте backoff и retry.
- Свойства типа rich_text или title могут иметь вложенные элементы — парсите аккуратно.
- Для больших объёмов данных планируйте пагинацию при запросе баз данных.
Конфиденциальность и соответствие требованиям
- Если вы храните персональные данные (ФИО, адрес, контакт), оцените требования местного законодательства по защите данных.
- Для GDPR: документируйте правовые основания хранения и срок хранения, предоставьте возможность удаления данных по запросу.
Полезные сниппеты и чек-листы
- Безопасный доступ к полю:
const safeGet = (obj, path, fallback = '') => {
try { return path.split('.').reduce((o,k) => o[k], obj) || fallback } catch { return fallback }
}- Минимальный конфиг .env в продакшене: держите в CI/CD, не коммитьте в git.
Краткое резюме
Notion — удобный инструмент для быстрой CMS-реализации. Архитектура: React → Express → Notion. Следите за безопасностью токенов, валидацией данных и обработкой ошибок. Документируйте схему базы данных и имейте план миграции.
Важные шаги: создать интеграцию, получить database_id, подключить интеграцию к базе, реализовать серверный слой с @notionhq/client и безопасно хранить секреты.
Спасибо за чтение. Удачной интеграции!