En vous promenant sur Beamreactor, nous stockons votre IP 48h pour des raisons de sécurité.
Beamreactor, WYSIWYG web engines: home

F.A.Q.

Features and architecture

Technical questions about the XDP engine, plugins, security, the frame system and BeamReactor development conventions.

What is frameheader() for?+
frameheader() opens a visual section (frame) on the page. It displays the plugin or section title and creates the HTML container in which content will be rendered. Usage: frameheader('My title', 'h3', false). Title levels follow the HTML hierarchy: h1 for the page title (once only), h2 for main sections, h3 and beyond for frames and widgets. A directly called plugin must start with: if($obj=='my_plugin.php') frameheader($dialplugindisplay); — this condition prevents double header rendering when the plugin is included from another script.
When should I use framefooter()?+
framefooter() closes the frame opened by frameheader(). It is required before opening a new section with frameheader(). Never call framefooter() without a following frameheader(), except at the end of a page. The standard pattern for structuring a page into multiple blocks: frameheader('Section 1'); /* content */ framefooter(); frameheader('Section 2'); /* content */. The engine handles the final closing automatically.
How do I structure a page with multiple sections?+
Use the framefooter() / frameheader() pair to chain sections. Each section creates a distinct visual block with its own title. Example: after displaying a form and receiving an error, close the current frame with framefooter(), open a clean new frame with frameheader(''), include the form again, then return. This keeps the user on a valid, properly framed page without any HTTP redirect.
How does secure() work?+
secure() checks whether the logged-in user's level is sufficient to access a resource. It takes a level constant as parameter (BASE_LEVEL_ADMIN, PLUGIN_LEVEL_MODERATOR, etc.) and returns true or false. The standard pattern: frameheader($dialplugindisplay); if(!secure(PLUGIN_LEVEL_MODERATOR)) { forbids(); return; }. The frame is opened BEFORE the check — forbids() displays inside the frame, otherwise the layout breaks. The trick secure(0) simply checks whether the user is logged in at all.
Which includes should I use in a plugin?+
None for config and libraries — the XDP engine loads them automatically. The only permitted include is for the locale: include(getlocale('plugin_name'));. Files named .conf.inc.php and .lib.inc.php are detected and loaded by the engine. Manual require or include for config or libs will cause a warning and a broken path. Similarly, never include a module (.mod.php) — they are called exclusively via ?obj=name.mod.
How do translations work in a plugin?+
Each plugin has its translation files in /locale/plugin_name.XX.inc.php (XX = ISO language code). Loading is done via include(getlocale('plugin_name'));, which must be called BEFORE frameheader() to avoid missing variable errors. Translations use a $dialpluginname[] array. $dialplugindisplay contains the displayed plugin title, $dialplugincall the name shown in the control centre. getAvailableLanguages() returns the list of available languages.
How do I load plugin-specific CSS or JavaScript?+
Use the global variable $headdata to inject into <head>: $headdata .= '<link rel="stylesheet" type="text/css" href="plugins/my_plugin/css/my_plugin.css">'; For JavaScript, same approach: $headdata .= '<script src="plugins/my_plugin/js/my_plugin.js"></script>'; To execute JS after the DOM, use $footdata with a heredoc. CSS must use variables defined in core.css — never invent colours. If a variable is missing, suggest adding it to core.css.
How do I validate user input?+
Use the Sanitizer: use Beamreactor\Sanitizer\Parser; then Parser::sanitize($input, 'type'). Available types include: bool, date, email, name, html, xml, uuid, url, string, ip, float, int, path and others. sanitize() cleans and validates the data, returning false if invalid. check() verifies the format without cleaning. Always sanitize BEFORE any SQL operation. Never invent a datatype — propose one if needed.
How do I interact with the database?+
Use the SQL class: use Beamreactor\Database\SQL;. Main methods: SQL::query() for multiple rows, SQL::queryFirst() for a single row, SQL::queryValue() for a single value, SQL::insertRow() to insert, SQL::updateRow() to update, SQL::deleteRow() to delete. Always use prepared statements with ? parameters. Direct variable concatenation in SQL is strictly forbidden. Check database availability with isset($cfg['dbtable']) and table existence with SQL::tableExists().
How do I create an AJAX endpoint?+
Modules (.mod.php) are BeamReactor's AJAX endpoints. They respond with JSON, XML, HTML or text. They go in /handlers/plugin_name.mod.php and are called via ?obj=plugin_name.mod (without .php). Never call the full file path. Minimal structure: frameheader check, security via secure(), Content-Type header, action processing via Parser::sanitize(), JSON response with ['success' => !!1] or ['success' => !!0]. On the JavaScript side, calls use $.post(BEAM_BASE_URL + '?obj=plugin_name.mod', {...}).
How does page routing work?+
Everything in BeamReactor goes through index.php. The ?obj= parameter determines what gets loaded. A plugin: ?obj=my_plugin.php. An AJAX module: ?obj=my_plugin.mod. A document: ?obj=my_page.dta. The XDP engine resolves the path, loads config, libs and locale automatically, then executes the script in a secured environment. No PHP script can be called directly — everything goes through the engine.
How do I display notifications to the user?+
BeamReactor has a toast system with 6 levels: debug (0), info (1), success (2), warning (3), error (4), critical (5). Quick usage: Toast::info('Title', 'Message', 5000); or Toast::add(Toast::LEVEL_WARNING, 'Title', 'Message', BASE_LEVEL_USER, 0). The minUserLevel parameter targets notifications by access level. Duration is in milliseconds, 0 for persistent.
What is the structure of a BeamReactor plugin?+
A plugin is a self-contained folder in /plugins/plugin_name/ containing: plugin_name.php (main interface), /conf/ (auto-loaded config), /lib/ (auto-loaded libraries), /locale/ (per-language translations), /handlers/ (AJAX endpoints .mod.php), /css/, /js/, /images/, /sql/ (table installation), /tests/, /doc/ (documentation .md and help .help.json), and /data/cache/ for persistent data. Installation means dropping the folder in. Removal means taking it out.
How do I display JavaScript dialogs in BeamReactor?+
BeamReactor replaces native alert/confirm/prompt with custom dialogs defined in javascript/dialogs.js.php. Four functions: alertWindow('Title', 'message') for alerts, confirmWindow('Title', 'question?', {}, callback) for confirmations, promptWindow('Title', 'Label:', {}, callback) for input, infoWindow('Title', 'info') for information. Never use native alert(), confirm() or prompt().
How do I pass PHP translations to JavaScript?+
In the plugin locale file, define a $js_translations array and call setJavascriptLocale($js_translations). Example: $js_translations = ['my_plugin' => ['error_msg' => $dialmyplugin[5]], 'global' => ['error' => $dial[32]]]; setJavascriptLocale($js_translations);. On the JavaScript side, access translations via PLUGIN_TRANSLATION.my_plugin.error_msg. Translations are injected into the head as a global JavaScript object.
Can I use exit or die in a plugin?+
No. Plugins must never use exit or die. The only permitted die in all plugin code is if(!function_exists('frameheader')) die('forbidden'); on the first line, which verifies the BeamReactor context. To stop execution, use return. To handle an error, display the message inside the frame then return. If a plugin uses exit or die, the engine cannot determine what failed and diagnostics become impossible.
How do security levels work?+
BeamReactor uses a fixed hierarchy: OVERMIND > ADMIN > MODERATOR > HIGHUSER > USER. BASE_LEVEL_* constants are defined in cog.inc.php. Each plugin can define its own levels via PLUGIN_NAME_LEVEL_* in its configuration. $basedisplevel always uses BASE_LEVEL_*, never PLUGIN_LEVEL_*. Custom define() calls come after $basedisplevel. The system automatically fills in missing levels via base_user_levels().
How does automatic class loading work?+
Files named .lib.inc.php and .conf.inc.php are loaded automatically by the engine. For additional classes, register a PSR-4 autoloader in the plugin configuration using spl_autoload_register(). The namespace follows the convention Beamreactor\PluginName\. Class files go in /lib/ and are resolved by the path relative to the namespace. This allows multiple plugins to coexist without name collisions.

Two factors authentication

It adds an essential extra layer of protection by requiring additional identity verification. This ensures that even if your password is stolen, a third party cannot access your data. It is the most effective defense against identity theft and account hacking.

How to set up two-factor authentication?+
To secure your account, two steps are required. Registered users must log in to the main BeamReactor interface. Click the "profile" button at the top left to access your settings. At the bottom, you will find a 2FA QR code to scan with an app like Google Authenticator or Microsoft Authenticator. Special recovery codes will be provided: make sure to copy them down to recover your account in case of phone loss or theft.
How do I log in with two-factor authentication?+
Log in with your username and password on the BeamReactor website. The system will then ask you for a code, which you will find in the Authenticator app on your phone.
What are the requirements?+
Update your phone's operating system and the Google or Microsoft Authenticator app to their latest versions. If you cannot log in but still have access to your registered email, try changing your password. If you lack email access, contact us via the support form.
What if I forgot my password?+
You can reset it at any time by clicking the "inaccessible account" link on the login page.
What if my phone is lost or broken?+
Use one of the recovery codes provided during your 2FA registration. On the authentication page, click on "recovery code", enter it, and then update your 2FA settings in your profile once logged in.
What if I have a new phone number?+
The procedure is the same as for a lost phone: use your recovery codes to log in, then synchronize your new device via your user profile.
Why is two-factor authentication implemented?+
Two-factor authentication (2FA) adds an essential layer of protection by requiring additional proof of identity. It ensures that even if your password is stolen, your data remains inaccessible to third parties. It is the most effective defense against identity theft and account hacking.