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

Having an issue?
We're here.

Browse the FAQ, open a support ticket, or contact us directly. No chatbot, no queue: an operator actually answers.

Before writing, the answer may already be here

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.

Need personalised help?

Ticketing — For registered users. Open a ticket, track its progress, exchange with the technical support team. Your history is preserved.

Direct contact — For commercial enquiries, partnerships or pre-purchase questions. No account needed.
Contact form →

Recent changelog

- April 14, 2026, 12:59 pm: Mise en place de la facturation numérique. Meilleure prise en compte des abonnements liés a l'achat de produits via Stripe (avant partiellement manuel, maintenant entièrement automatisé).
- April 19, 2026, 10:33 pm: Remplacement de l'array des strings VIES par un module (endpoint) VIES approprié avec check du numéro de TVA intra à chaque étape.
- April 19, 2026, 10:36 pm: Correction des affichages TTC, correctifs (multiples) de la structure d'abonnement stripe, des classes et des plugins y afférents (*order*, payment, products_order_check, products_order_confirm)... Ajout du JSON VIES à la table 'orders'.
- April 22, 2026, 11:25 pm: Fix du flow et des valeurs TTC sur l'ensemble du système marketing. Mise à jour des pages d'accès BeamReactor
- April 26, 2026, 1:35 pm: Rectification de race conditions (TOCTOU DB) dans les modules stripe et paypal. Mise en place d'un upsert dans la classe SQL.
- April 27, 2026, 10:13 pm: Mise à jour des loaders, retrait des fonctions inutiles autoDiscoverAll() et discoverPlugins(). Correction du 2FA, implémentation du générateur de code QR et de l'endpoint correspondant pour éviter la dépendance externe. Correction de la classe TwoFA pour prendre en compte ces modifications. Retrait de TOCTOU dans la classe CMDB (createOwner(), register(), subscribe()). Changement du nom de cookie de session, changé un rand() par un random_bytes(
- April 27, 2026, 10:14 pm: class session, changement de isAuthenticated() (utilisé pour le chargement de classes JS) pour favoriser l'usage de la méthode secure() originale.
- May 3, 2026, 2:06 pm: Enième mise à jour de Payment/PaymentStripe. Mise à jour du MCP pour permettre l'intervention sur le code, avec une fenêtre modale pour chaque intervention. Persona "system". Lien entre ContextHelper et MCP pour récuperer les profils, les historiques et stocker les interventions MCP dans l'environnement LLM général.
- May 4, 2026, 12:50 pm: Refactored PHPDoc dates from YYYY-MM-DD to YYYY.MM.DD across 679 files.
- May 10, 2026, 6:12 pm: Nombreuses mises à jour du systeme de bans pour activer le fitlrage cidr au niveau de ban.inc.php, correctifs d'aspects dans les dta d'Aegis pour l'affichage téléphonie portable, déplacement de last_visitors de la table stats vers la table defense_logs pour eviter l'anonymisation, mise à jour de current_users pour ignorer le webmaster
- May 12, 2026, 7:33 pm: Amélioration des traductions Java, retrait de l'ancien système 2FA, mise en place des fonctions forensic dans le datatype string ainsi que des forensicDecode et forensicRender dans le Parser, affichages sécurisés dans current_user et banna en utilisant les nouvelles fonctions forensic basées sur les defense logs, passage des includes en camelCase, fixed missing versions in misc JS files, js versions are now handled by the versions.rss, fixe
- May 12, 2026, 7:34 pm: 'fixed issues with the custom LLM demo plugin
- May 19, 2026, 5:31 pm: Table fleet_peers pour les ciphers, remise en place du système de partage des bans pair a pair dans la flotte des sites BeamReactor, meilleur usage du parser dans banna, statistics, abuse. Mise en place de la catégorie 10 "sécurité" pour le tableau de bord.
- May 19, 2026, 5:48 pm: Reorganisation des plugins. Banna, intrusion_scanner, parser_enforcer, audit, bans_sync, fleet_peers passent dans la catégorie sécurité, Invoices dans la boutique, support tickets dans communauté...
- May 20, 2026, 10:31 pm: Implementation du couple frameheader/framefooter dans le mdreader, mise en valeur des blocs de code, changement de structure de certaines includes pour limiter les temps de chargement au strict nécessaire.
- May 22, 2026, 3:38 pm: Fix de l'export SQL(mauvais échappement de backslash multiples)
- May 22, 2026, 4:38 pm: Modification de la page d'accueil BeamReactor pour montrer la compatibilité LLM universelle tant côté MCP que tiers/fournisseur/interne (auto hébergée) avec configuration simple.
- May 27, 2026, 11:40 pm: Grosse opération de réduction des zones d'attaque potentielles en transferant les locales vers un format JSON:\n\nRename mécanique des $dialXX historiques → $dial<plugin_literal> partout (104 plugins traités, ~1500 occurrences).\ngetlocale() étendu pour gérer JSON en priorité + fallback .inc.php.\nCache plugins.cache.php étendue: porte plugin_meta[lang][plugin] avec meta extraite par regex. login_success et plugin_catalog passent de N includes/requête à un lookup tableau (optimisation de chargement).\nPattern déclaratif _plugincall_query + _plugincall_template.\nHistorique modifié pour permettre la soumission de paragraphes complets.
- May 28, 2026, 8:45 pm: Implicit conversion from float 104.25311203319502 to int loses precision (error_logger)
- June 11, 2026, 12:15 am: Fixed potential XSS vulnerabilities in the CAP Parser and updated the rss_syndicator. Updated the URL datatype to force a scheme. Removed some calls to the now deprecated cleandata function. Updated the Claude/Anthropic compatibility model. updated the prompt for Gemini that would refuse to work under certain circumstances"
- June 11, 2026, 12:19 am: Creation de 2 mini plugins pour l'entrainement aux verbes irréguliers Allemands et au vocabulaire Anglais. Reimplémentation de la skin CSS1 pour rendre la structure claire pour des développeurs tiers. Mise à jour de la classe Calendar pour permettre le déclenchement d'évènements corrélés liés à la classe TODO et à la CMDB. Reflexions autour d'un module STIX d'export de tentatives d'attaques pour synchronisation vers des systèmes de syndication globaux.
- June 13, 2026, 1:19 pm: Readded Grok to the MCP with the proper grok/gpt routing. Fixed the MCP for RTE compatibility. Updated the RTE
- June 13, 2026, 1:20 pm: Mise à jour du calendrier (changement des locales pour déplacer la logique d'affichage des catégories)
- June 20, 2026, 3:25 pm: Planifié : création d'un outil MCP pour l'accès au calendrier, avec restriction des permissions à l'utilisateur courant.
- June 20, 2026, 3:34 pm: Mise à jour du notepad (comportement général, obfuscation des noms plus robuste), des css du plugin todo, de certaines locales
- June 22, 2026, 1:28 am: Fixed type error in SiteIndexer::extractContentFromHTML where MdParser returned an array instead of a string.
- June 22, 2026, 10:47 pm: Removed stray print_r in updater manifest fetch and added display of cURL/HTTP errors in the DOM if fetching the update manifest fails.
- June 22, 2026, 11:23 pm: Fixed HTTP response codes being lost during the final output buffer assembly in index.php (ensures 403, 404, etc. are properly sent to the client instead of reverting to 200). Added whitelist in hax.inc.php to prevent Updater from being banned.
- June 22, 2026, 11:36 pm: Secured versions.rss.php using fleet_peers database to validate remote sites and track their last_seen timestamp.
- June 23, 2026, 12:50 am: Updated WriteNotepad MCP tool to properly align with the database-driven implementation and user pseudonymization (HMAC-SHA256) instead of using flat files.

Full history →

Didn't find your answer?

Open a ticket or get in touch.

de en fr