Notion как CMS: интеграция с React и Express

Notion — гибкий инструмент продуктивности, который часто используют как CMS: он позволяет хранить данные, управлять задачами и моделировать рабочие процессы через базы данных. Благодаря публичному API вы можете интегрировать Notion с собственным приложением и автоматизировать обмен данными.
Коротко: Notion предоставляет REST-подобный API и официальный клиент для Node.js, а также возможность создавать интеграции с секретным токеном. В этом материале описана стандартная архитектура: React (фронтенд) → Express (бекенд) → Notion API.
Важно: в примерах используется секретный токен интеграции и ID базы данных. Храните такие данные в переменных окружения и не публикуйте их в публичных репозиториях.
Основные понятия
- Интеграция Notion: приложение, зарегистрированное в Notion, получающее Internal Integration Token для доступа к API.
- Database ID: уникальный идентификатор вашей базы данных в URL.
- Notion client: официальный npm-пакет @notionhq/client для взаимодействия с API.
Цели статьи
- Настроить интеграцию Notion и получить токен.
- Создать базу данных в рабочей области Notion и подключить интеграцию.
- Развернуть Express-сервер, который читает и записывает данные в Notion.
- Реализовать React-клиент, отправляющий POST и получающий GET.
- Рассмотреть безопасность, отладку и сценарии использования в прод.
1. Настройка интеграции Notion
Чтобы интеграция могла работать с вашей базой данных, создайте её в панели Notion:
- Откройте страницу интеграций Notion и войдите в аккаунт.
- На странице обзора интеграций нажмите New Integration и начните создание новой интеграции.
Укажите название интеграции и выберите нужные возможности (capabilities): чтение, запись и т. п. Эти настройки определяют, что ваше приложение может делать с данными Notion.
Нажмите Submit, чтобы создать интеграцию.
Скопируйте секретный Internal Integration Token и сохраните его в безопасном месте (например, в .env-файле). Нажмите Save Changes.
Важно: токен — это «ключ» к вашему API. Если токен скомпрометирован, отозовите его в настройках интеграции.
2. Создание базы данных в Notion
После создания интеграции вам нужна база данных, с которой будет работать приложение.
- Войдите в рабочую область Notion.
- Нажмите кнопку New Page в левом меню.
- Выберите тип таблицы (Table) и укажите имя базы данных.
- Добавьте поля (столбцы), которые нужны вашему приложению, с помощью кнопки + в заголовке таблицы.
- Нажмите Open as Full Page, чтобы открыть базу как отдельную страницу. В адресной строке появится URL с идентификатором базы данных.
- Извлеките Database ID: это часть URL между последним слэшем (/) и вопросительным знаком (?).
- Подключите базу к вашей интеграции: на странице базы нажмите «•••» (троеточие) в правом верхнем углу, выберите Add Connections, найдите вашу интеграцию и подключите её.
Результат: интеграция получает разрешение на чтение/запись в выбранную базу данных.
3. Создание Express-сервера
На бекенде используем официальный клиент @notionhq/client и минимальный Express-сервер, обменивающийся данными с фронтендом.
Подготовка проекта сервера:
- Создайте папку проекта и перейдите в неё.
- Инициализируйте npm (npm init) и установите зависимости:
npm install @notionhq/client cors body-parser dotenv expressПояснение: cors нужен для обмена между frontend и backend, body-parser — для парсинга JSON, dotenv — для переменных окружения, express — веб-сервер.
Создайте файл .env в корне сервера и добавьте туда:
NOTION_INTEGRATION_TOKEN='your_integration_secret_token'
NOTION_DATABASE_ID='your_database_id'Не храните .env в публичных репозиториях — добавьте его в .gitignore.
Пример index.js для Express
const express = require('express');
const { Client } = require('@notionhq/client');
const cors = require('cors');
const bodyParser = require('body-parser');
require('dotenv').config();
const app = express();
app.use(cors());
app.use(bodyParser.json());
const port = process.env.PORT || 8000;
const authToken = process.env.NOTION_INTEGRATION_TOKEN;
const notionDbID = process.env.NOTION_DATABASE_ID;
const notion = new Client({ auth: authToken });
app.post('/NotionAPIPost', 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);
res.status(500).send({ error: 'Notion API 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);
console.log('success');
} catch (error) {
console.log(error);
res.status(500).send({ error: 'Notion API error' });
}
});
app.listen(port, () => {
console.log(`server listening on port ${port}!`);
});Коротко о логике:
- Инициализация клиента Notion через токен.
- POST /NotionAPIPost создаёт новую страницу (запись) в базе данных с указанными свойствами.
- GET /NotionAPIGet запрашивает записи базы и возвращает их в ответе.
Запустите сервер командой (предположим, что в package.json указан скрипт start):
npm startДля разработки удобно использовать nodemon (devDependency и скрипт “dev”).
4. Настройка React-клиента
Создайте клиент в корне проекта:
npx create-react-app client
cd client
npm install axiosВ компоненте src/App.js используйте следующий код (удалите boilerplate перед вставкой):
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) => (
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;Запустите клиент командой:
npm startОткройте http://localhost:3000 и протестируйте форму.
5. Notion как CMS: когда это удобно и когда нет
Преимущества использования Notion как CMS:
- Быстрая настройка структуры контента без базы данных.
- Доступная интерфейсная редакция контента для контент-менеджеров.
- История изменений и совместная работа.
Ограничения и когда Notion не подходит:
- Ограничения по скорости и лимитам API при больших объёмах (batch-операции сложнее).
- Отсутствие сложных транзакций и продвинутых запросов как в SQL.
- Ограничения по схеме: Notion даёт гибкость, но она может усложнить валидацию данных.
Альтернативы: Airtable (похож на таблицы с API), Firebase/Firestore (реaltime, масштабируемость), PostgreSQL + CMS (более строгая модель данных).
6. Безопасность и конфиденциальность
- Храните NOTION_INTEGRATION_TOKEN и NOTION_DATABASE_ID в переменных окружения.
- Отключите публичный доступ к интеграции, если он не нужен.
- В проде проксируйте запросы через сервер (не храните токен в браузере).
- Логи: не выводите секреты в логах.
GDPR и личные данные:
- Если вы храните персональные данные (имена, местоположение), документируйте основание обработки и срок хранения.
- Обеспечьте возможность удаления/экспорта данных по запросу пользователя.
7. Практические рекомендации и лучшие практики
- Валидация: всегда проверяйте входящие данные на бекенде перед отправкой в Notion.
- Транзакции: Notion не поддерживает ACID-транзакции — проектируйте обработку ошибок и компенсационные операции.
- Pagination: при больших объёмах используйте методы пагинации API.
- Ограничения скорости: добавьте retry с экспоненциальной задержкой на случай 429.
8. Критерии приёмки
- Интеграция создана и токен хранится в .env.
- База данных создана, интеграция подключена через Add Connections.
- POST запрос создаёт запись с корректными свойствами.
- GET возвращает данные в ожидаемом формате и отображает их на клиенте.
- Валидация и обработка ошибок на сервере реализованы.
9. Отладка и распространённые ошибки
- 401 Unauthorized: проверьте токен интеграции и что интеграция подключена к базе.
- 400 Bad Request: проверьте структуру properties при вызове notion.pages.create.
- CORS ошибки: убедитесь, что app.use(cors()) настроен и фронтенд делает запросы на правильный порт.
- Пустые поля в ответе: проверьте наличие значений и их типы (title vs rich_text).
10. Роль‑ориентированные контрольные списки
Разработчик:
- Добавить .env и .gitignore.
- Реализовать валидацию и обработку ошибок.
- Настроить CI для безопасного хранения секретов.
Продукт-менеджер:
- Определить набор полей базы данных.
- Согласовать права доступа пользователей.
QA:
- Прописать тесты для POST/GET сценариев.
- Проверить поведение при сетевых ошибках и при пустых значениях.
DevOps:
- Настроить секреты в окружении продакшена (Vault, Secrets Manager).
- Настроить мониторинг и алерты на ошибки 5xx и 429.
11. Тестовые сценарии и критерии приёмки
- Тест 1: отправка валидных данных — запись создаётся и отображается в UI.
- Тест 2: отправка пустых полей — сервер возвращает 400 с объяснением.
- Тест 3: при неверном токене — сервер возвращает 500/401, лог содержит ошибку, но не токен.
- Тест 4: симуляция лимита API — retry с backoff срабатывает или корректно логируется.
12. Мини‑плейбук развертывания
- Подготовка: создать интеграцию, собрать токен, создать базу и подключить интеграцию.
- Бекенд: прописать .env, установить зависимости, запустить npm start/pm2.
- Фронтенд: собрать production-бандл и разместить на CDN/сервере.
- Переменные окружения: хранить в Secrets Manager.
- Мониторинг: настроить логирование ошибок и алерты.
13. Шаблон .env и package.json (примеры)
.env:
NOTION_INTEGRATION_TOKEN='your_integration_secret_token'
NOTION_DATABASE_ID='your_database_id'
PORT=8000package.json (скрипты):
{
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js"
}
}14. Когда стоит выбрать другие подходы
- Нужны сложные запросы/агрегации — используйте реляционную БД (PostgreSQL).
- Требуется высокая пропускная способность и реальное время — рассмотрите Firebase или собственный API с кешированием.
- Для табличных сценариев с мощным API Airtable может быть удобнее.
Заключение
Notion отлично подходит для прототипов, MVP и сценариев, где контент-менеджеры хотят редактировать данные напрямую через удобный UI. Интеграция с React и Express даёт быстрый путь к продакшену, но требует продуманного подхода к безопасности, обработке ошибок и масштабированию.
Важно: тестируйте поведение при ошибках API и храните секреты безопасно.
Краткое резюме:
- Настройте интеграцию Notion и сохраните токен в .env.
- Создайте базу и подключите интеграцию через Add Connections.
- Реализуйте Express-сервер с @notionhq/client и маршруты POST/GET.
- Сделайте React-клиент, отправляющий данные и отображающий результаты.
Примечание: этот материал ориентирован на небольшие и средние проекты; для больших нагрузок продумывайте архитектуру и альтернативы.
Похожие материалы
Сворачивание разделов в Word — как и зачем
Как оставаться мобильным без смартфона
Перекрёстные ссылки в Microsoft Word
Тени в PowerPoint: как добавить drop shadow