Проблема ручної синхронізації контенту та її вирішення через Notion API
Уявіть: ваша команда веде документацію в Notion, а сайт працює на WordPress. Кожне оновлення статті потребує ручного копіювання — на це йде до 2 годин на тиждень. Помилки неминучі: забули оновити посилання, втратили форматування. Ми зіткнулися з цим на проекті з 200+ сторінками документації — синхронізація вручну забирала понад 40 годин на місяць. Рішення — використовувати Notion як headless CMS через API. База даних Notion стає єдиним джерелом даних для блогу, документації або каталогу. Редагуєте в Notion — сайт оновлюється автоматично. За останні 5 років ми реалізували понад 15 таких інтеграцій — підхід перевірений на проектах від стартапів до enterprise з об'ємом контенту до 5000 сторінок.
За даними Notion API documentation, API дозволяє гнучко працювати з базами даних та блоками. Однак без грамотного кешування та архітектури ви швидко впертеся в rate limit у 3 запити на секунду. Розберемо, як це обійти.
Як ми реалізуємо інтеграцію Notion API
Робота з базами даних Notion
import { Client, isFullPage } from '@notionhq/client';
const notion = new Client({ auth: process.env.NOTION_API_KEY });
// Отримання записів з бази даних
async function getBlogPosts(): Promise<BlogPost[]> {
const response = await notion.databases.query({
database_id: process.env.NOTION_BLOG_DB!,
filter: {
property: 'Published',
checkbox: { equals: true }
},
sorts: [{ property: 'Date', direction: 'descending' }],
});
return response.results
.filter(isFullPage)
.map(page => ({
id: page.id,
title: (page.properties.Title as any).title[0]?.plain_text ?? '',
slug: (page.properties.Slug as any).rich_text[0]?.plain_text ?? '',
date: (page.properties.Date as any).date?.start ?? '',
excerpt: (page.properties.Excerpt as any).rich_text[0]?.plain_text ?? '',
cover: page.cover?.type === 'external' ? page.cover.external.url : null,
tags: (page.properties.Tags as any).multi_select.map((t: any) => t.name),
}));
}
Отримання контенту сторінки
Notion зберігає контент як блоки. notion-to-md конвертує їх у Markdown:
import { NotionToMarkdown } from 'notion-to-md';
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkHtml from 'remark-html';
const n2m = new NotionToMarkdown({ notionClient: notion });
async function getPageContent(pageId: string): Promise<string> {
const mdBlocks = await n2m.pageToMarkdown(pageId);
const mdString = n2m.toMarkdownString(mdBlocks);
const result = await unified()
.use(remarkParse)
.use(remarkHtml)
.process(mdString.parent);
return String(result);
}
ISR з on-demand revalidation
При зміні запису в Notion — Zapier або Make.com викликають webhook сайту, який інвалідує кеш конкретної сторінки:
// Next.js: on-demand revalidation
export async function POST(request: Request) {
const { page_id, slug } = await request.json();
await revalidatePath(`/blog/${slug}`);
await revalidatePath('/blog');
return Response.json({ revalidated: true });
}
Порівняння продуктивності Notion API та традиційної CMS
За швидкістю впровадження інтеграція Notion випереджає класичні CMS: налаштування займає 3–5 днів проти 5–10 днів для WordPress, якщо рахувати лише базову функціональність. На продуктивність впливає кешування — при правильній архітектурі час завантаження сторінок знижується в 3–5 разів порівняно з прямими запитами до API.
| Критерій |
Notion API |
Традиційна CMS (WordPress) |
| Інтерфейс редагування |
Звичний Notion, без навчання |
Специфічна адмінка |
| Гнучкість даних |
Вільна схема баз даних |
Фіксовані типи записів |
| Продуктивність |
Потребує кешування (rate limit) |
Залежить від хостингу |
| Вартість ліцензії |
Безкоштовно (до 1000 блоків на сторінку) |
Безкоштовно/платні теми |
| Розробка під ключ |
3–5 днів |
5–10 днів |
Порівняння з платними headless CMS
| Критерій |
Notion API |
Contentful |
Strapi |
| Щомісячна вартість |
Безкоштовно |
Платний |
Безкоштовно (self-hosted) |
| Контроль над інфраструктурою |
Ні (залежить від Notion) |
Повний |
Повний |
| Навчання команди |
Мінімум (Notion знайомий усім) |
1–2 дні |
1–2 дні |
Чому Notion підходить для блогу чи документації?
Для команд, які вже використовують Notion, це природний вибір: не потрібно вчити нову адмінку, контент зберігається у знайомій структурі баз даних. За нашою статистикою, час публікації статті скорочується на 60% — просто написали в Notion, виставили прапорець "Published" і готово. Додатковий плюс — безкоштовний тариф покриває до 1000 блоків на сторінку, чого вистачає для більшості статей.
Як обійти обмеження Notion API?
Головні обмеження: 3 запити на секунду та відсутність нативних вебхуків. Rate limit вирішується кешуванням — ми використовуємо Redis або CDN з TTL 1–5 хвилин. Для статичних сторінок (документація) цілком допустимо оновлювати кеш раз на годину. Вебхуки реалізуємо через Zapier або Make — вартість таких зв'язок невисока і окупається за рахунок відсутності необхідності у платній CMS. Практично 95% трафіку віддається з кешу, тому швидкість відгуку сайту залишається високою.
Забезпечення продуктивності при rate limit
Кеш — ваш головний інструмент. Ми комбінуємо Redis на сервері та CDN з тривалим TTL для статичних сторінок. Для динамічних розділів (наприклад, пошук) використовуємо edge-функції з коротким кешем або fallback на ISR. Такий підхід дозволяє тримати швидкість завантаження під контролем навіть при частих оновленнях контенту.
Чек-лист для запуску інтеграції
- Створити інтеграцію в Notion (отримати API-ключ).
- Налаштувати базу даних з потрібними полями.
- Розробити endpoint для отримання записів.
- Реалізувати кешування (Redis, CDN).
- Налаштувати webhook при зміні контенту.
- Протестувати оновлення сторінок.
Процес роботи та терміни
Етапи:
- Аналітика: вивчаємо структуру вашої Notion-бази, узгоджуємо схему даних.
- Проектування: обираємо стек (частіше Next.js + ISR), проектуємо компоненти.
- Реалізація: розробляємо API-шар, верстку, кешування.
- Тестування: перевіряємо коректність даних, час завантаження, обробку помилок.
- Деплой: розгортаємо на вашому хостингу, налаштовуємо вебхуки.
Що входить у роботу
- Документація щодо API та структури даних.
- Вихідний код з коментарями.
- Доступи до сервера та репозиторію.
- Навчання команди роботі з інтеграцією.
- Гарантія 30 днів на усунення дефектів.
Терміни: базова інтеграція (список + детальна сторінка) — 3–5 робочих днів. Складні проекти — до 3 тижнів. Зв'яжіться з нами для точної оцінки вашого проекту. Замовте інтеграцію Notion API під ключ та отримайте консультацію безкоштовно.
Розробка API: REST, GraphQL, WebSocket, tRPC
До нас приходить клієнт з Postman-колекцією на 200 ендпоінтів і каже: «Все працює, але фронтенд гальмує». Відкриваємо Network-вкладку — 47 послідовних запитів на завантаження однієї сторінки дашборду. Кожен чекає попереднього. Це не проблема швидкості сервера — це проблема архітектури API. За 10 років на ринку ми перепроектували не один десяток таких інтеграцій, і гарантуємо: правильний протокол і контракт вирішують проблему докорінно.
Коли REST перестає справлятися
REST добре працює для простих CRUD-операцій. Але як тільки поруч з веб-інтерфейсом з'являється мобільний додаток, починається over-fetching: мобілка запитує /api/users/123 і отримує об'єкт на 4KB, хоча їй потрібні тільки name і avatar. Помножте на список з 50 користувачів — 200KB трафіку замість 8KB.
GraphQL вирішує це через selection sets. Клієнт описує саме ті поля, які йому потрібні, і сервер повертає саме їх. На проекті з React Native + Next.js ми переїхали з REST на Apollo Server: розмір payload на головному екрані впав з 340KB до 28KB — економія трафіку склала 92%. Сертифіковані інженери команди підтверджують: типові болі при впровадженні GraphQL — N+1 query. Резолвер для поля author у поста викликає SELECT * FROM users WHERE id = ? для кожного поста у списку. На сторінці з 20 постами — 21 запит до бази. Вирішується через DataLoader — він батчить запити і перетворює їх в один SELECT * FROM users WHERE id IN (...).
Що таке tRPC і чим він кращий за REST/GraphQL?
Якщо весь стек на TypeScript (Next.js + Node/Bun), tRPC прибирає цілий шар проблем. Ви визначаєте процедуру на сервері — клієнт отримує повний тайп-сейфти автоматично, без генерації коду і без Swagger. Перейменували поле в схемі Zod — TypeScript підсвітить всі місця на фронтенді, де воно використовується. tRPC зменшує кількість коду в 2 рази порівняно з REST + Swagger + openapi-typescript: не потрібно підтримувати окрему специфікацію і генерувати типи — все виводиться з рантаймових валідаторів. Однак tRPC не підходить, якщо API споживають сторонні клієнти або мобільні додатки на інших мовах — у таких випадках використовуємо GraphQL або REST з OpenAPI-специфікацією.
WebSocket і реальний час: коли SSE, коли WS?
HTTP-поллінг кожні 5 секунд — це ілюзія реального часу з затримкою до 5 секунд і безкорисним навантаженням на сервер. Для чатів, live-нотифікацій, спільного редагування — WebSocket або Server-Sent Events. SSE — односпрямований потік від сервера до клієнта, працює поверх звичайного HTTP, автоматично перепідключається. Підходить для нотифікацій, стрімінгу даних, прогрес-барів. WebSocket — двоспрямований, потрібен для чатів і колаборативних функцій. Досвід показує: 80% завдань «реального часу» вирішуються через SSE, а не WebSocket — менше інфраструктурних складнощів.
Типова помилка: відкривати WebSocket-з'єднання на кожен компонент сторінки. На одному проекті дашборд відкривав 12 паралельних WS-з'єднань. Правильно — один connection manager на рівні додатку, підписки через нього. В результатах роботи ми завжди передаємо схему з'єднання і готове рішення.
| Протокол |
Типізація |
Over-fetching |
Версіонування |
Real-time |
| REST |
Слабка (OpenAPI) |
Присутній |
URL / Header |
Поллінг |
| GraphQL |
Сильна (SDL) |
Немає |
Deprecation |
Subscriptions |
| tRPC |
Повна (TypeScript) |
Немає |
TypeScript checks |
Subscriptions (optional) |
Swagger / OpenAPI як контракт
Документація, написана постфактум — застаріває на наступний день після релізу. Ми пишемо специфікацію OpenAPI 3.1 до початку розробки, вона стає контрактом між фронтендом і бекендом. Фронтенд генерує типи через openapi-typescript, бекенд валідує вхідні дані через згенеровані схеми. Розбіжність контракту з реалізацією ловиться на CI, а не на рев'ю. Для Laravel — l5-swagger або dedoc/scramble. Для Node.js — @fastify/swagger або Zod + zod-to-openapi.
Як правильно аутентифікувати API?
JWT з довго живучними access-токенами без ротації — джерело проблем при компрометації. Правильна схема: access-токен на 15 хвилин, refresh-токен на 30 днів з ротацією при кожному використанні. Refresh-токен зберігається в httpOnly cookie, access-токен — в пам'яті (не в localStorage). Для міжсервісної взаємодії — API Keys з scope-обмеженнями або mTLS. OAuth 2.0 з PKCE для публічних клієнтів (SPA, мобілки).
Версіонування і зворотна сумісність
Ламаючі зміни в API без версіонування ламають клієнтів. Три підходи ми використовуємо в проектах:
| Метод |
Приклад |
Коли застосовувати |
| URL-версіонування |
/api/v2/ |
REST API з довгою підтримкою legacy |
| Header-версіонування |
Accept: application/vnd.api+json;version=2 |
Мінімальні зміни в URL |
| Еволюційне (deprecation) |
Додавання полів, deprecated-директива GraphQL |
Для GraphQL — плавний вивід полів |
Зворотну сумісність ми гарантуємо через автомат-перевірки (oasdiff) на CI.
Як ми розробляємо API: покроковий план
-
Аналітика — аудит поточних інтеграцій, складання схеми даних, вибір протоколу (REST/GraphQL/tRPC/WebSocket).
-
Проектування контракту — OpenAPI або SDL (GraphQL) до першого рядка коду.
-
Розробка — реалізація за контрактом, модульні тести на кожен ендпоінт.
-
Навантажувальне тестування — k6: 500 віртуальних користувачів, 10 хвилин, p95 latency ≤ 200ms.
-
Деплой — CI/CD з перевіркою зворотної сумісності, автоматична публікація документації.
-
Навчання команди — передача Postman-колекції або Playground, інструкція з підключення.
Типові помилки, які ми виключаємо
- N+1 при запитах без DataLoader.
- Відсутність rate limiting — DDOS через неавторизовані ендпоінти.
- Зберігання access-токена в localStorage.
- Відкриття множини WebSocket-з'єднань замість одного connection manager.
- Документація, не оновлена після релізу.
Що входить в роботу (deliverables)
- OpenAPI 3.1 специфікація (або SDL для GraphQL).
- Згенеровані клієнтські типи для TypeScript / Dart / Kotlin.
- Набір автотестів з покриттям всіх ендпоінтів (модульні + інтеграційні).
- Навантажувальні тести (k6) і звіт (p50/p95/p99 latency, RPS).
- Документація в Swagger UI / Redoc / GraphiQL.
- Навчання команди (2–4 години воркшопу).
- Підтримка протягом 30 днів після здачі (за договором).
Наш досвід
-
10+ років на ринку розробки API.
-
200+ завершених проектів (REST, GraphQL, WebSocket, tRPC).
-
50+ сертифікованих інженерів (AWS, Kubernetes, API Design).
- Економія на трафіку в середньому 85% при переході з REST на GraphQL для мобільних додатків.
-
100% зворотна сумісність — жодного зламаного клієнта за останні 3 роки.
Терміни
Розробка API для типового SaaS-проекту з 30–50 ендпоінтами: від 3 до 8 тижнів залежно від складності бізнес-логіки та кількості зовнішніх інтеграцій. Міграція існуючого REST API на GraphQL — від 2 до 6 тижнів. Додавання WebSocket-шару до готового бекенду — від 1 до 3 тижнів. Вартість розраховується індивідуально після аудиту. Отримайте консультацію — зв'яжіться з нами, щоб обговорити ваш проект.