CMS та управління контентом: WYSIWYG, медіабібліотека, галереї
Редактор на сайті — це інтерфейс, яким користуються щодня люди, не маючи відношення до розробки. Якщо в ньому незручно змінювати заголовок статті, не працює загрузка зображень або форматування сбивається при копіюванні з Word — контент либо не оновлюється, либо оновлюється з помилками. Це прямі втрати: застарілі ціни, неактуальні акції, SEO-тексти, які ніхто не править.
Вибір CMS: коли що підходить
Headless CMS (Strapi, Contentful, Sanity) розділяють управління контентом від фронтенду. Контент через API споживає будь-який клієнт: веб-сайт, мобільне застосунок, цифрові вивіски. Правильний вибір для омніканальних продуктів та коли фронтенд на React/Vue/Next.js.
Sanity виділяється кастомізованою Studio: кожне поле, кожен тип документа, кожен віджет — React-компонент, який можна замінити. Portable Text (їхній формат для rich content) портується у будь-який рендерер. Для складних редакторських workflow — найкращий вибір у своїй категорії.
Contentful — стабільний хмарний сервіс, великий marketplace розширень, хороша CDN для медіафайлів. Мінус — ціна при ростові обсягу контенту.
Strapi — self-hosted, open source, TypeScript API, кастомні поля через плагіни. Хостиш сам, дані твої.
Традиційний CMS (WordPress, Craft CMS, Statamic) — коли потрібен звичний редакторський інтерфейс та немає окремого фронтенд-проекту. Craft CMS — професійний інструмент для контент-команд: Matrix поля, гнучка структура записів, вбудована локалізація.
Вбудований у Laravel (Nova, Filament): коли застосунок вже на Laravel та немає сенсу додавати окремо CMS. Filament — сучасний, React+Livewire, багата екосистема плагінів.
WYSIWYG: Tiptap, Lexical, TinyMCE
Редактор — це окремена інженерна задача, не просто <textarea>.
Tiptap (обгортка над ProseMirror) — найкращий баланс кастомізованості та зручності. Кожен елемент редактора — розширення: заголовки, списки, таблиці, упомінання, блоки коду — додаються вибірково. Collaborative editing через Yjs — вбудовано. Для Next.js/React-проектів — перший вибір.
Lexical (Meta, open source) — високопродуктивний, extensible, написаний для Facebook. Складніше у налаштуванні ніж Tiptap, але потужніший у кастомізації. Підходить якщо потрібни нестандартні блоки.
TinyMCE — багаторічний стандарт для корпоративних CMS. Працює з коробки, знайомий багатьом редакторам. Мінус — застарілий API, важкий по бандлу (~300KB), менше контролю над структурою контенту.
Проблема всіх WYSIWYG: «грязний» HTML при вставці з Word. замість пробілів, inline-стилі на кожному тегу, вкладені <span> без сенсу. Sanitize на вставку обов'язковий — інакше вёрстка ломається, SEO страждає.
Медіабібліотека
Загрузка файлів через простий <input type="file"> з прямим збереженням на диск сервера — антипаттерн. Диск заповниться, масштабування неможливо, CDN не підключиш.
Правильна схема: загрузка в S3-сумісне сховище (AWS S3, Cloudflare R2, MinIO для self-hosted) → CDN поверх (CloudFront, Cloudflare) → трансформації по запиту.
Imgproxy або Thumbor для серверної трансформації зображень: один оригінальний файл, будь-які розміри та формати генеруються динамічно. URL несе параметри: https://img.example.com/resize:800:600/format:webp/plain/s3://bucket/photo.jpg. Оригінал зберігається один раз, похідні не потрібно зберігати.
Cloudflare Images — managed сервіс: завантажуєш оригінал, отримуєш варіантні URL для різних розмірів. $5 за 100k зображень з трансформаціями — часто дешевше self-hosted.
Для відео: Cloudflare Stream або Mux. Завантажуєш вихідник, платформа кодує в HLS, віддає адаптивний стриміг. Без цього відео файл важить 500MB та завантажується як є.
Організація галерей
Drag-and-drop сортування у галереї — базове вимога. @dnd-kit/sortable (React) або SortableJS — бібліотеки з accessibility-підтримкою. Сортування через цілочисельний order у базі даних: при кожній перестановці пересраховуються order значення тільки затронутих елементів.
Ленива загрузка зображень у галереї обов'язкова. loading="lazy" на <img> для нативної ленивої загрузки. Intersection Observer API для кастомного контролю. На галереї 200 фотографій без lazy loading — 150MB трафіку при відкритті сторінки.
Lightbox: Photoswipe або Glightbox — доступні, без jQuery, з touch-жестами та keyboard-навігацією.
Структурований контент vs free-form HTML
Free-form WYSIWYG створює непередбачуваний HTML. Через рік контент-менеджер поставив 7 різних розмірів шрифту, 12 кольорів, випадкові відступи. Редизайн неможливий без ручної чистки кожної сторінки.
Структурований контент: замість «як це виглядає» — «що це є». Не <p style="font-size:24px; color:red">Важливо!</p>, а тип блока callout з параметром variant: warning. CMS зберігає структуру, фронтенд вирішує як її рендерити.
Sanity Portable Text, Contentful Rich Text, Strapi Dynamic Zones — всі йдуть у цьому напрямку. Перехід з free-form HTML на structured content при міграції — трудомісткая задача, але окупається при наступному редизайні.
Процес роботи
Починаємо з аудиту редакторських сценаріїв: хто редагує, як часто, який контент, потрібна локалізація. Вибір CMS під сценарії, а не по трендам. Налаштування прав доступу, workflow для публікації (чернетка → на перевірці → опубліковано), інтеграція з CDN для медіафайлів.
Строки
Інтеграція headless CMS (Strapi/Sanity) у існуючий Next.js проект: 2–5 тижнів. Кастомний WYSIWYG-редактор з Tiptap та специфичними блоками: 2–4 тижні. Медіабібліотека з S3 + трансформації: 1–3 тижні. Повна CMS-система з нуля: 4–10 тижнів.







