Plugin System

Plugin System

Understanding Plugins

What are Plugins?

Plugins are self-contained extensions that:

  • Extend Functionality - Add new features to your forum
  • Modify Behavior - Change how things work
  • Integrate Services - Connect with external APIs
  • Customize Experience - Tailor forum to your needs

Plugin Architecture

Plugins follow a structured architecture:

plugins/
└── my-plugin/
    ├── plugin.json          # Plugin metadata
    ├── MyPlugin.php         # Main plugin class
    ├── assets/              # CSS, JS, images
    │   ├── css/
    │   ├── js/
    │   └── img/
    ├── views/               # Template files
    │   └── admin.php
    └── README.md            # Documentation

Installing Plugins

  1. Download the plugin .zip from the Flatboard Resource Center or from the plugin author
  2. Go to Admin → Plugins
  3. Click "Install a plugin"
  4. Select the .zip archive and confirm — the archive is validated, extracted, and the plugin appears in the list automatically

The server validates the archive integrity, MIME type, size, and the presence of a valid plugin.json before extracting.

Method 2: Manual Installation (FTP / SSH)

Plugin packages are distributed as .zip archives. The manual workflow is: download → extract locally → upload the folder → activate.

Step 1: Download and Extract

  1. Download the plugin .zip from the Flatboard Resource Center or from the plugin author
  2. Verify that the plugin is compatible with your Flatboard 5 version
  3. Extract the archive on your local machine — you should get a folder (e.g. my-plugin/) with plugin.json at its root

Step 2: Upload the Plugin Folder

Via FTP

Connect to your server with an FTP client (FileZilla, Cyberduck, etc.) and upload the extracted plugin folder into the plugins/ directory of your Flatboard installation:

your-flatboard/
└── plugins/
    └── my-plugin/        ← upload this folder (not the .zip)
        ├── plugin.json
        └── ...
Via SSH

If you have shell access, you can extract the archive directly on the server:

cd /path/to/your-flatboard/plugins/
unzip my-plugin.zip          # extracts to my-plugin/
chmod 755 my-plugin/ -R      # adjust permissions if needed

Step 3: Activate the Plugin

Once the plugin folder is in place:

  1. Go to Admin → Plugins
  2. Find the plugin in the list — it will appear as inactive
  3. Click Activate

Step 4: Configure (if applicable)

If the plugin has settings, click the settings icon next to the plugin name, fill in the options, and save.

Creating a Plugin

Step 1: Create Plugin Structure

mkdir -p plugins/my-plugin/{assets/{css,js,img},views}

Step 2: Create plugin.json

{
  "id": "my-plugin",
  "name": "My Plugin",
  "version": "1.0.0",
  "description": "A custom plugin for Flatboard 5",
  "author": "Your Name",
  "license": "GPL3",
  "requires": {
    "flatboard": ">=5.0.0"
  },
  "class": "App\\Plugins\\MyPlugin\\MyPluginPlugin"
}

Step 3: Create Plugin Class

plugins/my-plugin/MyPluginPlugin.php:

<?php
namespace App\Plugins\MyPlugin;

use App\Core\Plugin;
use App\Helpers\PluginAssetHelper;

class MyPluginPlugin
{
    public function boot()
    {
        // Register plugin routes (preferred hook for plugins)
        Plugin::hook('router.plugins.register', [$this, 'registerRoutes']);
        // Inject CSS into <head>
        Plugin::hook('view.header.styles', [$this, 'addStyles']);
    }

    public function addStyles(array &$styles): void
    {
        $styles[] = PluginAssetHelper::loadCss('my-plugin', 'assets/css/style.css');
    }

    public function registerRoutes($router): void
    {
        $router->get('/my-plugin', function() {
            return 'Hello from my plugin!';
        });
    }
}

Step 4: Register Hooks

Flatboard 5 provides many hooks:

  • app.routes.register - Register custom routes
  • view.header.styles - Add CSS styles to header
  • view.footer.content - Add content to footer
  • view.post.avatar - Override post avatar rendering
  • view.user.avatar - Override user avatar rendering anywhere on the forum
  • discussion.created - When discussion is created
  • post.created - When post is created
  • user.registered - When user registers
  • user.updated - When user is updated
  • notification.types.register - Register custom notification types
  • visitor.page_info - Provide page metadata for presence indicator

See the complete hook list below for all available hooks.

Plugin Hooks

Available Hooks

Complete reference of all 96 hooks available in Flatboard 5. All data arguments marked by ref are passed by PHP reference — modifying them changes the actual value used by the framework.

Application

HookTrigger pointData
app.routes.registerApplication bootstrapRouter instance
router.plugins.registerRouter dispatchRouter instance
router.not_foundUnmatched HTML route (404)['url' => string, 'redirect' => ?string] by ref — set redirect to issue a 301
routes.registerPluginHelper::registerRoute() — called when a plugin registers a route$routes array by ref — internal hook used by the helper to append the route
security.csp.directivesCSP header generationCSP directives array by ref

View — Layout

HookTrigger pointData
assets.stylesPluginHelper::addStyle() — called when a plugin registers a stylesheetStyles array by ref — internal hook used by the helper to append the asset
assets.scriptsPluginHelper::addScript() — called when a plugin registers a scriptScripts array by ref — internal hook used by the helper to append the asset
view.header.styles<head> (frontend + backend)Styles array by ref
view.footer.scripts</body> (frontend + backend)Scripts array by ref
view.footer.contentFooter (frontend)HTML content array by ref
view.footer.linksFooter links (frontend)Links array by ref
view.footer.bottomInside <footer> just before closing tag (frontend)HTML string by ref — use to append content at the very bottom of the footer (e.g. legal links)
view.navbar.itemsMain navigation barNav items array by ref
view.main.beforeBefore main content (frontend)HTML string by ref
view.main.afterAfter main content (frontend)HTML string by ref
view.admin.sidebar.itemsAdmin sidebarSidebar items array by ref
view.admin.main.beforeBefore admin main contentHTML string by ref
view.admin.main.afterAfter admin main contentHTML string by ref
view.theme.content.filterFooter custom content + hero custom content (Premium theme)Content string — return value replaces the original content

View — Banner

HookTrigger pointData
view.banner.dataBanner component renderBanner data array by ref
view.banner.contentBanner component renderHTML string by ref, banner data

View — SEO

HookTrigger pointData
seo.meta.before<head> meta tagsSEO data array by ref
seo.meta.afterAfter default meta tagsAdditional meta HTML string by ref

View — Auth Forms

HookTrigger pointData
view.login.formLogin page + login modalForm fields array by ref
view.login.validationLogin form submissionValidation error by ref
view.user.register.formRegistration page + modalForm fields array by ref
view.user.register.validationRegistration form submissionValidation error by ref

View — Discussions & Replies

HookTrigger pointData
view.discussions.toolbarDiscussion list toolbar (all themes)HTML string by ref — append extra toolbar buttons
view.discussion.badgesDiscussion item card — badge rowBadges array by ref, discussion data — append extra status badges
view.discussion.create.formNew discussion formForm fields array by ref
view.discussion.create.validationDiscussion creation submissionValidation error by ref
view.discussion.edit.formDiscussion edit formForm fields array by ref, form context array
view.discussion.show.before_contentDiscussion view (before first post)Event data array by ref
view.discussion.show.after_contentDiscussion view (after first post)Event data array by ref
view.reply.create.formReply formForm fields array by ref
view.reply.create.validationReply submissionValidation error by ref
view.sidebar.navigationDiscussion list sidebarSidebar items array by ref
view.post.user_dataPost thread component — user data setup['post' => array, 'user_data' => array] by ref — modify user_data to override author display data (name, avatar, etc.) for virtual users or bots
view.post.avatarPost thread component — avatar render['user_id', 'username', 'avatar', 'size', 'html'] by ref — set html to override the default <img> output
view.user.avatarcomponents/avatar.php and discussion-item list (author + last-post author)['user_id', 'username', 'avatar', 'size', 'html'] by ref — set html to override the rendered avatar for any user across the forum
view.post.user.statsPost thread component — below the post count badge['user_id' => string, 'html' => string] by ref — append to html to inject extra badges/stats next to the post counter (all themes)
view.post.dropdown.itemsPost action dropdown menu (first post and replies)Hook data array by ref (postId, discussionId, canEdit, html) — append extra dropdown items
view.post.edit.formPost / reply edit formHook data array by ref (postId, discussionId, content)
view.profile.statsUser profile page — statistics card['user_id' => string, 'html' => string] by ref — append to html to inject extra rows below the discussions/replies counters

Content Events

HookTrigger pointData
discussion.createdAfter discussion savedEnriched event data array
discussion.created.legacyAfter discussion savedCreated discussion (legacy format)
discussion.updatedAfter discussion edited (DiscussionController::update())Updated discussion data
discussion.deletedAfter discussion deletedDiscussion data
categories.list.filterDiscussionController::index() and ::forums() — after categories sortedCategories array by ref — remove or reorder categories before rendering
discussions.index.filterDiscussionController::index() — after discussions loadedDiscussions array by ref — remove discussions from the all-discussions feed before rendering
best_answer.setBest answer selected['discussion_id', 'post_id', 'user_id']
post.createdAfter reply savedCreated post data
post.updatedAfter reply editedUpdated post data
post.deletedAfter reply deletedPost data
category.createdAfter category savedCreated category data
category.updatedAfter category updatedUpdated category data
category.deletedAfter category deletedCategory data
tag.createdAfter tag savedTag data

User Events

HookTrigger pointData
user.registeredAfter registrationCreated user data
user.updatedAfter user profile savedUpdated user data
user.deletedAfter user account deletedUser data
ban.createdAfter ban appliedUpdated user data
ban.removedAfter ban liftedUpdated user data
user.profile.tabsProfile page renderTabs array by ref, user array, isOwnProfile bool
user.profile.tab.contentsProfile page renderTab contents array by ref, user array, isOwnProfile bool
user.settings.notificationsNotifications settings formOptions array by ref, preferences array
user.settings.notifications.saveNotifications settings savePreferences array by ref, request data, user
user.settings.preferences.saveGeneral preferences savePreferences array by ref, request data, user

Moderation

HookTrigger pointData
report.createdAfter content report savedCreated report data
HookTrigger pointData
search.resultsSearch service (all types)Results array by ref, query, type, keywords, filters
search.before.displayBefore HTML search resultsResults array by ref, query, type, filters
search.ajax.resultsBefore AJAX search resultsResults array by ref, query, type, filters

Notifications

HookTrigger pointData
notification.types.registerNotificationService::validateNotificationType() — called at boot time$allowedTypes array by ref — append custom type strings to extend the core whitelist
notification.before.createBefore notification writtenNotification data array by ref, type string
notification.after.createAfter notification writtenNotification ID, notification data
notification.email.bodyBefore notification email sentEmail body string by ref, notification data

Markdown & Editor

HookTrigger pointData
markdown.pre_processBefore markdown parsing (MarkdownHelper)['raw' => string, 'context' => string] by ref — modify raw to alter the source before parsing
markdown.parseMarkdown rendering (all contexts)Result array by ref, raw markdown string
markdown.post_processAfter markdown parsing (MarkdownHelper)['html' => string, 'context' => string] by ref — modify html to post-process the rendered output
markdown.editor.configEditor component initConfig array by ref, $editorId
component.markdown-editor.beforeBefore editor textareaHTML string by ref, $editorId
component.markdown-editor.attributesEditor textarea tagAttributes array by ref, $editorId, config
markdown.editor.initEditor JS init scriptScript string by ref, $editorId, config
markdown.editor.getValueEditor getValue scriptScript string by ref, $editorId
markdown.editor.setValueEditor setValue scriptScript string by ref, $editorId, value path
component.markdown-editor.afterAfter editor textareaHTML string by ref, $editorId

Presence & Visitor Tracking

HookTrigger pointData
visitor.page_infoVisitor::getPageInfo() — unknown URLs only['page' => string, 'info' => array] by ref — set info['type'], info['title'], info['url']
visitor.before_trackVisitorTrackingMiddleware before write['ip_address', 'user_agent', 'page', 'user_id'] by ref
presence.anonymous_visitorsPresenceService::getActiveAnonymousVisitorsDetailed()Visitors array by ref
presence.botsPresenceService::getActiveBotsDetailed()Bots array by ref
presence.usersPresenceService::getActiveUsersDetailed()Users array by ref

Admin

HookTrigger pointData
admin.dashboard.widgetsAdmin dashboard renderWidgets array by ref

Cron

HookTrigger pointData
cron.registerPluginHelper::registerCronTask() — called when a plugin registers a scheduled task$tasks array by ref — internal hook used by the helper to append the task definition

Theme

HookTrigger pointData
theme.setting.valueThemeHelper::getThemeSetting() — after reading a theme settingValue by ref, setting key, field type — allows plugins to override theme setting values
themeswitcher.themes.expandTheme Switcher — build available themes listThemes array by ref — append sub-theme definitions (e.g. Bootswatch variants)
themeswitcher.theme.validateTheme Switcher — validate theme selection['themeId', 'subThemeId', 'valid'] by ref — set valid to override validation
themeswitcher.theme.activateTheme Switcher — apply theme switch['themeId', 'subThemeId'] by ref — run side effects on theme activation

Plugin Views

HookTrigger pointData
plugin.view.indexPlugin index view rendered['pluginId', 'viewName', 'viewVars'] by ref
plugin.view.{viewName}Named plugin view rendered['pluginId', 'viewName', 'viewVars'] by ref
plugin.view.index.permissionsBefore plugin index viewPermissions array by ref, pluginId, 'index'
plugin.view.{viewName}.permissionsBefore named plugin viewPermissions array by ref, pluginId, viewName
plugin.view.{viewName}.varsBefore named plugin viewViewVars array by ref, pluginId, viewName
plugin.view.admin.varsBefore plugin admin viewViewVars array by ref, pluginId, 'admin'
plugin.view.privacy.varsBefore plugin privacy viewViewVars array by ref, pluginId, 'privacy'
plugin.view.cookies.varsBefore plugin cookies viewViewVars array by ref, pluginId, 'cookies'

Webhooks

HookTrigger pointData
webhook.receivedInbound webhook payloadWebhook data array

Using Hooks

// Register a hook
Plugin::hook('discussion.created', function($discussion) {
    // Do something when discussion is created
    Logger::info("New discussion: " . $discussion['title']);
});

// Register with priority
Plugin::hook('post.created', [$this, 'handlePostCreated'], 10);

// Extend the notification type whitelist (by reference)
Plugin::hook('notification.types.register', function(array &$types): void {
    $types[] = 'my_custom_type';
    $types[] = 'reputation_badge';
});

// Override avatar rendering for a virtual user (by reference)
Plugin::hook('view.user.avatar', function(array &$data): void {
    if ($data['user_id'] === 'my-bot') {
        $data['html'] = '<span class="avatar-bot"><i class="fas fa-robot"></i></span>';
    }
});

Plugin Configuration

Settings Storage

Plugin settings are stored in the "plugin" section of plugin.json and accessed via Plugin::getData(). Do not use Config::get/set for plugin-specific settings.

use App\Core\Plugin;

// Read a setting (with optional default)
$value = Plugin::getData('my-plugin', 'setting', 'default');

// Dot-notation is supported for nested keys
$host = Plugin::getData('my-plugin', 'smtp.host', '');

// Write a setting (in-memory only)
Plugin::setData('my-plugin', 'setting', 'value');

// Persist all settings to plugin.json
Plugin::saveData('my-plugin', ['setting' => 'value', 'another' => 'data']);

Admin Interface

Create admin settings page:

  1. Create view file: views/admin.php
  2. Register admin route
  3. Handle form submission
  4. Save settings to config

Best Practices

Plugin Development

  • Follow Structure - Use standard plugin structure
  • Namespace Properly - Use proper namespaces
  • Document Code - Add comments and documentation
  • Handle Errors - Implement error handling
  • Test Thoroughly - Test before release

Security

  • Validate Input - Always validate user input
  • Sanitize Output - Sanitize all output
  • Check Permissions - Verify user permissions
  • Use CSRF Protection - Protect forms with CSRF tokens

Performance

  • Lazy Load - Load assets only when needed
  • Cache When Possible - Cache expensive operations
  • Minimize Queries - Optimize database/file access
  • Use Hooks Efficiently - Don't overload hooks

Managing Plugins

Activating/Deactivating

  • Activate - Enable plugin functionality
  • Deactivate - Disable without uninstalling

Uninstalling a Plugin

Uninstalling permanently removes a plugin and all its data from your forum.

Using the Admin Panel

  1. Navigate to Admin → Plugins
  2. Deactivate the plugin first — the Uninstall button is blocked for active plugins
  3. Click the Uninstall button (trash icon, red/danger style) next to the plugin
  4. Confirm in the confirmation dialog that appears
  5. The server will:
    • Run the plugin's uninstall() hook (if defined), then deactivate() hook
    • Remove all plugin permissions
    • Clear asset and translation caches
    • Remove the plugin's entry from plugins.enabled
    • Recursively delete the plugin directory from plugins/

Restrictions

  • Core plugins (marked cantDisable = "1" in plugin.json) cannot be uninstalled — the button is hidden
  • Active plugins cannot be uninstalled — deactivate the plugin first

Implementing the Uninstall Hook

Plugins can run cleanup logic when uninstalled:

public function uninstall(): void
{
    // Clean up plugin-specific data in stockage/, custom tables, etc.
    // Called before the plugin directory is deleted
}

public function deactivate(): void
{
    // Called when plugin is deactivated (also called during uninstall)
}

Updating Plugins

  1. Backup - Backup your forum first
  2. Download - Get new plugin version
  3. Replace Files - Replace plugin files
  4. Clear Cache - Clear forum cache
  5. Test - Test plugin functionality

Plugin Dependencies

Some plugins require other plugins:

{
  "requires": {
    "flatboard": ">=5.0.0",
    "plugins": {
      "another-plugin": ">=1.0.0"
    }
  }
}

Pro Plugins

FlatSEO (v1.2.1)

A complete SEO toolkit for Flatboard, fully admin-driven — no code editing required.

Meta & Social

  • Configurable title format with custom separators
  • Open Graph (Facebook, LinkedIn) and Twitter/X Cards meta tags
  • Per-page image overrides for social sharing previews

Structured Data (JSON-LD)

Automatically generated JSON-LD schemas:

Schema typeApplied to
WebSite + SearchActionAll pages
OrganizationForum home
BreadcrumbListAll pages
DiscussionForumPostingDiscussion pages
QAPageDiscussions with a best answer
ProfilePageUser profile pages

Sitemap & Crawling

  • XML sitemap with per-URL priority and changefreq settings
  • Image sitemap support
  • Live cache invalidation on content changes
  • Full robots.txt editor in the admin panel
  • Global noindex controls for search pages, user profiles, and tag pages

Redirects & Verification

  • 301/302 redirect manager — rule-based, no .htaccess editing
  • Search engine verification codes: Google, Bing, Yandex, Pinterest

Analytics Injection

  • Google Analytics 4 and Google Tag Manager script injection (admin-configurable, no template editing)

SEO Audit

  • Per-discussion SEO scoring with actionable recommendations
  • Auto-translated breadcrumbs for all 5 supported languages

TUI Editor (v1.3.1)

A modern Markdown/WYSIWYG editor powered by Toast UI Editor, replacing the default editor globally.

Editing Modes

  • Markdown mode — raw Markdown with live preview
  • WYSIWYG mode — rich text editing, switchable at any time
  • Preview layout: side-by-side or tabbed

Features

FeatureDetails
Image uploadDrag-and-drop or browse
Video embedsYouTube and TikTok direct URL paste
Table editorVisual table creation and editing
Syntax highlightingCodeMirror-powered fenced code blocks
Emoji pickerBuilt-in emoji panel
AutosaveConfigurable interval (seconds)
Spell checkerBrowser spell-check toggle
Fullscreen modeDistraction-free writing
ToolbarPer-context configuration (new discussion, reply, admin)

Private Messaging (v1.1.1)

A full-featured direct messaging system between registered members.

Mailbox

  • Inbox, Sent, and Drafts views
  • Read receipts — know when your message has been read
  • Typing indicators — real-time "is typing…" indicator
  • Full-text message search

Composer

  • Emoji picker
  • Optional file attachments
  • Configurable maximum message length (up to 50,000 characters)

Notifications

  • Email notification on new message (respects per-user preferences)
  • In-forum notification badge

Administration

Configurable from Admin → Plugins → Private Messaging → Settings:

SettingDefaultRange
Max message length5 000 charsup to 50 000
Max messages per user (inbox)100configurable
Max recipients per message1configurable
Pagination (messages per page)20configurable
Auto-delete old messagesOff1–365 days

Additional options:

  • User block list — members can block specific users
  • Welcome/rules message — Markdown-formatted message shown to new users
  • Date display — relative ("2 hours ago") or absolute

FlatHome (v1.0.2)

A full-featured homepage, CMS, and blog system for Flatboard. FlatHome transforms your forum into a complete web platform with a landing page, custom CMS pages, a blog with comments, and a flexible navigation builder.

CMS Pages

  • Unlimited custom pages with Markdown or WYSIWYG editor
  • Auto-generated URL slugs (editable)
  • Page view counter
  • PHP template system — assign custom PHP templates (e.g. home, contact) to any page
  • Page groups — group pages into dropdown menus in the navigation bar
  • Multi-language menu labels — per-language labels for nav items
  • Discussion-linked pages — a page can mirror a forum discussion
  • Homepage flag — designate any page as the site homepage (single enforcement)

Homepage Modes

ModeDescription
pageA CMS page is the site root
forumThe discussion list is the site root
blogThe blog archive is the site root

Blog

  • Blog posts are forum discussions from a designated category
  • Full article view with hero banner, author info, tags, and read-time estimate
  • Markdown comments — logged-in members can post comments via AJAX
  • Blog sidebar — recent posts, popular posts, tags, categories
  • Blog category can be hidden from the main forum list
  • Shortcodes in page content: {remote_version}, {remote_codename}, {remote_release_date}

Landing Page Template

The built-in home template (modeles/home.php) renders a modern landing page with:

  • Hero section — headline, lead text from page content, two CTA buttons, live discussion preview
  • Features section — four key capability chips
  • Join section — documentation, bug report, and community cards
  • Blog preview — latest blog articles

The Navigation order panel in the admin allows drag-and-drop reordering of all nav items (forum, pages, page groups, blog). Items can be dragged into a group to create a dropdown.

Contact Page Template

The built-in contact template provides a ready-made contact form. The recipient email is resolved from plugin settings or the forum configuration. All labels are translated in 5 languages.

Admin Panel

Accessible at Admin → FlatHome — manage pages, page groups, blog settings, navigation order, and plugin configuration from a single interface.


Forum Monitoring (v1.1.1)

Real-time health monitoring and anomaly detection for your forum.

Activity Chart

Visualizes forum activity over a configurable time window:

  • Available windows: 7, 14, 30, 90, 180, 365 days
  • Plots discussions, posts, and member registrations over time

Leaderboards

  • Top users — ranked by post count (up to 100 entries)
  • Top discussions — ranked by reply count (up to 100 entries)

Anomaly Detection

  • Automatically flags unusual activity patterns (traffic spikes, burst posting)
  • Configurable spam score threshold (scale 1–10)
  • Email alerts sent to administrators when anomalies are detected

Admin Integration

  • Admin dashboard widget — compact health summary on the main dashboard
  • Dedicated section at Admin → Forum Monitoring

Flat Moderation Extend (v1.0.1)

Advanced moderation tools that go beyond the core moderation features.

Pre-moderation Queue

Hold content from new users for review before publication:

  • Configurable post-count threshold — users below this number of approved posts have their content held automatically
  • Held discussions and replies are invisible to other members until approved or rejected
  • All administrators and moderators receive an instant notification with a direct link to the moderation queue when new content is held
  • Accessible at Admin → Moderation Queue

Shadow Banning

Silently hide content from a disruptive user without alerting them:

  • The shadow-banned user sees their own posts and discussions as normal
  • Other members do not see the shadow-banned user's content
  • Applied per-user from the admin panel

Discussion Merging

Merge two discussions into one:

  • Replies from the merged discussion are moved to the target discussion
  • Automatic 301-style redirects from the old discussion ID to the new one
  • Prevents broken links and consolidates duplicate threads

Bulk Actions

Perform moderation actions on multiple discussions at once:

  • From the admin panel: pin, lock, solve, move, hide, or delete multiple discussions
  • From the frontend discussion list: moderators can perform bulk actions without leaving the forum

Configuration (Admin → Plugins → Flat Moderation Extend → Settings):

SettingDefaultDescription
Pre-moderation enabledOnEnable/disable the pre-moderation queue
Post-count threshold5Users with fewer approved posts are subject to pre-moderation
Shadow ban enabledOnEnable/disable the shadow ban feature

Storage Migrator (v1.1.1)

Zero-downtime migration between the two storage backends — JSON flat-file and SQLite.

Overview

Details
DirectionJSON → SQLite and SQLite → JSON (bidirectional)
DowntimeNone — forum remains accessible during migration
SafetyOriginal data is preserved until migration is confirmed
RollbackFully rollback-friendly at any step

How It Works

  1. Go to Admin → Storage Migrator
  2. Select the target storage (JSON or SQLite)
  3. The migrator copies all data (discussions, posts, users, categories…) to the new backend atomically
  4. Verify the result — the old data remains intact
  5. Confirm the switch — the forum now uses the new backend

Community Plugins

EasyMDE (v2.3.2)

A modern Markdown editor powered by EasyMDE, replacing the default editor globally.

Editing Features

FeatureDetails
Syntax highlightingCodeMirror-powered fenced code blocks
Image uploadBrowse or paste images directly into the editor
Video embedsYouTube and TikTok direct URL paste
Emoji pickerBuilt-in emoji panel
AutosaveConfigurable interval (milliseconds)
Spell checkerBrowser spell-check toggle
Side-by-side previewLive Markdown preview panel
Fullscreen modeDistraction-free writing
ToolbarPer-context configuration (new discussion, reply, edit, PM, admin pages)

Configuration (Admin → Plugins → EasyMDE → Settings)

Key options:

SettingDefaultDescription
Syntax highlightingOnHighlight code in fenced blocks
Spell checkerOnEnable browser spell checking
AutofocusOnFocus the editor on page load
Line numbersOffShow line numbers in editor
Line wrappingOnWrap long lines
Tab size2Number of spaces per tab
AutosaveOffSave draft to browser storage periodically
Autosave delay10 000 msInterval between autosaves
Toolbar per context(see below)Customizable toolbar for each editor context

Toolbar contexts: discussion-create, reply, post-edit, discussion-edit, settings, pm, page-edit, default.


Logger (v1.1.5)

A forum activity logger with optional webhook delivery. Every selected event is recorded and can be forwarded in real time to an external URL.

Tracked Events

All events can be toggled individually:

CategoryEvents
Discussionscreated, updated, deleted
Postscreated, updated, deleted
Usersregistered, updated, deleted
Categoriescreated, updated, deleted
Tagscreated, updated, deleted
Reportscreated
Banscreated, removed

Webhook Delivery

Set a webhook URL in the plugin settings to receive a POST request for each enabled event. The payload contains the full event data.

Configuration (Admin → Plugins → Logger → Settings):

SettingDescription
Webhook URLTarget URL for event delivery (leave empty to disable)
Enabled eventsToggle each event type individually

Troubleshooting

Plugin Not Loading

Check:

  1. Plugin structure is correct
  2. plugin.json is valid
  3. Plugin class exists and is correct
  4. Check error logs

Plugin Conflicts

Solution:

  1. Deactivate conflicting plugins
  2. Check hook priorities
  3. Review plugin code
  4. Contact plugin developers

Plugin Errors

Solution:

  1. Check error logs
  2. Enable debug mode (temporarily)
  3. Review plugin code
  4. Check Flatboard 5 compatibility

Resources

Last updated: March 17, 2026