Rapid

EditorJS block editor fieldtype for ProcessWire. Stores content as JSON, renders HTML server-side via pluggable block renderers.

EditorJS block editor fieldtype for ProcessWire. Stores content as JSON, renders HTML server-side via pluggable PHP block renderers.

Rapid

Author: Maxim Semenov
Website: smnv.org
Email: maxim@smnv.org

If this project helps your work, consider supporting future development: GitHub Sponsors or smnv.org/sponsor.

Requirements


  • ProcessWire >= 3.0.200
  • PHP >= 8.2

Installation


  1. Copy the Rapid/ folder to site/modules/.
  2. In the admin go to Modules → Refresh → install Rapid.
    This automatically installs InputfieldRapid, ProcessFieldtypeRapid, ProcessRapid, and ProcessRapidFrontend.
  3. Add a field of type Rapid to any template.

No build step required — a pre-built js/dist/editor.js is included.

Template usage


// Render all blocks
echo $page->body;
echo $page->body->render();

// Restrict to specific block types
$r = new RapidRenderer(['allowedBlocks' => ['paragraph', 'header', 'image']]);
echo $page->body->renderWith($r);

// Single block by index
echo $page->body->renderBlock(0);

// Render a specific language when multilingual content is enabled
echo $page->body->renderLanguage('de');

// Plain text — for meta descriptions, search indexing
$description = mb_substr($page->body->toText(), 0, 160);

// Raw JSON
$json = $page->body->toJSON();

// From a raw JSON string (static shortcut; multilingual JSON uses current language)
echo RapidRenderer::fromJSON($json, $page);

// Check if empty
if (!$page->body->isEmpty()) { ... }

Supported blocks


Block tools

TypeJS packageNotes
paragraphbuilt-inlarge variant supported
header@editorjs/headerh1–h6, auto-generates anchor ID
quote@editorjs/quoteCaption optional
nestedList@editorjs/nested-listOrdered + unordered, recursive
table@editorjs/tableOptional header row
code@editorjs/codeMonospace, scroll overflow
delimiter@editorjs/delimiter<hr>
warning@editorjs/warningTitle + message box
checklist@editorjs/checklistRead-only checkboxes on output
raw@editorjs/rawHTML pass-through
image@editorjs/imageUploads to page files directory, optional WebP + resize
galleryCustomUpload multiple images at once, rendered as responsive grid
attaches@editorjs/attachesFile download block
embedCustomYouTube + Vimeo via URL paste, youtube-nocookie.com
columns@calumk/editorjs-columns2–3 column nested editor, rendered server-side
alerteditorjs-alert8 color variants
toggleeditorjs-toggle-blockSpoiler / accordion via <details>
linkTool@editorjs/linkLink preview with OG metadata

Inline tools

TypeJS package
inlineCode@editorjs/inline-code
marker@editorjs/marker
underline@editorjs/underline
boldbuilt-in
italicbuilt-in
linkbuilt-in

Plugins

PluginNotes
editorjs-drag-dropDrag blocks by settings handle
editorjs-undoCtrl+Z / Ctrl+Y

Field configuration


In Setup → Fields → your field → Details:

Editor behaviour

  • Allowed block types — restrict available blocks. Leave all unchecked to allow every type.
  • Min height (px) — minimum height of the editor area (default: 200).
  • Placeholder text — shown when editor is empty.
  • Editor alignmentLeft, Center, or Full width.
  • Toolbar positionLeft (default) or Right.
  • Autosave debounce (ms) — delay between typing and saving to the hidden textarea (default: 300).

Header block

  • Allowed heading levels — restrict which h-levels appear in the toolbar.
  • Default level — pre-selected level when inserting a new header.

File uploads

  • Max upload size (MB) — applies to images and file attachments.
  • Default image width / height (px) — resize all images on render via Pageimage::size(). 0 = no resize.
  • Image options — Convert to WebP, Crop to fit.
  • Allowed image types — JPEG, PNG, GIF, WebP, SVG. Leave all unchecked to allow all types. Uploaded SVG files are sanitized before storage.
  • Allowed file extensions — comma-separated list (e.g. pdf,doc,xlsx,zip). Leave empty to allow all safe extensions; executable extensions are always blocked.

Output / rendering

  • Enable frontend editing — render an inline Rapid editor on the frontend for authorized users.
  • Who can edit — permission required to use the frontend editor (default: page-edit).
  • Frontend save URL — URL path used by the frontend editor save hook (default: /rapid-save/).
  • CSS frameworkVanilla (rapid-*), Tailwind CSS, Bootstrap 5, or UIkit 3.
  • Output wrapper CSS class — added to the wrapping <div>. Useful for scoped CSS (e.g. prose).
  • Enable multilingual content — store separate block JSON for each ProcessWire language.
  • Text formatters — ProcessWire Textformatter modules applied to rendered block text and captions.

Inline toolbar

  • Visible inline tools — restrict which inline tools appear in the text selection toolbar.

Frontend editing


Enable per-field in Output / rendering. Requires ProcessRapidFrontend module (auto-installed with Rapid).

$editor = $modules->get('ProcessRapidFrontend');

// Auto: editor for authorized users, plain HTML for others
echo $editor->renderField($page, 'body');

// Manual control
if ($editor->canEdit($page, 'body')) {
    echo $editor->editorFor($page, 'body');
} else {
    echo $page->body;
}
  • Save requests POST to the configured frontend save URL (default: /rapid-save/; no admin URL needed).
  • Protected by HMAC nonce (no separate CSRF token required).
  • Save requests are accepted only for Rapid fields assigned to the target page template.
  • Save payloads must contain the expected EditorJS blocks array.
  • Save payloads larger than 2MB are rejected before decoding.
  • JS bundle and CSS are injected automatically on first editorFor() call.

CSS frameworks


// Output with Tailwind classes (set in field config, applied automatically)
echo $page->body;

// Override per render call
echo $page->body->render(['outputFramework' => 'bootstrap']);

Class mappings are defined in RapidFrameworks.php.

Multilingual content


Enable per-field in Output / rendering → Enable multilingual content. Requires ProcessWire LanguageSupport.

When enabled, the admin inputfield renders one Rapid editor per ProcessWire language. The frontend renderer uses the current $user->language; if no content exists for that language yet, Rapid falls back to the first non-empty language value. Frontend editing still opens the current language's own value so empty translations stay empty until edited.

Existing single-language JSON remains valid. When multilingual content is enabled on an existing field, the old JSON is used as the current language value and no database migration is required.

// Current user language
echo $page->body;

// Explicit language
echo $page->body->renderLanguage('fr');

// Raw JSON for one language
$json = $page->body->getLanguageJSON('fr');

Text formatters


Enable per-field in Output / rendering → Text formatters. Rapid applies selected Textformatter modules to text-like block content before server-side rendering: paragraphs, headings, quotes, lists, tables, image/embed captions, warnings, checklists, alerts, and toggle titles.

Raw HTML, code blocks, link URLs, file URLs, and link preview metadata are left untouched.

// Override per render call
echo $page->body->render([
    'textformatters' => ['TextformatterHannaCode'],
]);

Frontend styles


Include rapid.css for default vanilla styling:

$config->styles->add($config->urls->FieldtypeRapid . 'rapid.css');

Dark mode

rapid.css and js/editor.css are fully integrated with the AdminThemeUikit Design System.
All colors reference --pw-* CSS custom properties and adapt automatically via the CSS light-dark() function — no extra classes or prefers-color-scheme media queries needed.

Required: --pw-* variables must be defined on :root (provided by AdminThemeUikit's admin-custom.css or equivalent). Rapid-specific tokens (--rapid-*) are declared inside rapid.css and can be overridden per-project:

:root {
    --rapid-accent: var(--pw-main-color);     /* quote border, checklist checkbox */
    --rapid-code-bg: light-dark(#1e1e2e, #0d0d1a);
    /* … see rapid.css :root block for full list */
}

Localization


Rapid passes a ProcessWire translation-backed i18n.messages dictionary to EditorJS in both the admin inputfield and the frontend editor. Core EditorJS UI, tool names, block tunes, warning/link/alert/toggle strings, Rapid's custom embed tool, and frontend save/status labels can be translated through ProcessWire's normal module translation workflow.

Custom block types


<?php namespace ProcessWire;

class RapidBlockMyType extends RapidBlockAbstract {
    public static function render(array $block, ?Page $page = null, ?Field $field = null): string {
        $text = htmlspecialchars(strip_tags($block['data']['text'] ?? ''));
        return "<div " . self::attr($block) . ">$text</div>";
    }
    public static function toText(array $block): string {
        return strip_tags($block['data']['text'] ?? '');
    }
}

Auto-discovered — no registration needed. Type key = lcfirst of the class suffix.

Upload endpoints


Mounted at /[admin]/setup/rapid-upload/:

RouteMethodDescription
upload/POSTImage upload
attach/POSTFile upload
link/?url=GETFetch OG metadata
save/POSTFrontend save (nonce-protected)

The link metadata endpoint accepts only public http/https URLs and reads only the first 1MB of remote HTML.

Building the JS bundle


cd site/modules/Rapid/js
npm install
node esbuild.mjs

Architecture


FileRole
FieldtypeRapid.module.phpFieldtype — DB schema, value lifecycle, field config UI
InputfieldRapid.module.phpInputfield — admin editor, asset loading
ProcessFieldtypeRapid.module.phpUpload/link/save endpoints
ProcessRapid.module.phpDashboard and block preview
ProcessRapidFrontend.module.phpFrontend editing helper + /rapid-save/ hook
RapidValue.phpValue object returned by $page->field
RapidRenderer.phpBlock dispatcher — iterates blocks, handles toggle nesting
RapidAttr.phpHTML attribute builder
RapidFrameworks.phpCSS class mappings for Tailwind, Bootstrap, UIkit
blocks/RapidBlockAbstract.phpBase class for block renderers
blocks/RapidBlocks.phpBuilt-in block renderers
js/editor.jsEditor source (ES modules)
js/dist/editor.jsPre-built IIFE bundle loaded in admin
js/editor.cssAdmin editor styles
rapid.cssFrontend styles for vanilla rendering

Author


Maxim Semenov — smnv.orgmaxim@smnv.org

More modules by Maxim Semenov

  • Context

    Export ProcessWire site context for AI development (JSON + TOON formats)
  • WireWall

    Advanced traffic firewall with VPN/Proxy/Tor detection, rate limiting, and JS challenge
  • Ichiban (SEO control center)

    Comprehensive SEO module: meta/OG/schema, audit, redirects, revisions, email reports.
  • Subscribe

    Newsletter subscription handler with lists, double opt-in, honeypot, rate limiting and unsubscribe link.
  • Dimensions

    Stores product dimensions (L×W×H) and weight with selectable units of measurement.
  • AiWire

    AI integration for ProcessWire. Supports Anthropic, OpenAI, Google, xAI, and OpenRouter.
  • Plausible Analytics

    Plausible Analytics dashboard using Stats API v2 with page-edit widget, traffic trends chart, and geo/device tabs.
  • PagePDF

    Convert ProcessWire pages to PDF documents with advanced typography support
  • Page Markdown

    Export any page to a clean Markdown file. Adds an export button to the page editor.

All modules by Maxim Semenov

Install and use modules at your own risk. Always have a site and database backup before installing new modules.