CMS and Content Management: WYSIWYG, Media Library, Galleries
The editor on a website is an interface used daily by people with no development background. If it's inconvenient to change article headline, image upload doesn't work or formatting breaks when copying from Word — content either doesn't update, or updates with errors. Direct losses: outdated prices, inactive promotions, SEO texts nobody edits.
Choosing CMS: When What Fits
Headless CMS (Strapi, Contentful, Sanity) separates content management from frontend. Content consumed via API by any client: website, mobile app, digital signage. Right choice for omnichannel products and when frontend is React/Vue/Next.js.
Sanity stands out with customizable Studio: every field, every document type, every widget — React component you can replace. Portable Text (their format for rich content) ports to any renderer. For complex editorial workflows — best in class.
Contentful — stable cloud service, large extension marketplace, good CDN for media. Minus — price at content volume growth.
Strapi — self-hosted, open source, TypeScript API, custom fields via plugins. You host it, your data.
Traditional CMS (WordPress, Craft CMS, Statamic) — when you need familiar editing interface and no separate frontend project. Craft CMS — professional tool for content teams: Matrix fields, flexible record structure, built-in localization.
Built into Laravel (Nova, Filament): when app already on Laravel and no point adding separate CMS. Filament — modern, React+Livewire, rich plugin ecosystem.
WYSIWYG: Tiptap, Lexical, TinyMCE
Editor — separate engineering task, not just <textarea>.
Tiptap (wrapper over ProseMirror) — best balance of customizability and ease. Every editor element — extension: headings, lists, tables, mentions, code blocks — added selectively. Collaborative editing via Yjs — built-in. For Next.js/React projects — first choice.
Lexical (Meta, open source) — high-performance, extensible, written for Facebook. More complex setup than Tiptap, but more powerful in customization. Fits if you need non-standard blocks.
TinyMCE — multi-year standard for corporate CMS. Works out of box, familiar to many editors. Minus — outdated API, heavy on bundle (~300KB), less control over content structure.
Problem with all WYSIWYG: "dirty" HTML when pasting from Word. instead of spaces, inline styles on every tag, nested <span> meaninglessly. Sanitize on paste required — otherwise formatting breaks, SEO suffers.
Media Library
File upload via simple <input type="file"> with direct disk save — antipattern. Disk fills up, scaling impossible, can't attach CDN.
Right scheme: upload to S3-compatible storage (AWS S3, Cloudflare R2, MinIO for self-hosted) → CDN on top (CloudFront, Cloudflare) → request transformations.
Imgproxy or Thumbor for server image transformation: one original file, any sizes and formats generated dynamically. URL carries parameters: https://img.example.com/resize:800:600/format:webp/plain/s3://bucket/photo.jpg. Original stored once, derivatives not needed.
Cloudflare Images — managed service: upload original, get variant URLs for different sizes. $5 per 100k images with transformations — often cheaper than self-hosted.
For video: Cloudflare Stream or Mux. Upload source, platform encodes to HLS, serves adaptive streaming. Without this video file weighs 500MB and loads as-is.
Gallery Organization
Drag-and-drop sorting in gallery — basic requirement. @dnd-kit/sortable (React) or SortableJS — libraries with accessibility support. Sorting via integer order in database: only affected elements recalculate order on swap.
Lazy loading images in gallery mandatory. loading="lazy" on <img> for native lazy loading. Intersection Observer API for custom control. 200 photo gallery without lazy loading — 150MB traffic on page open.
Lightbox: Photoswipe or Glightbox — accessible, no jQuery, with touch gestures and keyboard navigation.
Structured Content vs Free-Form HTML
Free-form WYSIWYG creates unpredictable HTML. Year later content manager set 7 different font sizes, 12 colors, random padding. Redesign impossible without manual cleanup of every page.
Structured content: instead of "how it looks" — "what it is". Not <p style="font-size:24px; color:red">Important!</p>, but block type callout with parameter variant: warning. CMS stores structure, frontend renders it.
Sanity Portable Text, Contentful Rich Text, Strapi Dynamic Zones — all moving this way. Transition from free-form HTML to structured on migration — labor-intensive, but pays off on next redesign.
Process
Start with audit of editing scenarios: who edits, how often, what content, localization needed. Choose CMS for scenarios, not trends. Setup access control, publishing workflow (draft → under review → published), integrate CDN for media files.
Timeline
Headless CMS integration (Strapi/Sanity) into existing Next.js project: 2–5 weeks. Custom WYSIWYG editor with Tiptap and specific blocks: 2–4 weeks. Media library with S3 + transformations: 1–3 weeks. Full CMS system from scratch: 4–10 weeks.







