We've relied on this plugin internally for a long time across a wide range of projects. With more engineering capacity now available, we've polished it up and are excited to share it with the OctoberCMS community. We have a strong end-to-end and unit test coverage for quality control. As our projects basically all have the same structure, we expect some bugs in more diverse setups. We're happy to address them when reported to us.
Renick.Content is a next-generation block content editor for October CMS — a single form widget (and Tailor content field) that replaces rich-text soup with structured, versioned, AI-assisted content your themes stay in control of.
Authors work in a three-pane editor: a structure tree for nesting and drag & drop, a live preview rendered server-side with your real theme CSS, and an inspector for content, generic design settings, visibility scheduling and an SEO check — per block.
Find our landing page and the technical docs here: https://www.renick.io/de/content-plugin
20 production-ready blocks
Heading, Rich Text (TipTap 3), Quote, Image, Gallery (GLightbox), Video, Slider (Splide — carousel, image and card slider), Section, Grid + Column, Card + Card Grid, Accordion, Timeline, Map (privacy-proxied tiles), PDF, Anchor, Button, Call to Action (five designs), Placeholder, Spacer — all rendered through overridable Twig partials with Bootstrap 5 markup. The frontend bundle (Bootstrap 5, GLightbox, Splide, init scripts) ships with the plugin and is served through October's asset combiner — or bring your own.
Privacy by default
YouTube/Vimeo embeds render as a GDPR-friendly click-to-load facade: the poster image is proxied and cached server-side, and no request leaves the visitor's browser until they press play.
Built for real editorial work
- Version history with retention, pinning and one-click restore, plus a full audit log
- Templates: save any document as a starting point for the next one
- Import/export as JSON or a portable ZIP bundle including media
- Multisite-aware visibility (schedule from/until, per-site restriction — fail-closed)
- Media usage index that guards used files against deletion
- RainLab.Blog integration (opt-in): edit blog posts with the block editor instead of a plain Markdown/WYSIWYG field
- AI assistance (optional, off by default): translate documents, draft from a brief — OpenAI, OpenRouter or any compatible endpoint, with a monthly token budget (experimental / timeouts possible)
Built for developers
- Clean JSON documents, validated against a published JSON Schema
- Theme-overridable partials, theme-provided block types, and October events for registering blocks and hooking into rendering
- PHP facade (
Content::get/put/export/…), REST API (off by default, bearer-token protected) - Addressable Placeholder blocks your plugins can fill at render time
We will publish a MIT-licensed theme which can be freely customized, copied, and extended. Look out for Dawn theme.
Bilingual documentation (EN/DE) with a generated, always-current reference is included.
Installation via Command Line
php artisan plugin:install Renick.Content
Renick.Content
Block-based content editing for OctoberCMS 4.3. A content document is a list of typed blocks (heading, rich text, image, button, section, and more) stored as JSON in a host field, edited with a backend block editor, and rendered on the frontend through a fallback-safe renderer.
Official landing page: https://www.renick.io/de/content-plugin
Install
The plugin registers itself through the standard OctoberCMS discovery. With the
plugin in plugins/renick/content:
php artisan october:migrate # boots the plugin php artisan plugin:list # shows: Renick.Content
Usage
Tailor entries
Add a contenteditor field to a blueprint:
fields:
content:
label: Content
type: contenteditor
The field stores the document JSON in a longText column and renders the block
editor in the entry form.
Backend forms
The same widget is available to any backend form as type: contenteditor.
Frontend rendering
Render a stored document on a CMS page with the component:
[renickContent]
==
{% component 'renickContent' document=post.content %}
…or inline with the Twig function anywhere in a theme:
{{ content_render(post.content)|raw }}
Both funnel through BlockRenderer, which resolves each block's partial
theme override → plugin default → safe placeholder and never throws on a
missing or unknown block (D10): the offending block degrades to an HTML comment
(plus a visible card in debug) while its neighbours still render.
Blocks
| Handle | Group | Purpose |
|---|---|---|
heading |
text | h1–h6 heading |
richtext |
text | HTML rich text, edited with a TipTap editor in the Inspector |
quote |
text | Blockquote with author + role |
image |
media | Media image with alt, caption and optional link |
gallery |
media | Multi-image field (array or one path per line), optional captions |
video |
media | YouTube/Vimeo privacy embed or media-library <video> |
slider / slide |
media | Slideshow container and its slides |
pdf |
media | Embedded PDF from the media library |
map |
media | Privacy-proxied map (tiles served through the plugin) |
button |
components | Labelled link/button |
cta |
components | Call-to-action block |
card |
components | Card with image, text and link |
accordion / accordion-item |
components | Collapsible sections (with an FAQ variant) |
timeline / timeline-item |
components | Vertical timeline and its entries |
anchor |
components | Named anchor / link wrapper |
shared |
components | Reference to a reusable Shared Content document |
placeholder |
utility | Named slot bound to a Custom Script (JS) |
section |
layout | Container that nests child blocks |
grid / column |
layout | Column container (2/3/4) and its columns |
card-grid |
layout | Grid of cards |
spacer |
utility | Explicit vertical whitespace (xs–xl) |
Every block also carries generic settings (spacing top/bottom, width,
CSS class, anchor id — rendered as rc-* utility classes) and visibility
(on/off toggle, show-from / show-until schedule, evaluated server-side at
render time). The document format is published as JSON Schema in
schema/document-v1.json.
Each block is a YAML definition plus a default partial in
blocks/<handle>/. A theme may override a partial at
partials/renick-content/<handle>.htm; the default guarantees rendering never
breaks.
Layout
classes/ BlockDefinition, ContentDocument, VisibilityRules, BlockManager, BlockRenderer,
StaticPagesIntegration, RainLabBlogIntegration
blocks/ block definitions (YAML) + default partials
console/ Artisan commands (export/import bundle, prune versions/proxy cache, reindex media, seed demo)
formwidgets/ ContentEditor form widget (mount partial; UI ships in assets/dist)
contentfields/ ContentEditor Tailor content field
components/ Content component (renickContent)
assets/src/ Editor source — TypeScript + React 18 + TipTap 3 (see INITIAL_PLAN.md#25-the-editor)
assets/dist/ COMMITTED editor bundle (single ESM file + css)
tests/unit/ PHPUnit suite
Editor build
The backend editor is a TipTap 3 / React island bundled with Vite (pnpm).
Consumers never build anything — assets/dist is committed and shipped.
cd plugins/renick/content pnpm install pnpm run typecheck && pnpm test # TS + Vitest (converter round-trips, fuzz, constraints) pnpm run build # rebuild assets/dist (CI fails if stale)
AI & REST API
AI features are disabled by default. Configure them under
Settings → Renick Content AI: provider (OpenAI, OpenRouter, or the offline
mock driver for testing), API keys (encrypted at rest), per-feature models,
an image-generation model and storage target, a monthly token budget (warn-only)
and the Firecrawl research toggle.
In the editor toolbar the AI menu offers Translate… (values only —
structure, ids and URLs stay untouched), Draft from brief… and Research &
draft… (Firecrawl-gathered sources; requires the privacy toggle); the image
block can generate images from a prompt. Every AI result shows a block-diff
confirmation modal before it is applied, and records an auditable
ai_translate / ai_draft version.
Custom Scripts (JS bound to a placeholder block) can be AI-generated behind
a review gate: generated code is loaded into the form for the admin to review
and only becomes public once they save it, with create/update logging and a
created_by/updated_by audit trail.
The REST API is off by default. Enable it plus a bearer token in the AI
settings; endpoints live under /api/renick/content/v1:
GET /document?host_type=&host_id=&field= # document + media manifest
PUT /document # write (normalize + validate)
GET /document/bundle?host_type=&host_id=&field= # export document + media as a ZIP
POST /document/bundle # import a ZIP bundle
POST /translate # {host…, target_language}
POST /draft # {brief, template_id?}
POST /duplicate # {document} → re-id'd copy
GET /templates
GET /versions?host_type=&host_id=&field=
POST /restore # {host…, version_id}
All requests: Authorization: Bearer <token>. Writes snapshot the previous
state first and record the action in the audit log. The same service classes
back the editor (Renick\Content\Classes\Content facade for PHP consumers).
The group is rate-limited (default 60 requests/minute, keyed by token then
client IP) and enforces body-size caps (2 MB for a document, 50 MB for a
bundle → HTTP 413 on overflow). All limits are overridable via env or
config/renick/content/limits.php — see config/limits.php.
Plugin integrations
Two opt-in integrations let the block editor take over content fields in other plugins, configured under Settings → Content Editor → Integrations. Each switch is inert unless the matching plugin is installed, and neither is a hard dependency:
- RainLab.Pages — edit a static page's content with the block editor. The swap happens only for pages whose markup is empty or already a block document; existing HTML pages keep the rich editor untouched.
- RainLab.Blog — edit a blog post's
contentwith the block editor. Same rule: only empty or already-block posts switch; existing Markdown posts are untouched. The renderedcontent_htmlis generated from the block document on save, so the stock RainLab blog components keep working.
Command line
Artisan commands (run from the October install root):
php artisan renick:content:export-bundle --host=… --id=… [--field=content] [--out=file.zip] [--dry-run] php artisan renick:content:import-bundle --host=… --id=… --in=file.zip [--overwrite-media] [--force] [--dry-run] php artisan renick:content:prune-versions [--days=180] # delete unpinned versions older than N days php artisan renick:content:prune-proxy-cache # clear expired map-tile / video-thumbnail cache php artisan renick:content:reindex-media # rebuild the media usage index php artisan renick:content:seed-demo [--section=Content\\Article] # demo entry with every block
Both bundle commands accept --dry-run to print exactly what they would
read/write without touching the filesystem or the database.
License
Renick.Content is proprietary, commercial software — source-available, not open source. Being able to view the source code does not grant a right to use it. Any production use requires a valid, paid license per installation / per site, purchased from the Licensor. Local, non-production evaluation is permitted.
The block-based content format (its specification and schema) is separately licensed under MIT, so authored content stays portable and interoperable. The plugin implementation itself remains proprietary.
See LICENSE.md for the full terms. Copyright © 2026 Renick
Büttner. Licensing enquiries: complains@renick.io.
-
This plugin has not been reviewed yet.
-
| 1.0.0 |
Initial 1.0.0 release of Renick.Content — the complete block-based content editor for OctoberCMS 4.3 (see CHANGELOG.md for the full feature set). Creates every plugin table and its supporting indexes and audit columns in schema-dependency order. Jul 16, 2026 |
|---|


