ludiWARE

Platform version history (newest first).

v1.2.12026-08-09 16:47:35Extensible My account and classifieds lightboxPlugins can add My account tabs (e.g. My listings). Public pages now inject the classifieds gallery script at the end of the HTML.
For users
- My account: extensions can register new tabs via the CMS (?tab=… URLs).
- Classifieds 1.2.12: “My listings” tab with edit, delete, and mark as sold.
- Ad photo lightbox: works on CMS token pages too (not only /classifieds/… routes).

Why this change
- Keep listing management in My account alongside profile settings.
- Fix the gallery when ad HTML is rendered inside a site page without the plugin front router.

Technical notes
- CMS filters: public_account_tabs, public_account_tab_panels, public_account_post_actions, public_accounts_handle_post, public_page_html.
- Classifieds plugin: sold status, owner actions, defer gallery JS v4.
v1.2.0 Package2026-08-09 15:29:10ludiWARE 1.2.0 — public profiles and member identityMinor release 1.2.0: full install packages (ZIP + tar.gz), public member profiles, clickable names site-wide, unified activity history on profiles, and republished Forums / Classifieds plugins.
For users
- Download: ludiware-1.2.0.tar.gz + ludiware-1.2.0.zip
- Repo: https://repo.ludiware.com/releases/1.2.0/
- Includes /install/ wizard

CMS highlights (since 1.1.x)
- Public member profile: /membre/{uid} (avatar, name, member since)
- Member names link to profiles (blog, account strip, extensions)
- Activity history on profile: blog comments, forum topics/replies, classified ads and comments
- `public_member_profile_activity` filter for extensions

Republished MarketPlace plugins
- Forums 1.0.18 (profile links + forum activity)
- Classifieds 1.2.9 (linked comments, listing activity)

Technical notes
- OSS export without factory secrets
- VersionLog FileName → public tar.gz on repo.ludiware.com

Télécharger le package

v1.1.142026-08-09 15:26:40Activity history on public profileA member’s profile page now shows a unified timeline of their public contributions: blog comments, forum topics and replies, classified ads and ad comments.
For visitors
- “Public activity” section under the profile header (/membre/{uid}).
- Each row: date, action type, clickable title to the content, short excerpt when available.
- Newest first (up to 60 items), mixing blog, forums and active plugins.

For developers / extensions
- New `public_member_profile_activity` filter — return items `{at, kind, label, title, url, excerpt?}`.
- Helpers: `lw_public_accounts_collect_member_activity()`, `lw_public_accounts_render_member_activity_html()`, `lw_public_accounts_member_activity_item()`.
- Blog: `lw_blog_member_public_activity()` (published comments).
- Plugins register sources via the filter (Forums, Classifieds).

Why
- One consolidated view of a member’s public presence instead of isolated per-plugin sections.
v1.1.132026-08-09 15:23:12Member names link to public profileWherever a registered member appears (blog comments, account strip, etc.), their name now links to their public profile page when that profile is visible.
For visitors
- Click a local active member’s name → /membre/{uid} (or /member/{uid} in English).
- Account strip “Signed in as …”: your display name links to your profile.
- Blog post comments: authors tied to a local member account get a profile link.
- Guests, CDS portal users, or authors without a member account: plain text name (unchanged).

For developers / extensions
- Central helpers: `lw_public_accounts_author_context_from_row()`, `lw_public_accounts_resolve_content_author()`, `lw_public_accounts_render_author_name_html()`.
- Shared CSS class `lw-member-profile-link` for profile links.

Why
- Consistent public member identity across the site (blog, forums, classifieds, etc.) following public profiles in 1.1.12.
v1.1.122026-08-09 15:17:27Public profile for registered membersEach locally registered site member gets a public profile page with avatar and display name. Extensions can append content (e.g. published classifieds).
For visitors
- Public URL: /membre/{uid} (FR) or /member/{uid} (EN) — avatar, display name, member since date.
- Profiles are shown only for active local member accounts, not admins or CentreDeService portal users.

For developers / extensions
- New `public_member_profile_html` filter to extend the page (Classifieds plugin lists published ads).
- Helpers: `lw_public_accounts_public_profile_url()`, `lw_public_accounts_user_by_uid_public()`.

Why
- Let visitors see who published content and build a consistent public identity on the site.
v1.1.112026-08-09 14:33:21Standardized alerts for admin and pluginsNew unified alert system: success, error, warning, and info messages are shown consistently in lw-admin and on the public site. Plugins can contribute through dedicated hooks.
For users
- Admin confirmations and errors (e.g. “Listing deleted”, “Settings saved”) now appear at the top of the page in a consistent banner.
- On the public site, plugins can show user messages with the same visual style.

Why
- Each module and plugin handled its own alerts (different variables, query strings, custom CSS), causing duplication and inconsistency.

Technical notes
- New module lw-admin/functions/flash.php: lw_flash_add(), lw_flash_redirect(), lw_flash_render_html(), lw_public_flash_html().
- admin_flash and public_flash hooks for extensions.
- Backward compatible with $lwFlash and $lwPageFlashError.
- Shared lw-flash.css for admin/public.
- Classifieds plugin migrated as an example (v1.2.2).
v1.1.102026-08-08 18:52:20Portable site-to-site configurationconfig.php no longer holds secrets or factory domain settings: database, emails, and environment overrides live in config.local.php; hostname and defaults are inferred automatically.
For users
- Copy the CMS between sites without editing config.php: only config.local.php (or the /install/ wizard) needs to match the new host.
- Cookies and site name follow the real domain when HTTPpath / COOKIEpath are omitted.

Why
- config.php mixed MySQL credentials, the ludiware.com domain, and factory emails, making every client deploy error-prone.

Technical notes
- lw_config_detect_http_host() + lw_config_apply_runtime_defaults() after config.local.php.
- MySQL connects only when DBhost / DBname / DBusername are set.
- Updated config.local.example.php and installer (domain optional).
v1.1.92026-08-08 17:58:54Modal sign-in fix (POST fields + SQL)Sign-in from the modal now reliably sends email and password (POST to the current page, fields read explicitly) and works on hosts without mysqlnd.
For users
- The login/register modal posts to the page you are on (not only /sign-in/), avoiding silent failures.
- If the account has no password (Google/Facebook admin sign-in), a clear message appears instead of “invalid email or password”.

Why
- On some themes, fields did not always have a name attribute when FormData ran; on some hosts, user SQL reads failed without mysqlnd.

Technical notes
- lw-account-forms.js v4: explicit buildFormData; action = current page in modals.
- lw_public_accounts_stmt_fetch_one_assoc(); modal forms: post_url injected at render.
v1.1.82026-08-08 17:51:46Admin recognition on public site + cookie domainAn administrator signed into lw-admin is recognized again on the public site (My account header). Cookies align with the site’s actual domain (e.g. dormezcheznous.com).
For users
- If you are signed into lw-admin on the same domain as the public site, the header shows “My account” without using the modal again.
- After signing in via the modal, the public session persists.
- Check config.local.php: COOKIEpath must match the site domain (not ludiware.com if the site uses another hostname).

Why
- Admin cookies were sometimes set for ludiware.com while the site runs on a custom domain; the public site never received them. Modal sign-in could also fail when mismatched admin cookies interfered.

Technical notes
- lw_cookie_domain() uses current HTTP host when it differs from COOKIEpath.
- lw_public_accounts_auth_from_cookies() + member session sync.
- Auth bootstrap on public index.php.
v1.1.72026-08-08 17:31:50Conditional account header (snippets / tokens)Show “Sign in” or “My account” in the header based on session state, using an HTML snippet and {{​account_if_guest}} / {{​account_if_logged_in}} tokens.
For users
- In an HTML snippet (or layout): wrap the Sign in button with {{​account_if_guest}}…{{​/account_if_guest}} and My account with {{​account_if_logged_in}}…{{​/account_if_logged_in}}.
- Useful tokens: {{​account_account_url}}, {{​account_user_name}}, {{​account_logout_url}}, {{​account_logged_in}} (1 or empty).
- Put  in the layout header.
- Built-in alternative: {{​account_strip}} (lw-admin banner).
- PHP snippets: $lw_db variable + lw_public_accounts_viewer().

Why
- Imported themes like DormezChezNous need a custom Bootstrap/modal button, not the generic banner.

Technical notes
- lw_public_accounts_apply_conditional_blocks() in apply_tokens; $lw_db exposed to PHP snippets.
v1.1.62026-08-08 17:25:08Account modal AJAX fix (Homelengo themes)Sign-in from a modal did not react on click: the account script now intercepts the click before theme scripts, shows errors (removes d-none), and shows loading state on the button.
For users
- The “Sign in” button in the modal works again: “…” while sending, visible red error on failure, page reload on success.
- No HTML change needed if data-lw-account and data-lw-account-error are already set.

Why
- Imported themes (Homelengo / DormezChezNous) registered listeners that blocked submit before our script; errors also stayed hidden behind Bootstrap d-none.

Technical notes
- lw-account-forms.js v3: capture click + submit, loaded last before </body>.
- Automatically removes d-none on data-lw-account-error.
v1.1.52026-08-08 17:13:29AJAX sign-in and register (modals)Account forms inside a modal (Bootstrap or similar) can submit without a full page reload: errors show in the modal, and the page refreshes after a successful sign-in.
For users
- If your login/register form is inside a modal (.modal or role="dialog"), submission uses AJAX automatically — no redirect to /sign-in/ that breaks the flow.
- Add an error slot: <div data-lw-account-error></div> in the modal.
- Force or disable: data-lw-account-ajax="1" or "0" on the <form>.
- On success: default is page reload (account menu updates); data-lw-account-on-success="redirect" to go to My account.
- Register captcha refreshes automatically after a failed attempt.

Why
- Sites like DormezChezNous open login/register in popups; a classic POST reloaded the whole page.

Technical notes
- lw-account-forms.js injected when data-lw-account is present.
- JSON responses server-side (lw_public_accounts_handle_post); index.php hook for POST from any page.
v1.1.42026-08-08 16:54:04Custom account forms (data-lw-account)Use your own HTML sign-in and register forms in the theme: the engine wires them automatically and exposes error messages via tokens or dedicated slots.
For users
- Form marker: data-lw-account="login" or "register" (also forgot, reset, profile, security).
- Fields: data-lw-account-field="email|password|…" or auto-detect via id/name/placeholder (like contact).
- Errors: {{​account_error_text}} in your HTML, or <div data-lw-account-error></div>.
- Success: {{​account_success_text}} or data-lw-account-success.
- Replace {{​account_login}} with your markup on the /connexion/ shell page if you do not want the default lw-admin form.
- Register: <div class="lw-account-captcha-slot"></div> for captcha.
- Optional OAuth: <div data-lw-account-oauth></div>.

Why
- Imported themes like DormezChezNous keep their Bootstrap design without duplicating account logic.

Technical notes
- account_forms.php (same pattern as data-lw-contact).
- Injects CSRF + lw_account_action; POST action targets /connexion/, /register/, etc.
v1.1.32026-08-08 12:47:55HTML editors with syntax highlighting and tabsAll admin HTML and code fields now have syntax highlighting and Tab indentation (4 spaces), including TinyMCE’s source code view.
For users
- Raw HTML fields (header, footer, snippets, templates, custom CSS, etc.): line numbers, highlighting, Tab to indent.
- TinyMCE rich editor: the source code button opens the same highlighted experience.
- Imported themes: direct HTML editing with highlighting.

Why
- Easier markup editing without an external IDE.
- Tab inserts consistent indentation; Shift+Tab outdents.

Technical notes
- lw-code-editor.js module (CodeMirror 5 via CDN).
- html, css, and php modes per field.
- App-shell navigation compatible (reinit after page change).
v1.1.22026-08-08 11:37:45In-app CMS update and footer alertRemote installations show a visible admin footer warning when a newer package is available, and can install the update from Settings → Versions without manually re-uploading files.
For users
- Admin footer: “Update available (vX.Y.Z)” badge when a newer VersionLog package is published on repo.ludiware.com.
- Settings → Versions: banner with “Update now” (automatic download and deploy).
- Preserved local files: config.local.php, config.php (only the Version line is updated), uploads/, storage/, installed extensions.

Why
- Avoid manual FTP/SFTP updates on every hosted site.
- Surface an outdated version (e.g. 1.0.53 vs 1.1.x) without digging through history.

Technical notes
- lw_cms_update_apply(): downloads ZIP/tar.gz from repo.ludiware.com, extracts and copies core files.
- lw_versionlog_check_update() unchanged (30 min cache).
- Settings sidebar badge + chrome alert for managers.
v1.1.12026-08-08 11:30:24Version history: readable tokens and bracesVersionLog entries no longer show raw HTML codes ({): tokens like {{​account_login}} display normally.
For visitors
- History page: CMS token examples show as plain text (visible braces), without double-encoded HTML entities.

Why
- Some VersionLog entries mentioned HTML entities ({) in their text; htmlspecialchars() displayed them literally on screen.

Technical
- lw_versionlog_prepare_display_source(): decode brace entities before zero-width neutralization and lw_e().
v1.1.0 Package2026-08-08 11:28:14ludiWARE 1.1.0 — public distributionMinor release 1.1.0: full install package (ZIP + tar.gz), public OAuth accounts, public version history, contact form prefill, and updated MarketPlace plugins.
For users
- Download: ludiware-1.1.0.tar.gz + ludiware-1.1.0.zip
- Repo: https://repo.ludiware.com/releases/1.1.0/
- Includes /install/ wizard (database, schema, admin account)

Since the 1.0.40 distribution
- Local member accounts: sign-up, login, forgot password, My account (profile / security tabs)
- Google and Facebook OAuth on the public site
- Public header recognizes lw-admin session and OAuth members
- 

Platform version history (newest first).

v1.2.12026-08-09 16:47:35Extensible My account and classifieds lightboxPlugins can add My account tabs (e.g. My listings). Public pages now inject the classifieds gallery script at the end of the HTML.
For users
- My account: extensions can register new tabs via the CMS (?tab=… URLs).
- Classifieds 1.2.12: “My listings” tab with edit, delete, and mark as sold.
- Ad photo lightbox: works on CMS token pages too (not only /classifieds/… routes).

Why this change
- Keep listing management in My account alongside profile settings.
- Fix the gallery when ad HTML is rendered inside a site page without the plugin front router.

Technical notes
- CMS filters: public_account_tabs, public_account_tab_panels, public_account_post_actions, public_accounts_handle_post, public_page_html.
- Classifieds plugin: sold status, owner actions, defer gallery JS v4.
v1.2.0 Package2026-08-09 15:29:10ludiWARE 1.2.0 — public profiles and member identityMinor release 1.2.0: full install packages (ZIP + tar.gz), public member profiles, clickable names site-wide, unified activity history on profiles, and republished Forums / Classifieds plugins.
For users
- Download: ludiware-1.2.0.tar.gz + ludiware-1.2.0.zip
- Repo: https://repo.ludiware.com/releases/1.2.0/
- Includes /install/ wizard

CMS highlights (since 1.1.x)
- Public member profile: /membre/{uid} (avatar, name, member since)
- Member names link to profiles (blog, account strip, extensions)
- Activity history on profile: blog comments, forum topics/replies, classified ads and comments
- `public_member_profile_activity` filter for extensions

Republished MarketPlace plugins
- Forums 1.0.18 (profile links + forum activity)
- Classifieds 1.2.9 (linked comments, listing activity)

Technical notes
- OSS export without factory secrets
- VersionLog FileName → public tar.gz on repo.ludiware.com

Télécharger le package

v1.1.142026-08-09 15:26:40Activity history on public profileA member’s profile page now shows a unified timeline of their public contributions: blog comments, forum topics and replies, classified ads and ad comments.
For visitors
- “Public activity” section under the profile header (/membre/{uid}).
- Each row: date, action type, clickable title to the content, short excerpt when available.
- Newest first (up to 60 items), mixing blog, forums and active plugins.

For developers / extensions
- New `public_member_profile_activity` filter — return items `{at, kind, label, title, url, excerpt?}`.
- Helpers: `lw_public_accounts_collect_member_activity()`, `lw_public_accounts_render_member_activity_html()`, `lw_public_accounts_member_activity_item()`.
- Blog: `lw_blog_member_public_activity()` (published comments).
- Plugins register sources via the filter (Forums, Classifieds).

Why
- One consolidated view of a member’s public presence instead of isolated per-plugin sections.
v1.1.132026-08-09 15:23:12Member names link to public profileWherever a registered member appears (blog comments, account strip, etc.), their name now links to their public profile page when that profile is visible.
For visitors
- Click a local active member’s name → /membre/{uid} (or /member/{uid} in English).
- Account strip “Signed in as …”: your display name links to your profile.
- Blog post comments: authors tied to a local member account get a profile link.
- Guests, CDS portal users, or authors without a member account: plain text name (unchanged).

For developers / extensions
- Central helpers: `lw_public_accounts_author_context_from_row()`, `lw_public_accounts_resolve_content_author()`, `lw_public_accounts_render_author_name_html()`.
- Shared CSS class `lw-member-profile-link` for profile links.

Why
- Consistent public member identity across the site (blog, forums, classifieds, etc.) following public profiles in 1.1.12.
v1.1.122026-08-09 15:17:27Public profile for registered membersEach locally registered site member gets a public profile page with avatar and display name. Extensions can append content (e.g. published classifieds).
For visitors
- Public URL: /membre/{uid} (FR) or /member/{uid} (EN) — avatar, display name, member since date.
- Profiles are shown only for active local member accounts, not admins or CentreDeService portal users.

For developers / extensions
- New `public_member_profile_html` filter to extend the page (Classifieds plugin lists published ads).
- Helpers: `lw_public_accounts_public_profile_url()`, `lw_public_accounts_user_by_uid_public()`.

Why
- Let visitors see who published content and build a consistent public identity on the site.
v1.1.112026-08-09 14:33:21Standardized alerts for admin and pluginsNew unified alert system: success, error, warning, and info messages are shown consistently in lw-admin and on the public site. Plugins can contribute through dedicated hooks.
For users
- Admin confirmations and errors (e.g. “Listing deleted”, “Settings saved”) now appear at the top of the page in a consistent banner.
- On the public site, plugins can show user messages with the same visual style.

Why
- Each module and plugin handled its own alerts (different variables, query strings, custom CSS), causing duplication and inconsistency.

Technical notes
- New module lw-admin/functions/flash.php: lw_flash_add(), lw_flash_redirect(), lw_flash_render_html(), lw_public_flash_html().
- admin_flash and public_flash hooks for extensions.
- Backward compatible with $lwFlash and $lwPageFlashError.
- Shared lw-flash.css for admin/public.
- Classifieds plugin migrated as an example (v1.2.2).
v1.1.102026-08-08 18:52:20Portable site-to-site configurationconfig.php no longer holds secrets or factory domain settings: database, emails, and environment overrides live in config.local.php; hostname and defaults are inferred automatically.
For users
- Copy the CMS between sites without editing config.php: only config.local.php (or the /install/ wizard) needs to match the new host.
- Cookies and site name follow the real domain when HTTPpath / COOKIEpath are omitted.

Why
- config.php mixed MySQL credentials, the ludiware.com domain, and factory emails, making every client deploy error-prone.

Technical notes
- lw_config_detect_http_host() + lw_config_apply_runtime_defaults() after config.local.php.
- MySQL connects only when DBhost / DBname / DBusername are set.
- Updated config.local.example.php and installer (domain optional).
v1.1.92026-08-08 17:58:54Modal sign-in fix (POST fields + SQL)Sign-in from the modal now reliably sends email and password (POST to the current page, fields read explicitly) and works on hosts without mysqlnd.
For users
- The login/register modal posts to the page you are on (not only /sign-in/), avoiding silent failures.
- If the account has no password (Google/Facebook admin sign-in), a clear message appears instead of “invalid email or password”.

Why
- On some themes, fields did not always have a name attribute when FormData ran; on some hosts, user SQL reads failed without mysqlnd.

Technical notes
- lw-account-forms.js v4: explicit buildFormData; action = current page in modals.
- lw_public_accounts_stmt_fetch_one_assoc(); modal forms: post_url injected at render.
v1.1.82026-08-08 17:51:46Admin recognition on public site + cookie domainAn administrator signed into lw-admin is recognized again on the public site (My account header). Cookies align with the site’s actual domain (e.g. dormezcheznous.com).
For users
- If you are signed into lw-admin on the same domain as the public site, the header shows “My account” without using the modal again.
- After signing in via the modal, the public session persists.
- Check config.local.php: COOKIEpath must match the site domain (not ludiware.com if the site uses another hostname).

Why
- Admin cookies were sometimes set for ludiware.com while the site runs on a custom domain; the public site never received them. Modal sign-in could also fail when mismatched admin cookies interfered.

Technical notes
- lw_cookie_domain() uses current HTTP host when it differs from COOKIEpath.
- lw_public_accounts_auth_from_cookies() + member session sync.
- Auth bootstrap on public index.php.
v1.1.72026-08-08 17:31:50Conditional account header (snippets / tokens)Show “Sign in” or “My account” in the header based on session state, using an HTML snippet and {{​​​​account_if_guest}} / {{​​​​account_if_logged_in}} tokens.
For users
- In an HTML snippet (or layout): wrap the Sign in button with {{​​​​account_if_guest}}…{{​​​​/account_if_guest}} and My account with {{​​​​account_if_logged_in}}…{{​​​​/account_if_logged_in}}.
- Useful tokens: {{​​​​account_account_url}}, {{​​​​account_user_name}}, {{​​​​account_logout_url}}, {{​​​​account_logged_in}} (1 or empty).
- Put {{​​​​snippet:your_key}} in the layout header.
- Built-in alternative: {{​​​​account_strip}} (lw-admin banner).
- PHP snippets: $lw_db variable + lw_public_accounts_viewer().

Why
- Imported themes like DormezChezNous need a custom Bootstrap/modal button, not the generic banner.

Technical notes
- lw_public_accounts_apply_conditional_blocks() in apply_tokens; $lw_db exposed to PHP snippets.
v1.1.62026-08-08 17:25:08Account modal AJAX fix (Homelengo themes)Sign-in from a modal did not react on click: the account script now intercepts the click before theme scripts, shows errors (removes d-none), and shows loading state on the button.
For users
- The “Sign in” button in the modal works again: “…” while sending, visible red error on failure, page reload on success.
- No HTML change needed if data-lw-account and data-lw-account-error are already set.

Why
- Imported themes (Homelengo / DormezChezNous) registered listeners that blocked submit before our script; errors also stayed hidden behind Bootstrap d-none.

Technical notes
- lw-account-forms.js v3: capture click + submit, loaded last before </body>.
- Automatically removes d-none on data-lw-account-error.
v1.1.52026-08-08 17:13:29AJAX sign-in and register (modals)Account forms inside a modal (Bootstrap or similar) can submit without a full page reload: errors show in the modal, and the page refreshes after a successful sign-in.
For users
- If your login/register form is inside a modal (.modal or role="dialog"), submission uses AJAX automatically — no redirect to /sign-in/ that breaks the flow.
- Add an error slot: <div data-lw-account-error></div> in the modal.
- Force or disable: data-lw-account-ajax="1" or "0" on the <form>.
- On success: default is page reload (account menu updates); data-lw-account-on-success="redirect" to go to My account.
- Register captcha refreshes automatically after a failed attempt.

Why
- Sites like DormezChezNous open login/register in popups; a classic POST reloaded the whole page.

Technical notes
- lw-account-forms.js injected when data-lw-account is present.
- JSON responses server-side (lw_public_accounts_handle_post); index.php hook for POST from any page.
v1.1.42026-08-08 16:54:04Custom account forms (data-lw-account)Use your own HTML sign-in and register forms in the theme: the engine wires them automatically and exposes error messages via tokens or dedicated slots.
For users
- Form marker: data-lw-account="login" or "register" (also forgot, reset, profile, security).
- Fields: data-lw-account-field="email|password|…" or auto-detect via id/name/placeholder (like contact).
- Errors: {{​​​​account_error_text}} in your HTML, or <div data-lw-account-error></div>.
- Success: {{​​​​account_success_text}} or data-lw-account-success.
- Replace {{​​​​account_login}} with your markup on the /connexion/ shell page if you do not want the default lw-admin form.
- Register: <div class="lw-account-captcha-slot"></div> for captcha.
- Optional OAuth: <div data-lw-account-oauth></div>.

Why
- Imported themes like DormezChezNous keep their Bootstrap design without duplicating account logic.

Technical notes
- account_forms.php (same pattern as data-lw-contact).
- Injects CSRF + lw_account_action; POST action targets /connexion/, /register/, etc.
v1.1.32026-08-08 12:47:55HTML editors with syntax highlighting and tabsAll admin HTML and code fields now have syntax highlighting and Tab indentation (4 spaces), including TinyMCE’s source code view.
For users
- Raw HTML fields (header, footer, snippets, templates, custom CSS, etc.): line numbers, highlighting, Tab to indent.
- TinyMCE rich editor: the source code button opens the same highlighted experience.
- Imported themes: direct HTML editing with highlighting.

Why
- Easier markup editing without an external IDE.
- Tab inserts consistent indentation; Shift+Tab outdents.

Technical notes
- lw-code-editor.js module (CodeMirror 5 via CDN).
- html, css, and php modes per field.
- App-shell navigation compatible (reinit after page change).
v1.1.22026-08-08 11:37:45In-app CMS update and footer alertRemote installations show a visible admin footer warning when a newer package is available, and can install the update from Settings → Versions without manually re-uploading files.
For users
- Admin footer: “Update available (vX.Y.Z)” badge when a newer VersionLog package is published on repo.ludiware.com.
- Settings → Versions: banner with “Update now” (automatic download and deploy).
- Preserved local files: config.local.php, config.php (only the Version line is updated), uploads/, storage/, installed extensions.

Why
- Avoid manual FTP/SFTP updates on every hosted site.
- Surface an outdated version (e.g. 1.0.53 vs 1.1.x) without digging through history.

Technical notes
- lw_cms_update_apply(): downloads ZIP/tar.gz from repo.ludiware.com, extracts and copies core files.
- lw_versionlog_check_update() unchanged (30 min cache).
- Settings sidebar badge + chrome alert for managers.
v1.1.12026-08-08 11:30:24Version history: readable tokens and bracesVersionLog entries no longer show raw HTML codes ({): tokens like {{​​​​account_login}} display normally.
For visitors
- History page: CMS token examples show as plain text (visible braces), without double-encoded HTML entities.

Why
- Some VersionLog entries mentioned HTML entities ({) in their text; htmlspecialchars() displayed them literally on screen.

Technical
- lw_versionlog_prepare_display_source(): decode brace entities before zero-width neutralization and lw_e().
v1.1.0 Package2026-08-08 11:28:14ludiWARE 1.1.0 — public distributionMinor release 1.1.0: full install package (ZIP + tar.gz), public OAuth accounts, public version history, contact form prefill, and updated MarketPlace plugins.
For users
- Download: ludiware-1.1.0.tar.gz + ludiware-1.1.0.zip
- Repo: https://repo.ludiware.com/releases/1.1.0/
- Includes /install/ wizard (database, schema, admin account)

Since the 1.0.40 distribution
- Local member accounts: sign-up, login, forgot password, My account (profile / security tabs)
- Google and Facebook OAuth on the public site
- Public header recognizes lw-admin session and OAuth members
- {{​​​​versionlog}} token: version history on the public site
- Contact form: name and email prefilled when signed in
- Bootstrap Icons + admin icon picker
- MarketPlace plugins: FAQ, Testimonials, Gallery, Forms, Booking, Classifieds, Forums

Republished plugins (MarketPlace)
- Forums 1.0.16
- Classifieds 1.0.15

Technical notes
- OSS export without factory secrets; VersionLog FileName → public tar.gz.

Télécharger le package

v1.0.612026-08-08 11:25:48Version history: tokens display normallyExamples like {{​​​​account_login}} in version history show as readable text, without visible HTML entities ({).
For visitors / administrators
- History page and Settings → Versions: cited tokens appear as {{​​​​account_login}}, not as {{​​account_login}}.

Why
- Escaping braces as HTML entities then running htmlspecialchars() double-encoded and showed raw codes on screen.

Technical
- Zero-width space neutralization only (no { entities) in lw_versionlog_format_display_text() and lw_versionlog_shield_public_html().
v1.0.602026-08-08 11:24:31Contact form: name and email prefilled when signed inOn the contact form, Name and Email fields are filled automatically when the visitor is already signed in (local account, lw-admin, or CDS portal).
For users
- {{​​​​contact_form}} and theme ZIP contact forms: Name and Email prefilled when signed in.
- Fields already set in the template are not overwritten.

Why
- Avoid re-entering identity on every contact message.

Sources
- CDS portal (SSO session): full name + contact email.
- Public member account or lw-admin cookie: display_name + lw_users email.

Technical
- lw_contact_prefill_identity(), lw_contact_apply_prefill_to_form(), lw_contact_form_html().
v1.0.592026-08-08 11:20:46{{​​​​versionlog}} token works on the public siteThe {{​​​​versionlog}} token is now recognized on the public site: the History page shows the version list instead of the raw token text.
For visitors
- History page: {{​​​​versionlog}} content is replaced by the version list (styles and safe text).

Why
- The VersionLog module was only loaded in lw-admin; on index.php (public front), lw_versionlog_prepare_public_html() was missing and the token stayed literal.

Technical
- require versionlog.php in www/index.php before public_render.php.
v1.0.582026-08-08 11:07:13Public version history: CMS tokens shown as plain textOn the ludiware.com History page, mentions like {{​​​​account_login}}, {{​​​​menu:main}}, etc. in VersionLog entries display as text instead of injecting forms or menus.
For visitors
- History page (/historique/): version title, description and details show cited tokens as documentation, with no login form or menu injected mid-sentence.

Why
- VersionLog content is rendered via a PHP snippet then processed by the CMS token engine; example {{​​​​account_login}} was executed as a real token.

Technical
- Native {{​​​​versionlog}} / {{​​​​versionlog_list}} token; .lw-vl-* blocks shielded before the token pipeline; HTML entities for {{​​​​ and }} on display.
v1.0.572026-08-08 10:58:52Version history: CMS tokens shown as plain textMentions like {{​​​​account_login}}, {{​​​​menu:main}}, etc. in VersionLog technical details are no longer interpreted as CMS tokens.
For administrators
- Settings → Version history: title, description and full details show tokens literally (documentation), with no forms or injected content.

Why
- VersionLog entries often cite tokens as examples in “Technical detail”; the token engine must not execute them on display.

Technical
- Neutralize {{​​​​ → {{​​​​ + zero-width space on API output and lw-admin client; HTML-escaped display.
v1.0.562026-08-08 10:54:16Public header: lw-admin session recognitionWhen signed into lw-admin, you also appear as a member on the public site (header, My account), consistent with blog comments.
For visitors / administrators
- lw-admin cookies → {{​​​​account_strip}} shows your name and “My account”.
- /account/ works without visiting /login/ again.
- /login/ and /register/ redirect to My account when already recognized.

Identity priority (unchanged for blog when a Facebook session is active)
1. Public member session (login / OAuth)
2. lw-admin cookie

Public sign-out clears the member session only; if lw-admin remains, you stay signed in.
v1.0.552026-08-08 10:38:20Blog and forums: public member identity firstOn the public site, the member session (login / Facebook / Google) now takes precedence over lw-admin cookies for blog comments.
Fixed issue
- Header “Signed in as…” (member session) and blog “Commenting as…” (admin cookies) could show two different people when logged into lw-admin and Facebook on the public site.

Behavior
- Priority: CDS portal → public member (session) → admin staff (lw-admin cookie).
- Blog login hint links to /login/ when local accounts are active (no CDS).

Note
- If Facebook created a second lw_users account (different email from admin), that is expected: two separate profiles. Merge manually or delete the duplicate in Users.
v1.0.542026-08-08 10:11:29OAuth — stable redirect URLThe Google/Facebook callback URL in site settings now uses the site’s public domain (e.g. ludiware.com), not the admin host.
For administrators
- Settings → Member accounts: the “authorized redirect” URL matches the site’s public domain.
- Help note for adding the URI in Facebook Login → Valid OAuth Redirect URIs.

Why
- When opened from the admin panel (different subdomain), the generated URL could differ from the one used on the public site.
v1.0.532026-08-08 10:03:23Google and Facebook sign-in for membersVisitors can sign in or register with Google or Facebook on login and register pages when local accounts are used (no CentreDeService portal). A local member profile is created automatically when needed.
For visitors
- “Sign in with Google” and “Sign in with Facebook” on /login/ and /register/ (FR: /connexion/, /inscription/).
- If the email is not registered yet, a member account is created and the session starts.
- If an account already exists with the same email, the OAuth profile is linked to it.

For administrators
- Site settings → Member accounts: enable providers, OAuth credentials, and redirect URLs to paste into Google Cloud / Facebook Developer.
- Automatically disabled when the CentreDeService portal handles authentication.

Technical
- lw_users google_id / facebook_id columns, oauth_accounts.php module, /oauth/{provider}/callback/ routes.
v1.0.522026-08-08 08:35:18Icon picker — full catalogThe icon picker now shows useful favorites first, then all Bootstrap icons (~1,600) via search.
For administrators
- On open: a grid of favorites (home, commerce, transport, etc.).
- Search: filters the full set of ~1,683 installed Bootstrap Icons.
- Result count and message when the list is truncated.

Fix
- The list was previously capped at 120 icons in alphabetical order (123, alarm…), which felt incomplete.
v1.0.512026-08-08 08:29:09Bootstrap Icons and icon pickerBootstrap Icons now render reliably across the admin with complete font files. A reusable icon picker is available for forms (search, grid, preview).
For administrators
- Bootstrap Icons font files (woff/woff2) installed so existing `bi-*` icons in lw-admin display correctly.
- New reusable icon picker component (`lw_icon_picker_field`) for any admin form.

Usage
- Button with icon preview, name search, clickable grid, and a “No icon” option.
- PHP helpers `lw_bootstrap_icon_names()` and `lw_bootstrap_icon_class()`.

Technical
- Files: `functions/icon_picker.php`, `js/lw-icon-picker.js`, styles in `lw-admin.css`.
v1.0.502026-08-08 07:27:10My account — profile and security tabsThe My account page has two tabs: My information (first name, last name, avatar) and Access & security (email, password). New tokens for ZIP templates.
For users
- My information tab: first name, last name, avatar upload.
- Access & security tab: change email and/or password (current password required).

ZIP tokens
- {{​​​​account_panel}}: full panel with tabs.
- {{​​​​account_tabs}}, {{​​​​account_profile}}, {{​​​​account_security}}: custom layout.
- {{​​​​account_avatar}}, {{​​​​account_avatar_url}}, {{​​​​account_first_name}}, {{​​​​account_last_name}}, {{​​​​account_email}}.
- {{​​​​account_profile_url}}, {{​​​​account_security_url}}: direct links to each tab.

Technical notes
- lw_users.avatar_path column, files in uploads/users/, public session synced after updates.
v1.0.492026-08-08 07:17:18Public accounts unified in lw_usersRegistration, sign-in and forgot password on the public site now use the lw_users table (same as lw-admin). Only accounts with admin access can open lw-admin.
For users
- Same email and password everywhere: admin or visitor registered at /register/.
- Accounts created on the public site have the user role and cannot access lw-admin.
- Administrators can also sign in at /login/ with their usual credentials.

Why
- Removes the mistaken dual lw_site_members / lw_users system.

Technical notes
- public_accounts.php: auth, registration and reset on lw_users; per-site public session.
- auth.php unchanged: can_access_admin required for lw-admin.
- Obsolete lw_site_members table can be dropped in the database (DROP TABLE).
v1.0.482026-08-08 07:11:33Public sign-in with an administrator accountSite administrators can sign in on the public site (/login/) using the same email and password as lw-admin, without a separate registration.
For users
- At /login/, a global administrator or a user assigned to the site is accepted with lw-admin credentials.
- The first sign-in automatically creates the local member profile for that site; later sign-ins reuse it.

Why
- Before this fix, only accounts registered via /register/ (lw_site_members) were recognized; the first admin saw “Invalid email or password.”

Technical notes
- lw_users → lw_site_members bridge in lw_public_accounts_login(): admin password check, site access (global_admin or local_admin site member), hash sync and member session.
v1.0.472026-08-08 06:52:34Local member accounts on the public siteSites without a CentreDeService portal can offer registration, sign-in, forgot password and a member area on the public site, with tokens for ZIP templates and CMS shell pages.
For users
- Register at /register/ with captcha and password confirmation.
- Sign in at /login/, recover at /forgot-password/, reset via email link.
- “My account” when signed in; {{​​​​account_strip}} banner in the header.

For administrators
- Settings → Member accounts: CMS shells and “Generate system pages”.
- Menu editor: Add member (Sign in, Forgot password, Register, My account) when CDS is off.
- ZIP tokens: {{​​​​account_login}}, {{​​​​account_register}}, {{​​​​account_panel}}, {{​​​​account_forgot}}, {{​​​​account_reset}} and related URLs.

Why
- Let standalone ludiWARE sites (no CDS) offer visitor accounts for comments, gated content or future personalization.

Technical notes
- lw_site_members table, session CSRF, registration captcha separate from contact, try_serve routes, public_render apply_tokens.
v1.0.462026-08-07 12:59:32Contact captcha: fix valid answers rejectedWhen a page or template has multiple contact forms, the same security question is shown everywhere and a correct answer is accepted.
For users
- The “What is X + Y?” captcha is the same on all contact forms on a page.
- A correct answer is no longer rejected with “Incorrect security check.”

Why
- Each form could get a different question while the session stores only one expected answer (content and template finalized separately).

Technical notes
- lw_contact_captcha_issue() reuses a valid session challenge; contact finalize runs once on the full HTML (public_render.php).
v1.0.452026-08-07 12:15:48Blog tokens: latest posts (footer / sidebar)Use {{​​​​blog-latest-title-1}}, {{​​​​blog-latest-image-1}}, {{​​​​blog-latest-excerpt-1}}, etc. (up to 10) in a template or page to show the most recent posts.
For users
- {{​​​​blog-latest-title-N}}: title (N=1 = newest, 2 = second, … up to 10)
- {{​​​​blog-latest-image-N}}: featured image URL
- {{​​​​blog-latest-excerpt-N}}: excerpt from post body
- {{​​​​blog-latest-date-N}}: short date (e.g. April 15, 2020)
- {{​​​​blog-latest-date-long-N}}: long formatted date
- {{​​​​blog-latest-url-N}}: link to the post
- Ideal for a “Blog” block in the footer or sidebar of an imported ZIP theme.

Why
- Customize the footer without manually copying post titles and images.

Technical notes
- lw_blog_apply_latest_tokens() in blog.php, invoked from lw_blog_apply_tokens() on templates and pages.
v1.0.442026-08-07 12:10:34Theme contact: error messages and Subject fieldZIP theme contact forms again show the actual error message (captcha, missing fields, etc.) and the theme Subject field is supported.
For users
- After a failed send, the specific message appears (e.g. wrong captcha) instead of the generic “Could not send your message.”
- Theme Subject fields (e.g. msg_subject, placeholder or label “Subject”) are stored and included in notification email.
- Fields without a name attribute but with placeholder/label (Your name, Your email…) are detected on import and render.

Why
- lw_contact_form_html() cleared the session flash before theme forms could display it.
- Some themes name the subject field differently than subject.

Technical notes
- public_render.php: lw_contact_form_html() only when {{​​​​contact_form}} is present.
- contact_forms.php: msg_subject alias, placeholder/label detection, name/email fallbacks.
v1.0.432026-08-07 12:04:45Fix HTTP 500 on ZIP theme contact pagesImported “Contact us” pages no longer crash when the Send button sits inside the theme grid (Bootstrap, etc.).
For users
- Custom contact pages from imported themes render again with captcha and Messages inbox delivery.
- Before the fix, some layouts (e.g. Bootstrap grid forms) returned HTTP 500.

Why
- When wiring the theme form, the captcha slot was inserted at the wrong DOM level if the submit control was not a direct child of <form>.

Technical notes
- contact_forms.php: lw_contact_wire_form_element() inserts the captcha slot via the submit button’s immediate parent instead of form->insertBefore() on a nested node.
v1.0.422026-08-07 09:41:46Customizable CDS shop pages (shells and tokens)Like the blog, you can pick CMS pages as shells for the shop, categories, product pages, cart and orders, then place granular tokens (title, price, image, list, etc.).
For users
- In Site settings → CentreDeService.NET, “Shop shell pages”, map a CMS page to each screen type (/boutique/, category, product, cart, order).
- Without a shell, the default CDS render is unchanged.
- On a product shell: {{​​​​cds_product_title}}, {{​​​​cds_product_image}}, {{​​​​cds_product_price}}, {{​​​​cds_product_desc}}, {{​​​​cds_product_add_cart}}, or {{​​​​cds_product}} for the full card.
- On list / category: {{​​​​cds_shop_list}} (full block), or {{​​​​cds_shop_categories}}, {{​​​​cds_shop_products}}, {{​​​​cds_shop_pager}}, {{​​​​cds_category_title}}.
- Cart / order: {{​​​​cds_cart}}, {{​​​​cds_order}}, {{​​​​cds_cart_count}}.

Why
- Let the shop layout match the site theme, following the blog token pattern.

Technical notes
- Shells: cds_shop_*_page_uid; lw_cds_resolve_shell_page in lw_cds_try_serve.
- Tokens: lw_cds_apply_shop_field_tokens + context in lw_cds_apply_tokens.
v1.0.412026-08-07 09:03:11ZIP theme contact forms wired to the CMSContact forms already present in an imported theme can send messages through the lw-admin contact engine without replacing the theme design. Detection is automatic on import; you can also force it with data-lw-contact="1".
For users
- A theme contact form (classes / mailto / name-email-message fields) is wired to the Messages inbox and notification email.
- The form’s look (theme HTML/CSS) is preserved.
- Manual marker: data-lw-contact="1" forces binding; data-lw-contact="0" excludes it.
- Captcha and success/error messages work like {{​​​​contact_form}}.

Why
- Avoid replacing a polished theme form with the generic {{​​​​contact_form}} markup.

Technical notes
- lw_contact_wire_form_html (import); lw_contact_finalize_bound_forms (render); field aliases in lw_contact_submit.
v1.0.40 Package2026-08-06 13:07:30ludiWARE 1.0.40 — installation packageFull public distribution (ZIP + tar.gz) with installer. Includes recent work: blog (tokens, category URLs, subcategories), CMS 404 page, global media library, menus / ZIP import, and display fixes.
For users
- Downloadable package to install or update ludiWARE.
- Archives: ludiware-1.0.40.tar.gz and ludiware-1.0.40.zip
- Repo: https://repo.ludiware.com/releases/1.0.40/
- Includes /install/ wizard (database, schema, admin account)

Notable since last distribution
- Blog: author / long date / time / comments / categories tokens; /blogue/category/subcategory/slug URLs; admin subcategories; French comment agreement
- Designated CMS 404 page + badge; ZIP import (chrome, mega-menus, 404 detect)
- Global media library and folders; active menus; header dedupe

Why
- Ship an installable package aligned with the current CMS version.

Technical notes
- OSS export (no secrets, no factory api/admin); VersionLog FileName points to the public tar.gz.

Télécharger le package

v1.0.392026-08-06 13:01:02Singular “commentaire” for 0 or 1 commentIn the French blog post list, “0 commentaire” and “1 commentaire” (no trailing s) are shown; the plural starts at 2.
For users
- Post card meta: correct French agreement for commentaire (singular for 0/1).

Why
- “0 commentaires” was incorrect in French.

Technical notes
- lw_blog_format_comments_count: singular when count <= 1 (FR).
v1.0.382026-08-06 13:00:31Easier blog subcategories in adminIn lw-admin, each category has a button to add a subcategory. The Parent category field is more prominent, with a tree-style list.
For users
- Categories list: diagram icon creates a subcategory already linked to the right parent.
- Form: parent field first, help about /blogue/parent/child/… URLs.
- “Subcategory” badge and Parent column in the table.

Why
- Hierarchy already existed in the database but was too easy to miss in the UI.

Technical notes
- blogcats.php (?new=1&parent=uid); blog.cat_* i18n keys; category cache bust.
v1.0.372026-08-06 12:51:12Blog URLs with nested categoriesPosts are now available at /blogue/category/subcategory/post-slug. Old /blogue/slug addresses redirect to the new URL automatically.
For users
- Post URL: /blogue/{category}/{subcategory}/{slug} from the category tree.
- No category: /blogue/{slug} as before.
- Category lists: /blogue/{category}/{subcategory} (legacy /blogue/categorie/… redirects).
- List links, comments, sitemap and admin use the new structure.

Why
- Mirror the category tree in the URL for clearer SEO and navigation.

Technical notes
- lw_blog_post_url / lw_blog_post_path_extra; path resolution in lw_blog_try_serve; 301 redirects.
v1.0.362026-08-06 12:48:37New blog tokens (author, date, comments…)Article templates can show the comment count, author, a long date, publish time, and the categories list. An Author field was added when editing posts.
For users
- New tokens: {{​​​​blog_comments_count}} (number only), {{​​​​blog_author}}, {{​​​​blog_date_long}} (e.g. Thursday, September 3, 2024), {{​​​​blog_time}} (HH:MM), {{​​​​blog_categories}} (published categories list).
- {{​​​​blog_date}} stays YYYY-MM-DD.
- “Author” field on create/edit, used by {{​​​​blog_author}}.

Why
- Richer article layouts without hard-coded HTML.

Technical notes
- author_name column; lw_blog_format_date_long / lw_blog_render_categories_token_list helpers; tokens documented in templates.php.
v1.0.352026-08-06 11:32:25CMS 404 page: fixed display + badgeThe page set as 404 now renders correctly (including on draft sites / preview). The pages list shows a “404” badge like the home badge. ZIP imports auto-detect 404 error pages.
For users
- When you check “Use as 404 page”, unknown URLs show that themed page instead of the generic dark 404.
- This also works in preview and while the site is still a draft.
- Pages list: orange “404” badge next to status, like the Home badge.
- New ZIP imports: a page named 404 / not-found is assigned automatically.

Why
- 404 page rendering ignored preview mode and rejected draft sites (“Site not published”), falling back to the generic page.

Technical notes
- lw_public_site_404(..., $preview); force preview render when site is draft; pages.badge_404; auto page_404_page_uid on ZIP import.
v1.0.342026-08-06 11:26:54ZIP import: no duplicate header in page contentWhen importing a template, the header (and similar wrappers) is removed from page content once it lives in the global header. Already-imported sites are cleaned on view.
For users
- Imported pages no longer keep a copy of the menu/header in their content when global chrome is active.
- Templates without a <header> tag (e.g. #header / .header-area) are supported too.

Why
- Stripping was too strict (majority vote, non-semantic wrappers ignored), leaving leftovers in page HTML.

Technical notes
- Structural detection + normalized affix (ignore active); broader DOM strip/dedupe; public render cleanup.
v1.0.332026-08-06 11:16:07Menu: current item highlighted correctlyOn sites (including imported templates), the active menu item follows the page being viewed instead of staying stuck on Home.
For users
- Visiting About (or another page) highlights that item, not Home.
- Parents of an active submenu item stay highlighted too.

Why
- Import copied the homepage’s active class into the CMS menu and never recalculated it from the URL.

Technical notes
- Menu render strips imported active/current classes, marks by page_uid or current path, aria-current=page.
v1.0.322026-08-06 11:00:39Fix media “New folder” fieldChoosing “New folder” in the media library correctly shows the name field again, including after in-app navigation.
For users
- The text field under “New folder” appears reliably when selected.

Why
- The script did not rebind after app-shell fragment navigation.

Technical notes
- Event delegation + re-init on lw:fragment-loaded (lw-media-folder.js v2).
v1.0.312026-08-06 10:50:19Global media library and foldersUpload shared images (logos, etc.) once under Library → Global media and reuse them on every site. Folder selection on upload lists existing folders or “New folder”.
For users
- New Library → Global media section for shared image upload and management.
- On a site media page, the Global tab lists those files read-only (copy URL); platform admins get a Manage link.
- On upload/edit, Folder is a dropdown (none / existing / New folder + text field).

Why
- Avoid re-uploading the same logo on every site.
- Make folder tagging clearer without retyping names.

Technical notes
- lw_media.site_id NULL = global; files under uploads/global/; single reference (no per-site copy).
v1.0.302026-08-06 09:59:30ZIP import: mega-menus preservedWhen importing a ZIP template, rich mega-menu panels (columns, images, CTAs) and Bootstrap dropdown attributes are kept and rendered correctly.
For users
- Templates with mega-menus (full-width panels, grids, images) keep their look after import.
- Bootstrap dropdowns keep their options (data-bs-toggle, etc.).
- Items with a mega panel show an HTML field in Menus for edits (until the mega-menu extension).

Why
- Import only read nested <ul> lists; <div class="dropdown-menu"> panels were dropped when tokenizing {{​​​​menu:…}}.

Technical notes
- New item fields: panel_html, link_attrs, label_html; harvest detection; render anchor+panel; URL rewrite on persist.
v1.0.292026-08-06 09:42:25Fix header/footer save (duplication)Saving header and footer on a ZIP template no longer duplicates the footer under the copyright bar.
For users
- Saving “Header & footer” no longer leaves a second unstyled footer.
- Sites already affected are fixed on view (and permanently when you save chrome again).

Why
- The parser used the first inner </div> of the footer as the block end, then appended the remainder after the footer.

Technical notes
- after_footer extracted via DOM; only script/style/link/noscript kept; public render repair.
token: version history on the public site - Contact form: name and email prefilled when signed in - Bootstrap Icons + admin icon picker - MarketPlace plugins: FAQ, Testimonials, Gallery, Forms, Booking, Classifieds, Forums Republished plugins (MarketPlace) - Forums 1.0.16 - Classifieds 1.0.15 Technical notes - OSS export without factory secrets; VersionLog FileName → public tar.gz.

Télécharger le package

v1.0.612026-08-08 11:25:48Version history: tokens display normallyExamples like {{​account_login}} in version history show as readable text, without visible HTML entities ({).
For visitors / administrators
- History page and Settings → Versions: cited tokens appear as {{​account_login}}, not as {{​account_login}}.

Why
- Escaping braces as HTML entities then running htmlspecialchars() double-encoded and showed raw codes on screen.

Technical
- Zero-width space neutralization only (no { entities) in lw_versionlog_format_display_text() and lw_versionlog_shield_public_html().
v1.0.602026-08-08 11:24:31Contact form: name and email prefilled when signed inOn the contact form, Name and Email fields are filled automatically when the visitor is already signed in (local account, lw-admin, or CDS portal).
For users
- {{​contact_form}} and theme ZIP contact forms: Name and Email prefilled when signed in.
- Fields already set in the template are not overwritten.

Why
- Avoid re-entering identity on every contact message.

Sources
- CDS portal (SSO session): full name + contact email.
- Public member account or lw-admin cookie: display_name + lw_users email.

Technical
- lw_contact_prefill_identity(), lw_contact_apply_prefill_to_form(), lw_contact_form_html().
v1.0.592026-08-08 11:20:46

Platform version history (newest first).

v1.2.12026-08-09 16:47:35Extensible My account and classifieds lightboxPlugins can add My account tabs (e.g. My listings). Public pages now inject the classifieds gallery script at the end of the HTML.
For users
- My account: extensions can register new tabs via the CMS (?tab=… URLs).
- Classifieds 1.2.12: “My listings” tab with edit, delete, and mark as sold.
- Ad photo lightbox: works on CMS token pages too (not only /classifieds/… routes).

Why this change
- Keep listing management in My account alongside profile settings.
- Fix the gallery when ad HTML is rendered inside a site page without the plugin front router.

Technical notes
- CMS filters: public_account_tabs, public_account_tab_panels, public_account_post_actions, public_accounts_handle_post, public_page_html.
- Classifieds plugin: sold status, owner actions, defer gallery JS v4.
v1.2.0 Package2026-08-09 15:29:10ludiWARE 1.2.0 — public profiles and member identityMinor release 1.2.0: full install packages (ZIP + tar.gz), public member profiles, clickable names site-wide, unified activity history on profiles, and republished Forums / Classifieds plugins.
For users
- Download: ludiware-1.2.0.tar.gz + ludiware-1.2.0.zip
- Repo: https://repo.ludiware.com/releases/1.2.0/
- Includes /install/ wizard

CMS highlights (since 1.1.x)
- Public member profile: /membre/{uid} (avatar, name, member since)
- Member names link to profiles (blog, account strip, extensions)
- Activity history on profile: blog comments, forum topics/replies, classified ads and comments
- `public_member_profile_activity` filter for extensions

Republished MarketPlace plugins
- Forums 1.0.18 (profile links + forum activity)
- Classifieds 1.2.9 (linked comments, listing activity)

Technical notes
- OSS export without factory secrets
- VersionLog FileName → public tar.gz on repo.ludiware.com

Télécharger le package

v1.1.142026-08-09 15:26:40Activity history on public profileA member’s profile page now shows a unified timeline of their public contributions: blog comments, forum topics and replies, classified ads and ad comments.
For visitors
- “Public activity” section under the profile header (/membre/{uid}).
- Each row: date, action type, clickable title to the content, short excerpt when available.
- Newest first (up to 60 items), mixing blog, forums and active plugins.

For developers / extensions
- New `public_member_profile_activity` filter — return items `{at, kind, label, title, url, excerpt?}`.
- Helpers: `lw_public_accounts_collect_member_activity()`, `lw_public_accounts_render_member_activity_html()`, `lw_public_accounts_member_activity_item()`.
- Blog: `lw_blog_member_public_activity()` (published comments).
- Plugins register sources via the filter (Forums, Classifieds).

Why
- One consolidated view of a member’s public presence instead of isolated per-plugin sections.
v1.1.132026-08-09 15:23:12Member names link to public profileWherever a registered member appears (blog comments, account strip, etc.), their name now links to their public profile page when that profile is visible.
For visitors
- Click a local active member’s name → /membre/{uid} (or /member/{uid} in English).
- Account strip “Signed in as …”: your display name links to your profile.
- Blog post comments: authors tied to a local member account get a profile link.
- Guests, CDS portal users, or authors without a member account: plain text name (unchanged).

For developers / extensions
- Central helpers: `lw_public_accounts_author_context_from_row()`, `lw_public_accounts_resolve_content_author()`, `lw_public_accounts_render_author_name_html()`.
- Shared CSS class `lw-member-profile-link` for profile links.

Why
- Consistent public member identity across the site (blog, forums, classifieds, etc.) following public profiles in 1.1.12.
v1.1.122026-08-09 15:17:27Public profile for registered membersEach locally registered site member gets a public profile page with avatar and display name. Extensions can append content (e.g. published classifieds).
For visitors
- Public URL: /membre/{uid} (FR) or /member/{uid} (EN) — avatar, display name, member since date.
- Profiles are shown only for active local member accounts, not admins or CentreDeService portal users.

For developers / extensions
- New `public_member_profile_html` filter to extend the page (Classifieds plugin lists published ads).
- Helpers: `lw_public_accounts_public_profile_url()`, `lw_public_accounts_user_by_uid_public()`.

Why
- Let visitors see who published content and build a consistent public identity on the site.
v1.1.112026-08-09 14:33:21Standardized alerts for admin and pluginsNew unified alert system: success, error, warning, and info messages are shown consistently in lw-admin and on the public site. Plugins can contribute through dedicated hooks.
For users
- Admin confirmations and errors (e.g. “Listing deleted”, “Settings saved”) now appear at the top of the page in a consistent banner.
- On the public site, plugins can show user messages with the same visual style.

Why
- Each module and plugin handled its own alerts (different variables, query strings, custom CSS), causing duplication and inconsistency.

Technical notes
- New module lw-admin/functions/flash.php: lw_flash_add(), lw_flash_redirect(), lw_flash_render_html(), lw_public_flash_html().
- admin_flash and public_flash hooks for extensions.
- Backward compatible with $lwFlash and $lwPageFlashError.
- Shared lw-flash.css for admin/public.
- Classifieds plugin migrated as an example (v1.2.2).
v1.1.102026-08-08 18:52:20Portable site-to-site configurationconfig.php no longer holds secrets or factory domain settings: database, emails, and environment overrides live in config.local.php; hostname and defaults are inferred automatically.
For users
- Copy the CMS between sites without editing config.php: only config.local.php (or the /install/ wizard) needs to match the new host.
- Cookies and site name follow the real domain when HTTPpath / COOKIEpath are omitted.

Why
- config.php mixed MySQL credentials, the ludiware.com domain, and factory emails, making every client deploy error-prone.

Technical notes
- lw_config_detect_http_host() + lw_config_apply_runtime_defaults() after config.local.php.
- MySQL connects only when DBhost / DBname / DBusername are set.
- Updated config.local.example.php and installer (domain optional).
v1.1.92026-08-08 17:58:54Modal sign-in fix (POST fields + SQL)Sign-in from the modal now reliably sends email and password (POST to the current page, fields read explicitly) and works on hosts without mysqlnd.
For users
- The login/register modal posts to the page you are on (not only /sign-in/), avoiding silent failures.
- If the account has no password (Google/Facebook admin sign-in), a clear message appears instead of “invalid email or password”.

Why
- On some themes, fields did not always have a name attribute when FormData ran; on some hosts, user SQL reads failed without mysqlnd.

Technical notes
- lw-account-forms.js v4: explicit buildFormData; action = current page in modals.
- lw_public_accounts_stmt_fetch_one_assoc(); modal forms: post_url injected at render.
v1.1.82026-08-08 17:51:46Admin recognition on public site + cookie domainAn administrator signed into lw-admin is recognized again on the public site (My account header). Cookies align with the site’s actual domain (e.g. dormezcheznous.com).
For users
- If you are signed into lw-admin on the same domain as the public site, the header shows “My account” without using the modal again.
- After signing in via the modal, the public session persists.
- Check config.local.php: COOKIEpath must match the site domain (not ludiware.com if the site uses another hostname).

Why
- Admin cookies were sometimes set for ludiware.com while the site runs on a custom domain; the public site never received them. Modal sign-in could also fail when mismatched admin cookies interfered.

Technical notes
- lw_cookie_domain() uses current HTTP host when it differs from COOKIEpath.
- lw_public_accounts_auth_from_cookies() + member session sync.
- Auth bootstrap on public index.php.
v1.1.72026-08-08 17:31:50Conditional account header (snippets / tokens)Show “Sign in” or “My account” in the header based on session state, using an HTML snippet and {{​​​​account_if_guest}} / {{​​​​account_if_logged_in}} tokens.
For users
- In an HTML snippet (or layout): wrap the Sign in button with {{​​​​account_if_guest}}…{{​​​​/account_if_guest}} and My account with {{​​​​account_if_logged_in}}…{{​​​​/account_if_logged_in}}.
- Useful tokens: {{​​​​account_account_url}}, {{​​​​account_user_name}}, {{​​​​account_logout_url}}, {{​​​​account_logged_in}} (1 or empty).
- Put {{​​​​snippet:your_key}} in the layout header.
- Built-in alternative: {{​​​​account_strip}} (lw-admin banner).
- PHP snippets: $lw_db variable + lw_public_accounts_viewer().

Why
- Imported themes like DormezChezNous need a custom Bootstrap/modal button, not the generic banner.

Technical notes
- lw_public_accounts_apply_conditional_blocks() in apply_tokens; $lw_db exposed to PHP snippets.
v1.1.62026-08-08 17:25:08Account modal AJAX fix (Homelengo themes)Sign-in from a modal did not react on click: the account script now intercepts the click before theme scripts, shows errors (removes d-none), and shows loading state on the button.
For users
- The “Sign in” button in the modal works again: “…” while sending, visible red error on failure, page reload on success.
- No HTML change needed if data-lw-account and data-lw-account-error are already set.

Why
- Imported themes (Homelengo / DormezChezNous) registered listeners that blocked submit before our script; errors also stayed hidden behind Bootstrap d-none.

Technical notes
- lw-account-forms.js v3: capture click + submit, loaded last before </body>.
- Automatically removes d-none on data-lw-account-error.
v1.1.52026-08-08 17:13:29AJAX sign-in and register (modals)Account forms inside a modal (Bootstrap or similar) can submit without a full page reload: errors show in the modal, and the page refreshes after a successful sign-in.
For users
- If your login/register form is inside a modal (.modal or role="dialog"), submission uses AJAX automatically — no redirect to /sign-in/ that breaks the flow.
- Add an error slot: <div data-lw-account-error></div> in the modal.
- Force or disable: data-lw-account-ajax="1" or "0" on the <form>.
- On success: default is page reload (account menu updates); data-lw-account-on-success="redirect" to go to My account.
- Register captcha refreshes automatically after a failed attempt.

Why
- Sites like DormezChezNous open login/register in popups; a classic POST reloaded the whole page.

Technical notes
- lw-account-forms.js injected when data-lw-account is present.
- JSON responses server-side (lw_public_accounts_handle_post); index.php hook for POST from any page.
v1.1.42026-08-08 16:54:04Custom account forms (data-lw-account)Use your own HTML sign-in and register forms in the theme: the engine wires them automatically and exposes error messages via tokens or dedicated slots.
For users
- Form marker: data-lw-account="login" or "register" (also forgot, reset, profile, security).
- Fields: data-lw-account-field="email|password|…" or auto-detect via id/name/placeholder (like contact).
- Errors: {{​​​​account_error_text}} in your HTML, or <div data-lw-account-error></div>.
- Success: {{​​​​account_success_text}} or data-lw-account-success.
- Replace {{​​​​account_login}} with your markup on the /connexion/ shell page if you do not want the default lw-admin form.
- Register: <div class="lw-account-captcha-slot"></div> for captcha.
- Optional OAuth: <div data-lw-account-oauth></div>.

Why
- Imported themes like DormezChezNous keep their Bootstrap design without duplicating account logic.

Technical notes
- account_forms.php (same pattern as data-lw-contact).
- Injects CSRF + lw_account_action; POST action targets /connexion/, /register/, etc.
v1.1.32026-08-08 12:47:55HTML editors with syntax highlighting and tabsAll admin HTML and code fields now have syntax highlighting and Tab indentation (4 spaces), including TinyMCE’s source code view.
For users
- Raw HTML fields (header, footer, snippets, templates, custom CSS, etc.): line numbers, highlighting, Tab to indent.
- TinyMCE rich editor: the source code button opens the same highlighted experience.
- Imported themes: direct HTML editing with highlighting.

Why
- Easier markup editing without an external IDE.
- Tab inserts consistent indentation; Shift+Tab outdents.

Technical notes
- lw-code-editor.js module (CodeMirror 5 via CDN).
- html, css, and php modes per field.
- App-shell navigation compatible (reinit after page change).
v1.1.22026-08-08 11:37:45In-app CMS update and footer alertRemote installations show a visible admin footer warning when a newer package is available, and can install the update from Settings → Versions without manually re-uploading files.
For users
- Admin footer: “Update available (vX.Y.Z)” badge when a newer VersionLog package is published on repo.ludiware.com.
- Settings → Versions: banner with “Update now” (automatic download and deploy).
- Preserved local files: config.local.php, config.php (only the Version line is updated), uploads/, storage/, installed extensions.

Why
- Avoid manual FTP/SFTP updates on every hosted site.
- Surface an outdated version (e.g. 1.0.53 vs 1.1.x) without digging through history.

Technical notes
- lw_cms_update_apply(): downloads ZIP/tar.gz from repo.ludiware.com, extracts and copies core files.
- lw_versionlog_check_update() unchanged (30 min cache).
- Settings sidebar badge + chrome alert for managers.
v1.1.12026-08-08 11:30:24Version history: readable tokens and bracesVersionLog entries no longer show raw HTML codes ({): tokens like {{​​​​account_login}} display normally.
For visitors
- History page: CMS token examples show as plain text (visible braces), without double-encoded HTML entities.

Why
- Some VersionLog entries mentioned HTML entities ({) in their text; htmlspecialchars() displayed them literally on screen.

Technical
- lw_versionlog_prepare_display_source(): decode brace entities before zero-width neutralization and lw_e().
v1.1.0 Package2026-08-08 11:28:14ludiWARE 1.1.0 — public distributionMinor release 1.1.0: full install package (ZIP + tar.gz), public OAuth accounts, public version history, contact form prefill, and updated MarketPlace plugins.
For users
- Download: ludiware-1.1.0.tar.gz + ludiware-1.1.0.zip
- Repo: https://repo.ludiware.com/releases/1.1.0/
- Includes /install/ wizard (database, schema, admin account)

Since the 1.0.40 distribution
- Local member accounts: sign-up, login, forgot password, My account (profile / security tabs)
- Google and Facebook OAuth on the public site
- Public header recognizes lw-admin session and OAuth members
- {{​​​​versionlog}} token: version history on the public site
- Contact form: name and email prefilled when signed in
- Bootstrap Icons + admin icon picker
- MarketPlace plugins: FAQ, Testimonials, Gallery, Forms, Booking, Classifieds, Forums

Republished plugins (MarketPlace)
- Forums 1.0.16
- Classifieds 1.0.15

Technical notes
- OSS export without factory secrets; VersionLog FileName → public tar.gz.

Télécharger le package

v1.0.612026-08-08 11:25:48Version history: tokens display normallyExamples like {{​​​​account_login}} in version history show as readable text, without visible HTML entities ({).
For visitors / administrators
- History page and Settings → Versions: cited tokens appear as {{​​​​account_login}}, not as {{​​account_login}}.

Why
- Escaping braces as HTML entities then running htmlspecialchars() double-encoded and showed raw codes on screen.

Technical
- Zero-width space neutralization only (no { entities) in lw_versionlog_format_display_text() and lw_versionlog_shield_public_html().
v1.0.602026-08-08 11:24:31Contact form: name and email prefilled when signed inOn the contact form, Name and Email fields are filled automatically when the visitor is already signed in (local account, lw-admin, or CDS portal).
For users
- {{​​​​contact_form}} and theme ZIP contact forms: Name and Email prefilled when signed in.
- Fields already set in the template are not overwritten.

Why
- Avoid re-entering identity on every contact message.

Sources
- CDS portal (SSO session): full name + contact email.
- Public member account or lw-admin cookie: display_name + lw_users email.

Technical
- lw_contact_prefill_identity(), lw_contact_apply_prefill_to_form(), lw_contact_form_html().
v1.0.592026-08-08 11:20:46{{​​​​versionlog}} token works on the public siteThe {{​​​​versionlog}} token is now recognized on the public site: the History page shows the version list instead of the raw token text.
For visitors
- History page: {{​​​​versionlog}} content is replaced by the version list (styles and safe text).

Why
- The VersionLog module was only loaded in lw-admin; on index.php (public front), lw_versionlog_prepare_public_html() was missing and the token stayed literal.

Technical
- require versionlog.php in www/index.php before public_render.php.
v1.0.582026-08-08 11:07:13Public version history: CMS tokens shown as plain textOn the ludiware.com History page, mentions like {{​​​​account_login}}, {{​​​​menu:main}}, etc. in VersionLog entries display as text instead of injecting forms or menus.
For visitors
- History page (/historique/): version title, description and details show cited tokens as documentation, with no login form or menu injected mid-sentence.

Why
- VersionLog content is rendered via a PHP snippet then processed by the CMS token engine; example {{​​​​account_login}} was executed as a real token.

Technical
- Native {{​​​​versionlog}} / {{​​​​versionlog_list}} token; .lw-vl-* blocks shielded before the token pipeline; HTML entities for {{​​​​ and }} on display.
v1.0.572026-08-08 10:58:52Version history: CMS tokens shown as plain textMentions like {{​​​​account_login}}, {{​​​​menu:main}}, etc. in VersionLog technical details are no longer interpreted as CMS tokens.
For administrators
- Settings → Version history: title, description and full details show tokens literally (documentation), with no forms or injected content.

Why
- VersionLog entries often cite tokens as examples in “Technical detail”; the token engine must not execute them on display.

Technical
- Neutralize {{​​​​ → {{​​​​ + zero-width space on API output and lw-admin client; HTML-escaped display.
v1.0.562026-08-08 10:54:16Public header: lw-admin session recognitionWhen signed into lw-admin, you also appear as a member on the public site (header, My account), consistent with blog comments.
For visitors / administrators
- lw-admin cookies → {{​​​​account_strip}} shows your name and “My account”.
- /account/ works without visiting /login/ again.
- /login/ and /register/ redirect to My account when already recognized.

Identity priority (unchanged for blog when a Facebook session is active)
1. Public member session (login / OAuth)
2. lw-admin cookie

Public sign-out clears the member session only; if lw-admin remains, you stay signed in.
v1.0.552026-08-08 10:38:20Blog and forums: public member identity firstOn the public site, the member session (login / Facebook / Google) now takes precedence over lw-admin cookies for blog comments.
Fixed issue
- Header “Signed in as…” (member session) and blog “Commenting as…” (admin cookies) could show two different people when logged into lw-admin and Facebook on the public site.

Behavior
- Priority: CDS portal → public member (session) → admin staff (lw-admin cookie).
- Blog login hint links to /login/ when local accounts are active (no CDS).

Note
- If Facebook created a second lw_users account (different email from admin), that is expected: two separate profiles. Merge manually or delete the duplicate in Users.
v1.0.542026-08-08 10:11:29OAuth — stable redirect URLThe Google/Facebook callback URL in site settings now uses the site’s public domain (e.g. ludiware.com), not the admin host.
For administrators
- Settings → Member accounts: the “authorized redirect” URL matches the site’s public domain.
- Help note for adding the URI in Facebook Login → Valid OAuth Redirect URIs.

Why
- When opened from the admin panel (different subdomain), the generated URL could differ from the one used on the public site.
v1.0.532026-08-08 10:03:23Google and Facebook sign-in for membersVisitors can sign in or register with Google or Facebook on login and register pages when local accounts are used (no CentreDeService portal). A local member profile is created automatically when needed.
For visitors
- “Sign in with Google” and “Sign in with Facebook” on /login/ and /register/ (FR: /connexion/, /inscription/).
- If the email is not registered yet, a member account is created and the session starts.
- If an account already exists with the same email, the OAuth profile is linked to it.

For administrators
- Site settings → Member accounts: enable providers, OAuth credentials, and redirect URLs to paste into Google Cloud / Facebook Developer.
- Automatically disabled when the CentreDeService portal handles authentication.

Technical
- lw_users google_id / facebook_id columns, oauth_accounts.php module, /oauth/{provider}/callback/ routes.
v1.0.522026-08-08 08:35:18Icon picker — full catalogThe icon picker now shows useful favorites first, then all Bootstrap icons (~1,600) via search.
For administrators
- On open: a grid of favorites (home, commerce, transport, etc.).
- Search: filters the full set of ~1,683 installed Bootstrap Icons.
- Result count and message when the list is truncated.

Fix
- The list was previously capped at 120 icons in alphabetical order (123, alarm…), which felt incomplete.
v1.0.512026-08-08 08:29:09Bootstrap Icons and icon pickerBootstrap Icons now render reliably across the admin with complete font files. A reusable icon picker is available for forms (search, grid, preview).
For administrators
- Bootstrap Icons font files (woff/woff2) installed so existing `bi-*` icons in lw-admin display correctly.
- New reusable icon picker component (`lw_icon_picker_field`) for any admin form.

Usage
- Button with icon preview, name search, clickable grid, and a “No icon” option.
- PHP helpers `lw_bootstrap_icon_names()` and `lw_bootstrap_icon_class()`.

Technical
- Files: `functions/icon_picker.php`, `js/lw-icon-picker.js`, styles in `lw-admin.css`.
v1.0.502026-08-08 07:27:10My account — profile and security tabsThe My account page has two tabs: My information (first name, last name, avatar) and Access & security (email, password). New tokens for ZIP templates.
For users
- My information tab: first name, last name, avatar upload.
- Access & security tab: change email and/or password (current password required).

ZIP tokens
- {{​​​​account_panel}}: full panel with tabs.
- {{​​​​account_tabs}}, {{​​​​account_profile}}, {{​​​​account_security}}: custom layout.
- {{​​​​account_avatar}}, {{​​​​account_avatar_url}}, {{​​​​account_first_name}}, {{​​​​account_last_name}}, {{​​​​account_email}}.
- {{​​​​account_profile_url}}, {{​​​​account_security_url}}: direct links to each tab.

Technical notes
- lw_users.avatar_path column, files in uploads/users/, public session synced after updates.
v1.0.492026-08-08 07:17:18Public accounts unified in lw_usersRegistration, sign-in and forgot password on the public site now use the lw_users table (same as lw-admin). Only accounts with admin access can open lw-admin.
For users
- Same email and password everywhere: admin or visitor registered at /register/.
- Accounts created on the public site have the user role and cannot access lw-admin.
- Administrators can also sign in at /login/ with their usual credentials.

Why
- Removes the mistaken dual lw_site_members / lw_users system.

Technical notes
- public_accounts.php: auth, registration and reset on lw_users; per-site public session.
- auth.php unchanged: can_access_admin required for lw-admin.
- Obsolete lw_site_members table can be dropped in the database (DROP TABLE).
v1.0.482026-08-08 07:11:33Public sign-in with an administrator accountSite administrators can sign in on the public site (/login/) using the same email and password as lw-admin, without a separate registration.
For users
- At /login/, a global administrator or a user assigned to the site is accepted with lw-admin credentials.
- The first sign-in automatically creates the local member profile for that site; later sign-ins reuse it.

Why
- Before this fix, only accounts registered via /register/ (lw_site_members) were recognized; the first admin saw “Invalid email or password.”

Technical notes
- lw_users → lw_site_members bridge in lw_public_accounts_login(): admin password check, site access (global_admin or local_admin site member), hash sync and member session.
v1.0.472026-08-08 06:52:34Local member accounts on the public siteSites without a CentreDeService portal can offer registration, sign-in, forgot password and a member area on the public site, with tokens for ZIP templates and CMS shell pages.
For users
- Register at /register/ with captcha and password confirmation.
- Sign in at /login/, recover at /forgot-password/, reset via email link.
- “My account” when signed in; {{​​​​account_strip}} banner in the header.

For administrators
- Settings → Member accounts: CMS shells and “Generate system pages”.
- Menu editor: Add member (Sign in, Forgot password, Register, My account) when CDS is off.
- ZIP tokens: {{​​​​account_login}}, {{​​​​account_register}}, {{​​​​account_panel}}, {{​​​​account_forgot}}, {{​​​​account_reset}} and related URLs.

Why
- Let standalone ludiWARE sites (no CDS) offer visitor accounts for comments, gated content or future personalization.

Technical notes
- lw_site_members table, session CSRF, registration captcha separate from contact, try_serve routes, public_render apply_tokens.
v1.0.462026-08-07 12:59:32Contact captcha: fix valid answers rejectedWhen a page or template has multiple contact forms, the same security question is shown everywhere and a correct answer is accepted.
For users
- The “What is X + Y?” captcha is the same on all contact forms on a page.
- A correct answer is no longer rejected with “Incorrect security check.”

Why
- Each form could get a different question while the session stores only one expected answer (content and template finalized separately).

Technical notes
- lw_contact_captcha_issue() reuses a valid session challenge; contact finalize runs once on the full HTML (public_render.php).
v1.0.452026-08-07 12:15:48Blog tokens: latest posts (footer / sidebar)Use {{​​​​blog-latest-title-1}}, {{​​​​blog-latest-image-1}}, {{​​​​blog-latest-excerpt-1}}, etc. (up to 10) in a template or page to show the most recent posts.
For users
- {{​​​​blog-latest-title-N}}: title (N=1 = newest, 2 = second, … up to 10)
- {{​​​​blog-latest-image-N}}: featured image URL
- {{​​​​blog-latest-excerpt-N}}: excerpt from post body
- {{​​​​blog-latest-date-N}}: short date (e.g. April 15, 2020)
- {{​​​​blog-latest-date-long-N}}: long formatted date
- {{​​​​blog-latest-url-N}}: link to the post
- Ideal for a “Blog” block in the footer or sidebar of an imported ZIP theme.

Why
- Customize the footer without manually copying post titles and images.

Technical notes
- lw_blog_apply_latest_tokens() in blog.php, invoked from lw_blog_apply_tokens() on templates and pages.
v1.0.442026-08-07 12:10:34Theme contact: error messages and Subject fieldZIP theme contact forms again show the actual error message (captcha, missing fields, etc.) and the theme Subject field is supported.
For users
- After a failed send, the specific message appears (e.g. wrong captcha) instead of the generic “Could not send your message.”
- Theme Subject fields (e.g. msg_subject, placeholder or label “Subject”) are stored and included in notification email.
- Fields without a name attribute but with placeholder/label (Your name, Your email…) are detected on import and render.

Why
- lw_contact_form_html() cleared the session flash before theme forms could display it.
- Some themes name the subject field differently than subject.

Technical notes
- public_render.php: lw_contact_form_html() only when {{​​​​contact_form}} is present.
- contact_forms.php: msg_subject alias, placeholder/label detection, name/email fallbacks.
v1.0.432026-08-07 12:04:45Fix HTTP 500 on ZIP theme contact pagesImported “Contact us” pages no longer crash when the Send button sits inside the theme grid (Bootstrap, etc.).
For users
- Custom contact pages from imported themes render again with captcha and Messages inbox delivery.
- Before the fix, some layouts (e.g. Bootstrap grid forms) returned HTTP 500.

Why
- When wiring the theme form, the captcha slot was inserted at the wrong DOM level if the submit control was not a direct child of <form>.

Technical notes
- contact_forms.php: lw_contact_wire_form_element() inserts the captcha slot via the submit button’s immediate parent instead of form->insertBefore() on a nested node.
v1.0.422026-08-07 09:41:46Customizable CDS shop pages (shells and tokens)Like the blog, you can pick CMS pages as shells for the shop, categories, product pages, cart and orders, then place granular tokens (title, price, image, list, etc.).
For users
- In Site settings → CentreDeService.NET, “Shop shell pages”, map a CMS page to each screen type (/boutique/, category, product, cart, order).
- Without a shell, the default CDS render is unchanged.
- On a product shell: {{​​​​cds_product_title}}, {{​​​​cds_product_image}}, {{​​​​cds_product_price}}, {{​​​​cds_product_desc}}, {{​​​​cds_product_add_cart}}, or {{​​​​cds_product}} for the full card.
- On list / category: {{​​​​cds_shop_list}} (full block), or {{​​​​cds_shop_categories}}, {{​​​​cds_shop_products}}, {{​​​​cds_shop_pager}}, {{​​​​cds_category_title}}.
- Cart / order: {{​​​​cds_cart}}, {{​​​​cds_order}}, {{​​​​cds_cart_count}}.

Why
- Let the shop layout match the site theme, following the blog token pattern.

Technical notes
- Shells: cds_shop_*_page_uid; lw_cds_resolve_shell_page in lw_cds_try_serve.
- Tokens: lw_cds_apply_shop_field_tokens + context in lw_cds_apply_tokens.
v1.0.412026-08-07 09:03:11ZIP theme contact forms wired to the CMSContact forms already present in an imported theme can send messages through the lw-admin contact engine without replacing the theme design. Detection is automatic on import; you can also force it with data-lw-contact="1".
For users
- A theme contact form (classes / mailto / name-email-message fields) is wired to the Messages inbox and notification email.
- The form’s look (theme HTML/CSS) is preserved.
- Manual marker: data-lw-contact="1" forces binding; data-lw-contact="0" excludes it.
- Captcha and success/error messages work like {{​​​​contact_form}}.

Why
- Avoid replacing a polished theme form with the generic {{​​​​contact_form}} markup.

Technical notes
- lw_contact_wire_form_html (import); lw_contact_finalize_bound_forms (render); field aliases in lw_contact_submit.
v1.0.40 Package2026-08-06 13:07:30ludiWARE 1.0.40 — installation packageFull public distribution (ZIP + tar.gz) with installer. Includes recent work: blog (tokens, category URLs, subcategories), CMS 404 page, global media library, menus / ZIP import, and display fixes.
For users
- Downloadable package to install or update ludiWARE.
- Archives: ludiware-1.0.40.tar.gz and ludiware-1.0.40.zip
- Repo: https://repo.ludiware.com/releases/1.0.40/
- Includes /install/ wizard (database, schema, admin account)

Notable since last distribution
- Blog: author / long date / time / comments / categories tokens; /blogue/category/subcategory/slug URLs; admin subcategories; French comment agreement
- Designated CMS 404 page + badge; ZIP import (chrome, mega-menus, 404 detect)
- Global media library and folders; active menus; header dedupe

Why
- Ship an installable package aligned with the current CMS version.

Technical notes
- OSS export (no secrets, no factory api/admin); VersionLog FileName points to the public tar.gz.

Télécharger le package

v1.0.392026-08-06 13:01:02Singular “commentaire” for 0 or 1 commentIn the French blog post list, “0 commentaire” and “1 commentaire” (no trailing s) are shown; the plural starts at 2.
For users
- Post card meta: correct French agreement for commentaire (singular for 0/1).

Why
- “0 commentaires” was incorrect in French.

Technical notes
- lw_blog_format_comments_count: singular when count <= 1 (FR).
v1.0.382026-08-06 13:00:31Easier blog subcategories in adminIn lw-admin, each category has a button to add a subcategory. The Parent category field is more prominent, with a tree-style list.
For users
- Categories list: diagram icon creates a subcategory already linked to the right parent.
- Form: parent field first, help about /blogue/parent/child/… URLs.
- “Subcategory” badge and Parent column in the table.

Why
- Hierarchy already existed in the database but was too easy to miss in the UI.

Technical notes
- blogcats.php (?new=1&parent=uid); blog.cat_* i18n keys; category cache bust.
v1.0.372026-08-06 12:51:12Blog URLs with nested categoriesPosts are now available at /blogue/category/subcategory/post-slug. Old /blogue/slug addresses redirect to the new URL automatically.
For users
- Post URL: /blogue/{category}/{subcategory}/{slug} from the category tree.
- No category: /blogue/{slug} as before.
- Category lists: /blogue/{category}/{subcategory} (legacy /blogue/categorie/… redirects).
- List links, comments, sitemap and admin use the new structure.

Why
- Mirror the category tree in the URL for clearer SEO and navigation.

Technical notes
- lw_blog_post_url / lw_blog_post_path_extra; path resolution in lw_blog_try_serve; 301 redirects.
v1.0.362026-08-06 12:48:37New blog tokens (author, date, comments…)Article templates can show the comment count, author, a long date, publish time, and the categories list. An Author field was added when editing posts.
For users
- New tokens: {{​​​​blog_comments_count}} (number only), {{​​​​blog_author}}, {{​​​​blog_date_long}} (e.g. Thursday, September 3, 2024), {{​​​​blog_time}} (HH:MM), {{​​​​blog_categories}} (published categories list).
- {{​​​​blog_date}} stays YYYY-MM-DD.
- “Author” field on create/edit, used by {{​​​​blog_author}}.

Why
- Richer article layouts without hard-coded HTML.

Technical notes
- author_name column; lw_blog_format_date_long / lw_blog_render_categories_token_list helpers; tokens documented in templates.php.
v1.0.352026-08-06 11:32:25CMS 404 page: fixed display + badgeThe page set as 404 now renders correctly (including on draft sites / preview). The pages list shows a “404” badge like the home badge. ZIP imports auto-detect 404 error pages.
For users
- When you check “Use as 404 page”, unknown URLs show that themed page instead of the generic dark 404.
- This also works in preview and while the site is still a draft.
- Pages list: orange “404” badge next to status, like the Home badge.
- New ZIP imports: a page named 404 / not-found is assigned automatically.

Why
- 404 page rendering ignored preview mode and rejected draft sites (“Site not published”), falling back to the generic page.

Technical notes
- lw_public_site_404(..., $preview); force preview render when site is draft; pages.badge_404; auto page_404_page_uid on ZIP import.
v1.0.342026-08-06 11:26:54ZIP import: no duplicate header in page contentWhen importing a template, the header (and similar wrappers) is removed from page content once it lives in the global header. Already-imported sites are cleaned on view.
For users
- Imported pages no longer keep a copy of the menu/header in their content when global chrome is active.
- Templates without a <header> tag (e.g. #header / .header-area) are supported too.

Why
- Stripping was too strict (majority vote, non-semantic wrappers ignored), leaving leftovers in page HTML.

Technical notes
- Structural detection + normalized affix (ignore active); broader DOM strip/dedupe; public render cleanup.
v1.0.332026-08-06 11:16:07Menu: current item highlighted correctlyOn sites (including imported templates), the active menu item follows the page being viewed instead of staying stuck on Home.
For users
- Visiting About (or another page) highlights that item, not Home.
- Parents of an active submenu item stay highlighted too.

Why
- Import copied the homepage’s active class into the CMS menu and never recalculated it from the URL.

Technical notes
- Menu render strips imported active/current classes, marks by page_uid or current path, aria-current=page.
v1.0.322026-08-06 11:00:39Fix media “New folder” fieldChoosing “New folder” in the media library correctly shows the name field again, including after in-app navigation.
For users
- The text field under “New folder” appears reliably when selected.

Why
- The script did not rebind after app-shell fragment navigation.

Technical notes
- Event delegation + re-init on lw:fragment-loaded (lw-media-folder.js v2).
v1.0.312026-08-06 10:50:19Global media library and foldersUpload shared images (logos, etc.) once under Library → Global media and reuse them on every site. Folder selection on upload lists existing folders or “New folder”.
For users
- New Library → Global media section for shared image upload and management.
- On a site media page, the Global tab lists those files read-only (copy URL); platform admins get a Manage link.
- On upload/edit, Folder is a dropdown (none / existing / New folder + text field).

Why
- Avoid re-uploading the same logo on every site.
- Make folder tagging clearer without retyping names.

Technical notes
- lw_media.site_id NULL = global; files under uploads/global/; single reference (no per-site copy).
v1.0.302026-08-06 09:59:30ZIP import: mega-menus preservedWhen importing a ZIP template, rich mega-menu panels (columns, images, CTAs) and Bootstrap dropdown attributes are kept and rendered correctly.
For users
- Templates with mega-menus (full-width panels, grids, images) keep their look after import.
- Bootstrap dropdowns keep their options (data-bs-toggle, etc.).
- Items with a mega panel show an HTML field in Menus for edits (until the mega-menu extension).

Why
- Import only read nested <ul> lists; <div class="dropdown-menu"> panels were dropped when tokenizing {{​​​​menu:…}}.

Technical notes
- New item fields: panel_html, link_attrs, label_html; harvest detection; render anchor+panel; URL rewrite on persist.
v1.0.292026-08-06 09:42:25Fix header/footer save (duplication)Saving header and footer on a ZIP template no longer duplicates the footer under the copyright bar.
For users
- Saving “Header & footer” no longer leaves a second unstyled footer.
- Sites already affected are fixed on view (and permanently when you save chrome again).

Why
- The parser used the first inner </div> of the footer as the block end, then appended the remainder after the footer.

Technical notes
- after_footer extracted via DOM; only script/style/link/noscript kept; public render repair.
token works on the public site
The

Platform version history (newest first).

v1.2.12026-08-09 16:47:35Extensible My account and classifieds lightboxPlugins can add My account tabs (e.g. My listings). Public pages now inject the classifieds gallery script at the end of the HTML.
For users
- My account: extensions can register new tabs via the CMS (?tab=… URLs).
- Classifieds 1.2.12: “My listings” tab with edit, delete, and mark as sold.
- Ad photo lightbox: works on CMS token pages too (not only /classifieds/… routes).

Why this change
- Keep listing management in My account alongside profile settings.
- Fix the gallery when ad HTML is rendered inside a site page without the plugin front router.

Technical notes
- CMS filters: public_account_tabs, public_account_tab_panels, public_account_post_actions, public_accounts_handle_post, public_page_html.
- Classifieds plugin: sold status, owner actions, defer gallery JS v4.
v1.2.0 Package2026-08-09 15:29:10ludiWARE 1.2.0 — public profiles and member identityMinor release 1.2.0: full install packages (ZIP + tar.gz), public member profiles, clickable names site-wide, unified activity history on profiles, and republished Forums / Classifieds plugins.
For users
- Download: ludiware-1.2.0.tar.gz + ludiware-1.2.0.zip
- Repo: https://repo.ludiware.com/releases/1.2.0/
- Includes /install/ wizard

CMS highlights (since 1.1.x)
- Public member profile: /membre/{uid} (avatar, name, member since)
- Member names link to profiles (blog, account strip, extensions)
- Activity history on profile: blog comments, forum topics/replies, classified ads and comments
- `public_member_profile_activity` filter for extensions

Republished MarketPlace plugins
- Forums 1.0.18 (profile links + forum activity)
- Classifieds 1.2.9 (linked comments, listing activity)

Technical notes
- OSS export without factory secrets
- VersionLog FileName → public tar.gz on repo.ludiware.com

Télécharger le package

v1.1.142026-08-09 15:26:40Activity history on public profileA member’s profile page now shows a unified timeline of their public contributions: blog comments, forum topics and replies, classified ads and ad comments.
For visitors
- “Public activity” section under the profile header (/membre/{uid}).
- Each row: date, action type, clickable title to the content, short excerpt when available.
- Newest first (up to 60 items), mixing blog, forums and active plugins.

For developers / extensions
- New `public_member_profile_activity` filter — return items `{at, kind, label, title, url, excerpt?}`.
- Helpers: `lw_public_accounts_collect_member_activity()`, `lw_public_accounts_render_member_activity_html()`, `lw_public_accounts_member_activity_item()`.
- Blog: `lw_blog_member_public_activity()` (published comments).
- Plugins register sources via the filter (Forums, Classifieds).

Why
- One consolidated view of a member’s public presence instead of isolated per-plugin sections.
v1.1.132026-08-09 15:23:12Member names link to public profileWherever a registered member appears (blog comments, account strip, etc.), their name now links to their public profile page when that profile is visible.
For visitors
- Click a local active member’s name → /membre/{uid} (or /member/{uid} in English).
- Account strip “Signed in as …”: your display name links to your profile.
- Blog post comments: authors tied to a local member account get a profile link.
- Guests, CDS portal users, or authors without a member account: plain text name (unchanged).

For developers / extensions
- Central helpers: `lw_public_accounts_author_context_from_row()`, `lw_public_accounts_resolve_content_author()`, `lw_public_accounts_render_author_name_html()`.
- Shared CSS class `lw-member-profile-link` for profile links.

Why
- Consistent public member identity across the site (blog, forums, classifieds, etc.) following public profiles in 1.1.12.
v1.1.122026-08-09 15:17:27Public profile for registered membersEach locally registered site member gets a public profile page with avatar and display name. Extensions can append content (e.g. published classifieds).
For visitors
- Public URL: /membre/{uid} (FR) or /member/{uid} (EN) — avatar, display name, member since date.
- Profiles are shown only for active local member accounts, not admins or CentreDeService portal users.

For developers / extensions
- New `public_member_profile_html` filter to extend the page (Classifieds plugin lists published ads).
- Helpers: `lw_public_accounts_public_profile_url()`, `lw_public_accounts_user_by_uid_public()`.

Why
- Let visitors see who published content and build a consistent public identity on the site.
v1.1.112026-08-09 14:33:21Standardized alerts for admin and pluginsNew unified alert system: success, error, warning, and info messages are shown consistently in lw-admin and on the public site. Plugins can contribute through dedicated hooks.
For users
- Admin confirmations and errors (e.g. “Listing deleted”, “Settings saved”) now appear at the top of the page in a consistent banner.
- On the public site, plugins can show user messages with the same visual style.

Why
- Each module and plugin handled its own alerts (different variables, query strings, custom CSS), causing duplication and inconsistency.

Technical notes
- New module lw-admin/functions/flash.php: lw_flash_add(), lw_flash_redirect(), lw_flash_render_html(), lw_public_flash_html().
- admin_flash and public_flash hooks for extensions.
- Backward compatible with $lwFlash and $lwPageFlashError.
- Shared lw-flash.css for admin/public.
- Classifieds plugin migrated as an example (v1.2.2).
v1.1.102026-08-08 18:52:20Portable site-to-site configurationconfig.php no longer holds secrets or factory domain settings: database, emails, and environment overrides live in config.local.php; hostname and defaults are inferred automatically.
For users
- Copy the CMS between sites without editing config.php: only config.local.php (or the /install/ wizard) needs to match the new host.
- Cookies and site name follow the real domain when HTTPpath / COOKIEpath are omitted.

Why
- config.php mixed MySQL credentials, the ludiware.com domain, and factory emails, making every client deploy error-prone.

Technical notes
- lw_config_detect_http_host() + lw_config_apply_runtime_defaults() after config.local.php.
- MySQL connects only when DBhost / DBname / DBusername are set.
- Updated config.local.example.php and installer (domain optional).
v1.1.92026-08-08 17:58:54Modal sign-in fix (POST fields + SQL)Sign-in from the modal now reliably sends email and password (POST to the current page, fields read explicitly) and works on hosts without mysqlnd.
For users
- The login/register modal posts to the page you are on (not only /sign-in/), avoiding silent failures.
- If the account has no password (Google/Facebook admin sign-in), a clear message appears instead of “invalid email or password”.

Why
- On some themes, fields did not always have a name attribute when FormData ran; on some hosts, user SQL reads failed without mysqlnd.

Technical notes
- lw-account-forms.js v4: explicit buildFormData; action = current page in modals.
- lw_public_accounts_stmt_fetch_one_assoc(); modal forms: post_url injected at render.
v1.1.82026-08-08 17:51:46Admin recognition on public site + cookie domainAn administrator signed into lw-admin is recognized again on the public site (My account header). Cookies align with the site’s actual domain (e.g. dormezcheznous.com).
For users
- If you are signed into lw-admin on the same domain as the public site, the header shows “My account” without using the modal again.
- After signing in via the modal, the public session persists.
- Check config.local.php: COOKIEpath must match the site domain (not ludiware.com if the site uses another hostname).

Why
- Admin cookies were sometimes set for ludiware.com while the site runs on a custom domain; the public site never received them. Modal sign-in could also fail when mismatched admin cookies interfered.

Technical notes
- lw_cookie_domain() uses current HTTP host when it differs from COOKIEpath.
- lw_public_accounts_auth_from_cookies() + member session sync.
- Auth bootstrap on public index.php.
v1.1.72026-08-08 17:31:50Conditional account header (snippets / tokens)Show “Sign in” or “My account” in the header based on session state, using an HTML snippet and {{​​​​account_if_guest}} / {{​​​​account_if_logged_in}} tokens.
For users
- In an HTML snippet (or layout): wrap the Sign in button with {{​​​​account_if_guest}}…{{​​​​/account_if_guest}} and My account with {{​​​​account_if_logged_in}}…{{​​​​/account_if_logged_in}}.
- Useful tokens: {{​​​​account_account_url}}, {{​​​​account_user_name}}, {{​​​​account_logout_url}}, {{​​​​account_logged_in}} (1 or empty).
- Put {{​​​​snippet:your_key}} in the layout header.
- Built-in alternative: {{​​​​account_strip}} (lw-admin banner).
- PHP snippets: $lw_db variable + lw_public_accounts_viewer().

Why
- Imported themes like DormezChezNous need a custom Bootstrap/modal button, not the generic banner.

Technical notes
- lw_public_accounts_apply_conditional_blocks() in apply_tokens; $lw_db exposed to PHP snippets.
v1.1.62026-08-08 17:25:08Account modal AJAX fix (Homelengo themes)Sign-in from a modal did not react on click: the account script now intercepts the click before theme scripts, shows errors (removes d-none), and shows loading state on the button.
For users
- The “Sign in” button in the modal works again: “…” while sending, visible red error on failure, page reload on success.
- No HTML change needed if data-lw-account and data-lw-account-error are already set.

Why
- Imported themes (Homelengo / DormezChezNous) registered listeners that blocked submit before our script; errors also stayed hidden behind Bootstrap d-none.

Technical notes
- lw-account-forms.js v3: capture click + submit, loaded last before </body>.
- Automatically removes d-none on data-lw-account-error.
v1.1.52026-08-08 17:13:29AJAX sign-in and register (modals)Account forms inside a modal (Bootstrap or similar) can submit without a full page reload: errors show in the modal, and the page refreshes after a successful sign-in.
For users
- If your login/register form is inside a modal (.modal or role="dialog"), submission uses AJAX automatically — no redirect to /sign-in/ that breaks the flow.
- Add an error slot: <div data-lw-account-error></div> in the modal.
- Force or disable: data-lw-account-ajax="1" or "0" on the <form>.
- On success: default is page reload (account menu updates); data-lw-account-on-success="redirect" to go to My account.
- Register captcha refreshes automatically after a failed attempt.

Why
- Sites like DormezChezNous open login/register in popups; a classic POST reloaded the whole page.

Technical notes
- lw-account-forms.js injected when data-lw-account is present.
- JSON responses server-side (lw_public_accounts_handle_post); index.php hook for POST from any page.
v1.1.42026-08-08 16:54:04Custom account forms (data-lw-account)Use your own HTML sign-in and register forms in the theme: the engine wires them automatically and exposes error messages via tokens or dedicated slots.
For users
- Form marker: data-lw-account="login" or "register" (also forgot, reset, profile, security).
- Fields: data-lw-account-field="email|password|…" or auto-detect via id/name/placeholder (like contact).
- Errors: {{​​​​account_error_text}} in your HTML, or <div data-lw-account-error></div>.
- Success: {{​​​​account_success_text}} or data-lw-account-success.
- Replace {{​​​​account_login}} with your markup on the /connexion/ shell page if you do not want the default lw-admin form.
- Register: <div class="lw-account-captcha-slot"></div> for captcha.
- Optional OAuth: <div data-lw-account-oauth></div>.

Why
- Imported themes like DormezChezNous keep their Bootstrap design without duplicating account logic.

Technical notes
- account_forms.php (same pattern as data-lw-contact).
- Injects CSRF + lw_account_action; POST action targets /connexion/, /register/, etc.
v1.1.32026-08-08 12:47:55HTML editors with syntax highlighting and tabsAll admin HTML and code fields now have syntax highlighting and Tab indentation (4 spaces), including TinyMCE’s source code view.
For users
- Raw HTML fields (header, footer, snippets, templates, custom CSS, etc.): line numbers, highlighting, Tab to indent.
- TinyMCE rich editor: the source code button opens the same highlighted experience.
- Imported themes: direct HTML editing with highlighting.

Why
- Easier markup editing without an external IDE.
- Tab inserts consistent indentation; Shift+Tab outdents.

Technical notes
- lw-code-editor.js module (CodeMirror 5 via CDN).
- html, css, and php modes per field.
- App-shell navigation compatible (reinit after page change).
v1.1.22026-08-08 11:37:45In-app CMS update and footer alertRemote installations show a visible admin footer warning when a newer package is available, and can install the update from Settings → Versions without manually re-uploading files.
For users
- Admin footer: “Update available (vX.Y.Z)” badge when a newer VersionLog package is published on repo.ludiware.com.
- Settings → Versions: banner with “Update now” (automatic download and deploy).
- Preserved local files: config.local.php, config.php (only the Version line is updated), uploads/, storage/, installed extensions.

Why
- Avoid manual FTP/SFTP updates on every hosted site.
- Surface an outdated version (e.g. 1.0.53 vs 1.1.x) without digging through history.

Technical notes
- lw_cms_update_apply(): downloads ZIP/tar.gz from repo.ludiware.com, extracts and copies core files.
- lw_versionlog_check_update() unchanged (30 min cache).
- Settings sidebar badge + chrome alert for managers.
v1.1.12026-08-08 11:30:24Version history: readable tokens and bracesVersionLog entries no longer show raw HTML codes ({): tokens like {{​​​​account_login}} display normally.
For visitors
- History page: CMS token examples show as plain text (visible braces), without double-encoded HTML entities.

Why
- Some VersionLog entries mentioned HTML entities ({) in their text; htmlspecialchars() displayed them literally on screen.

Technical
- lw_versionlog_prepare_display_source(): decode brace entities before zero-width neutralization and lw_e().
v1.1.0 Package2026-08-08 11:28:14ludiWARE 1.1.0 — public distributionMinor release 1.1.0: full install package (ZIP + tar.gz), public OAuth accounts, public version history, contact form prefill, and updated MarketPlace plugins.
For users
- Download: ludiware-1.1.0.tar.gz + ludiware-1.1.0.zip
- Repo: https://repo.ludiware.com/releases/1.1.0/
- Includes /install/ wizard (database, schema, admin account)

Since the 1.0.40 distribution
- Local member accounts: sign-up, login, forgot password, My account (profile / security tabs)
- Google and Facebook OAuth on the public site
- Public header recognizes lw-admin session and OAuth members
- {{​​​​versionlog}} token: version history on the public site
- Contact form: name and email prefilled when signed in
- Bootstrap Icons + admin icon picker
- MarketPlace plugins: FAQ, Testimonials, Gallery, Forms, Booking, Classifieds, Forums

Republished plugins (MarketPlace)
- Forums 1.0.16
- Classifieds 1.0.15

Technical notes
- OSS export without factory secrets; VersionLog FileName → public tar.gz.

Télécharger le package

v1.0.612026-08-08 11:25:48Version history: tokens display normallyExamples like {{​​​​account_login}} in version history show as readable text, without visible HTML entities ({).
For visitors / administrators
- History page and Settings → Versions: cited tokens appear as {{​​​​account_login}}, not as {{​​account_login}}.

Why
- Escaping braces as HTML entities then running htmlspecialchars() double-encoded and showed raw codes on screen.

Technical
- Zero-width space neutralization only (no { entities) in lw_versionlog_format_display_text() and lw_versionlog_shield_public_html().
v1.0.602026-08-08 11:24:31Contact form: name and email prefilled when signed inOn the contact form, Name and Email fields are filled automatically when the visitor is already signed in (local account, lw-admin, or CDS portal).
For users
- {{​​​​contact_form}} and theme ZIP contact forms: Name and Email prefilled when signed in.
- Fields already set in the template are not overwritten.

Why
- Avoid re-entering identity on every contact message.

Sources
- CDS portal (SSO session): full name + contact email.
- Public member account or lw-admin cookie: display_name + lw_users email.

Technical
- lw_contact_prefill_identity(), lw_contact_apply_prefill_to_form(), lw_contact_form_html().
v1.0.592026-08-08 11:20:46{{​​​​versionlog}} token works on the public siteThe {{​​​​versionlog}} token is now recognized on the public site: the History page shows the version list instead of the raw token text.
For visitors
- History page: {{​​​​versionlog}} content is replaced by the version list (styles and safe text).

Why
- The VersionLog module was only loaded in lw-admin; on index.php (public front), lw_versionlog_prepare_public_html() was missing and the token stayed literal.

Technical
- require versionlog.php in www/index.php before public_render.php.
v1.0.582026-08-08 11:07:13Public version history: CMS tokens shown as plain textOn the ludiware.com History page, mentions like {{​​​​account_login}}, {{​​​​menu:main}}, etc. in VersionLog entries display as text instead of injecting forms or menus.
For visitors
- History page (/historique/): version title, description and details show cited tokens as documentation, with no login form or menu injected mid-sentence.

Why
- VersionLog content is rendered via a PHP snippet then processed by the CMS token engine; example {{​​​​account_login}} was executed as a real token.

Technical
- Native {{​​​​versionlog}} / {{​​​​versionlog_list}} token; .lw-vl-* blocks shielded before the token pipeline; HTML entities for {{​​​​ and }} on display.
v1.0.572026-08-08 10:58:52Version history: CMS tokens shown as plain textMentions like {{​​​​account_login}}, {{​​​​menu:main}}, etc. in VersionLog technical details are no longer interpreted as CMS tokens.
For administrators
- Settings → Version history: title, description and full details show tokens literally (documentation), with no forms or injected content.

Why
- VersionLog entries often cite tokens as examples in “Technical detail”; the token engine must not execute them on display.

Technical
- Neutralize {{​​​​ → {{​​​​ + zero-width space on API output and lw-admin client; HTML-escaped display.
v1.0.562026-08-08 10:54:16Public header: lw-admin session recognitionWhen signed into lw-admin, you also appear as a member on the public site (header, My account), consistent with blog comments.
For visitors / administrators
- lw-admin cookies → {{​​​​account_strip}} shows your name and “My account”.
- /account/ works without visiting /login/ again.
- /login/ and /register/ redirect to My account when already recognized.

Identity priority (unchanged for blog when a Facebook session is active)
1. Public member session (login / OAuth)
2. lw-admin cookie

Public sign-out clears the member session only; if lw-admin remains, you stay signed in.
v1.0.552026-08-08 10:38:20Blog and forums: public member identity firstOn the public site, the member session (login / Facebook / Google) now takes precedence over lw-admin cookies for blog comments.
Fixed issue
- Header “Signed in as…” (member session) and blog “Commenting as…” (admin cookies) could show two different people when logged into lw-admin and Facebook on the public site.

Behavior
- Priority: CDS portal → public member (session) → admin staff (lw-admin cookie).
- Blog login hint links to /login/ when local accounts are active (no CDS).

Note
- If Facebook created a second lw_users account (different email from admin), that is expected: two separate profiles. Merge manually or delete the duplicate in Users.
v1.0.542026-08-08 10:11:29OAuth — stable redirect URLThe Google/Facebook callback URL in site settings now uses the site’s public domain (e.g. ludiware.com), not the admin host.
For administrators
- Settings → Member accounts: the “authorized redirect” URL matches the site’s public domain.
- Help note for adding the URI in Facebook Login → Valid OAuth Redirect URIs.

Why
- When opened from the admin panel (different subdomain), the generated URL could differ from the one used on the public site.
v1.0.532026-08-08 10:03:23Google and Facebook sign-in for membersVisitors can sign in or register with Google or Facebook on login and register pages when local accounts are used (no CentreDeService portal). A local member profile is created automatically when needed.
For visitors
- “Sign in with Google” and “Sign in with Facebook” on /login/ and /register/ (FR: /connexion/, /inscription/).
- If the email is not registered yet, a member account is created and the session starts.
- If an account already exists with the same email, the OAuth profile is linked to it.

For administrators
- Site settings → Member accounts: enable providers, OAuth credentials, and redirect URLs to paste into Google Cloud / Facebook Developer.
- Automatically disabled when the CentreDeService portal handles authentication.

Technical
- lw_users google_id / facebook_id columns, oauth_accounts.php module, /oauth/{provider}/callback/ routes.
v1.0.522026-08-08 08:35:18Icon picker — full catalogThe icon picker now shows useful favorites first, then all Bootstrap icons (~1,600) via search.
For administrators
- On open: a grid of favorites (home, commerce, transport, etc.).
- Search: filters the full set of ~1,683 installed Bootstrap Icons.
- Result count and message when the list is truncated.

Fix
- The list was previously capped at 120 icons in alphabetical order (123, alarm…), which felt incomplete.
v1.0.512026-08-08 08:29:09Bootstrap Icons and icon pickerBootstrap Icons now render reliably across the admin with complete font files. A reusable icon picker is available for forms (search, grid, preview).
For administrators
- Bootstrap Icons font files (woff/woff2) installed so existing `bi-*` icons in lw-admin display correctly.
- New reusable icon picker component (`lw_icon_picker_field`) for any admin form.

Usage
- Button with icon preview, name search, clickable grid, and a “No icon” option.
- PHP helpers `lw_bootstrap_icon_names()` and `lw_bootstrap_icon_class()`.

Technical
- Files: `functions/icon_picker.php`, `js/lw-icon-picker.js`, styles in `lw-admin.css`.
v1.0.502026-08-08 07:27:10My account — profile and security tabsThe My account page has two tabs: My information (first name, last name, avatar) and Access & security (email, password). New tokens for ZIP templates.
For users
- My information tab: first name, last name, avatar upload.
- Access & security tab: change email and/or password (current password required).

ZIP tokens
- {{​​​​account_panel}}: full panel with tabs.
- {{​​​​account_tabs}}, {{​​​​account_profile}}, {{​​​​account_security}}: custom layout.
- {{​​​​account_avatar}}, {{​​​​account_avatar_url}}, {{​​​​account_first_name}}, {{​​​​account_last_name}}, {{​​​​account_email}}.
- {{​​​​account_profile_url}}, {{​​​​account_security_url}}: direct links to each tab.

Technical notes
- lw_users.avatar_path column, files in uploads/users/, public session synced after updates.
v1.0.492026-08-08 07:17:18Public accounts unified in lw_usersRegistration, sign-in and forgot password on the public site now use the lw_users table (same as lw-admin). Only accounts with admin access can open lw-admin.
For users
- Same email and password everywhere: admin or visitor registered at /register/.
- Accounts created on the public site have the user role and cannot access lw-admin.
- Administrators can also sign in at /login/ with their usual credentials.

Why
- Removes the mistaken dual lw_site_members / lw_users system.

Technical notes
- public_accounts.php: auth, registration and reset on lw_users; per-site public session.
- auth.php unchanged: can_access_admin required for lw-admin.
- Obsolete lw_site_members table can be dropped in the database (DROP TABLE).
v1.0.482026-08-08 07:11:33Public sign-in with an administrator accountSite administrators can sign in on the public site (/login/) using the same email and password as lw-admin, without a separate registration.
For users
- At /login/, a global administrator or a user assigned to the site is accepted with lw-admin credentials.
- The first sign-in automatically creates the local member profile for that site; later sign-ins reuse it.

Why
- Before this fix, only accounts registered via /register/ (lw_site_members) were recognized; the first admin saw “Invalid email or password.”

Technical notes
- lw_users → lw_site_members bridge in lw_public_accounts_login(): admin password check, site access (global_admin or local_admin site member), hash sync and member session.
v1.0.472026-08-08 06:52:34Local member accounts on the public siteSites without a CentreDeService portal can offer registration, sign-in, forgot password and a member area on the public site, with tokens for ZIP templates and CMS shell pages.
For users
- Register at /register/ with captcha and password confirmation.
- Sign in at /login/, recover at /forgot-password/, reset via email link.
- “My account” when signed in; {{​​​​account_strip}} banner in the header.

For administrators
- Settings → Member accounts: CMS shells and “Generate system pages”.
- Menu editor: Add member (Sign in, Forgot password, Register, My account) when CDS is off.
- ZIP tokens: {{​​​​account_login}}, {{​​​​account_register}}, {{​​​​account_panel}}, {{​​​​account_forgot}}, {{​​​​account_reset}} and related URLs.

Why
- Let standalone ludiWARE sites (no CDS) offer visitor accounts for comments, gated content or future personalization.

Technical notes
- lw_site_members table, session CSRF, registration captcha separate from contact, try_serve routes, public_render apply_tokens.
v1.0.462026-08-07 12:59:32Contact captcha: fix valid answers rejectedWhen a page or template has multiple contact forms, the same security question is shown everywhere and a correct answer is accepted.
For users
- The “What is X + Y?” captcha is the same on all contact forms on a page.
- A correct answer is no longer rejected with “Incorrect security check.”

Why
- Each form could get a different question while the session stores only one expected answer (content and template finalized separately).

Technical notes
- lw_contact_captcha_issue() reuses a valid session challenge; contact finalize runs once on the full HTML (public_render.php).
v1.0.452026-08-07 12:15:48Blog tokens: latest posts (footer / sidebar)Use {{​​​​blog-latest-title-1}}, {{​​​​blog-latest-image-1}}, {{​​​​blog-latest-excerpt-1}}, etc. (up to 10) in a template or page to show the most recent posts.
For users
- {{​​​​blog-latest-title-N}}: title (N=1 = newest, 2 = second, … up to 10)
- {{​​​​blog-latest-image-N}}: featured image URL
- {{​​​​blog-latest-excerpt-N}}: excerpt from post body
- {{​​​​blog-latest-date-N}}: short date (e.g. April 15, 2020)
- {{​​​​blog-latest-date-long-N}}: long formatted date
- {{​​​​blog-latest-url-N}}: link to the post
- Ideal for a “Blog” block in the footer or sidebar of an imported ZIP theme.

Why
- Customize the footer without manually copying post titles and images.

Technical notes
- lw_blog_apply_latest_tokens() in blog.php, invoked from lw_blog_apply_tokens() on templates and pages.
v1.0.442026-08-07 12:10:34Theme contact: error messages and Subject fieldZIP theme contact forms again show the actual error message (captcha, missing fields, etc.) and the theme Subject field is supported.
For users
- After a failed send, the specific message appears (e.g. wrong captcha) instead of the generic “Could not send your message.”
- Theme Subject fields (e.g. msg_subject, placeholder or label “Subject”) are stored and included in notification email.
- Fields without a name attribute but with placeholder/label (Your name, Your email…) are detected on import and render.

Why
- lw_contact_form_html() cleared the session flash before theme forms could display it.
- Some themes name the subject field differently than subject.

Technical notes
- public_render.php: lw_contact_form_html() only when {{​​​​contact_form}} is present.
- contact_forms.php: msg_subject alias, placeholder/label detection, name/email fallbacks.
v1.0.432026-08-07 12:04:45Fix HTTP 500 on ZIP theme contact pagesImported “Contact us” pages no longer crash when the Send button sits inside the theme grid (Bootstrap, etc.).
For users
- Custom contact pages from imported themes render again with captcha and Messages inbox delivery.
- Before the fix, some layouts (e.g. Bootstrap grid forms) returned HTTP 500.

Why
- When wiring the theme form, the captcha slot was inserted at the wrong DOM level if the submit control was not a direct child of <form>.

Technical notes
- contact_forms.php: lw_contact_wire_form_element() inserts the captcha slot via the submit button’s immediate parent instead of form->insertBefore() on a nested node.
v1.0.422026-08-07 09:41:46Customizable CDS shop pages (shells and tokens)Like the blog, you can pick CMS pages as shells for the shop, categories, product pages, cart and orders, then place granular tokens (title, price, image, list, etc.).
For users
- In Site settings → CentreDeService.NET, “Shop shell pages”, map a CMS page to each screen type (/boutique/, category, product, cart, order).
- Without a shell, the default CDS render is unchanged.
- On a product shell: {{​​​​cds_product_title}}, {{​​​​cds_product_image}}, {{​​​​cds_product_price}}, {{​​​​cds_product_desc}}, {{​​​​cds_product_add_cart}}, or {{​​​​cds_product}} for the full card.
- On list / category: {{​​​​cds_shop_list}} (full block), or {{​​​​cds_shop_categories}}, {{​​​​cds_shop_products}}, {{​​​​cds_shop_pager}}, {{​​​​cds_category_title}}.
- Cart / order: {{​​​​cds_cart}}, {{​​​​cds_order}}, {{​​​​cds_cart_count}}.

Why
- Let the shop layout match the site theme, following the blog token pattern.

Technical notes
- Shells: cds_shop_*_page_uid; lw_cds_resolve_shell_page in lw_cds_try_serve.
- Tokens: lw_cds_apply_shop_field_tokens + context in lw_cds_apply_tokens.
v1.0.412026-08-07 09:03:11ZIP theme contact forms wired to the CMSContact forms already present in an imported theme can send messages through the lw-admin contact engine without replacing the theme design. Detection is automatic on import; you can also force it with data-lw-contact="1".
For users
- A theme contact form (classes / mailto / name-email-message fields) is wired to the Messages inbox and notification email.
- The form’s look (theme HTML/CSS) is preserved.
- Manual marker: data-lw-contact="1" forces binding; data-lw-contact="0" excludes it.
- Captcha and success/error messages work like {{​​​​contact_form}}.

Why
- Avoid replacing a polished theme form with the generic {{​​​​contact_form}} markup.

Technical notes
- lw_contact_wire_form_html (import); lw_contact_finalize_bound_forms (render); field aliases in lw_contact_submit.
v1.0.40 Package2026-08-06 13:07:30ludiWARE 1.0.40 — installation packageFull public distribution (ZIP + tar.gz) with installer. Includes recent work: blog (tokens, category URLs, subcategories), CMS 404 page, global media library, menus / ZIP import, and display fixes.
For users
- Downloadable package to install or update ludiWARE.
- Archives: ludiware-1.0.40.tar.gz and ludiware-1.0.40.zip
- Repo: https://repo.ludiware.com/releases/1.0.40/
- Includes /install/ wizard (database, schema, admin account)

Notable since last distribution
- Blog: author / long date / time / comments / categories tokens; /blogue/category/subcategory/slug URLs; admin subcategories; French comment agreement
- Designated CMS 404 page + badge; ZIP import (chrome, mega-menus, 404 detect)
- Global media library and folders; active menus; header dedupe

Why
- Ship an installable package aligned with the current CMS version.

Technical notes
- OSS export (no secrets, no factory api/admin); VersionLog FileName points to the public tar.gz.

Télécharger le package

v1.0.392026-08-06 13:01:02Singular “commentaire” for 0 or 1 commentIn the French blog post list, “0 commentaire” and “1 commentaire” (no trailing s) are shown; the plural starts at 2.
For users
- Post card meta: correct French agreement for commentaire (singular for 0/1).

Why
- “0 commentaires” was incorrect in French.

Technical notes
- lw_blog_format_comments_count: singular when count <= 1 (FR).
v1.0.382026-08-06 13:00:31Easier blog subcategories in adminIn lw-admin, each category has a button to add a subcategory. The Parent category field is more prominent, with a tree-style list.
For users
- Categories list: diagram icon creates a subcategory already linked to the right parent.
- Form: parent field first, help about /blogue/parent/child/… URLs.
- “Subcategory” badge and Parent column in the table.

Why
- Hierarchy already existed in the database but was too easy to miss in the UI.

Technical notes
- blogcats.php (?new=1&parent=uid); blog.cat_* i18n keys; category cache bust.
v1.0.372026-08-06 12:51:12Blog URLs with nested categoriesPosts are now available at /blogue/category/subcategory/post-slug. Old /blogue/slug addresses redirect to the new URL automatically.
For users
- Post URL: /blogue/{category}/{subcategory}/{slug} from the category tree.
- No category: /blogue/{slug} as before.
- Category lists: /blogue/{category}/{subcategory} (legacy /blogue/categorie/… redirects).
- List links, comments, sitemap and admin use the new structure.

Why
- Mirror the category tree in the URL for clearer SEO and navigation.

Technical notes
- lw_blog_post_url / lw_blog_post_path_extra; path resolution in lw_blog_try_serve; 301 redirects.
v1.0.362026-08-06 12:48:37New blog tokens (author, date, comments…)Article templates can show the comment count, author, a long date, publish time, and the categories list. An Author field was added when editing posts.
For users
- New tokens: {{​​​​blog_comments_count}} (number only), {{​​​​blog_author}}, {{​​​​blog_date_long}} (e.g. Thursday, September 3, 2024), {{​​​​blog_time}} (HH:MM), {{​​​​blog_categories}} (published categories list).
- {{​​​​blog_date}} stays YYYY-MM-DD.
- “Author” field on create/edit, used by {{​​​​blog_author}}.

Why
- Richer article layouts without hard-coded HTML.

Technical notes
- author_name column; lw_blog_format_date_long / lw_blog_render_categories_token_list helpers; tokens documented in templates.php.
v1.0.352026-08-06 11:32:25CMS 404 page: fixed display + badgeThe page set as 404 now renders correctly (including on draft sites / preview). The pages list shows a “404” badge like the home badge. ZIP imports auto-detect 404 error pages.
For users
- When you check “Use as 404 page”, unknown URLs show that themed page instead of the generic dark 404.
- This also works in preview and while the site is still a draft.
- Pages list: orange “404” badge next to status, like the Home badge.
- New ZIP imports: a page named 404 / not-found is assigned automatically.

Why
- 404 page rendering ignored preview mode and rejected draft sites (“Site not published”), falling back to the generic page.

Technical notes
- lw_public_site_404(..., $preview); force preview render when site is draft; pages.badge_404; auto page_404_page_uid on ZIP import.
v1.0.342026-08-06 11:26:54ZIP import: no duplicate header in page contentWhen importing a template, the header (and similar wrappers) is removed from page content once it lives in the global header. Already-imported sites are cleaned on view.
For users
- Imported pages no longer keep a copy of the menu/header in their content when global chrome is active.
- Templates without a <header> tag (e.g. #header / .header-area) are supported too.

Why
- Stripping was too strict (majority vote, non-semantic wrappers ignored), leaving leftovers in page HTML.

Technical notes
- Structural detection + normalized affix (ignore active); broader DOM strip/dedupe; public render cleanup.
v1.0.332026-08-06 11:16:07Menu: current item highlighted correctlyOn sites (including imported templates), the active menu item follows the page being viewed instead of staying stuck on Home.
For users
- Visiting About (or another page) highlights that item, not Home.
- Parents of an active submenu item stay highlighted too.

Why
- Import copied the homepage’s active class into the CMS menu and never recalculated it from the URL.

Technical notes
- Menu render strips imported active/current classes, marks by page_uid or current path, aria-current=page.
v1.0.322026-08-06 11:00:39Fix media “New folder” fieldChoosing “New folder” in the media library correctly shows the name field again, including after in-app navigation.
For users
- The text field under “New folder” appears reliably when selected.

Why
- The script did not rebind after app-shell fragment navigation.

Technical notes
- Event delegation + re-init on lw:fragment-loaded (lw-media-folder.js v2).
v1.0.312026-08-06 10:50:19Global media library and foldersUpload shared images (logos, etc.) once under Library → Global media and reuse them on every site. Folder selection on upload lists existing folders or “New folder”.
For users
- New Library → Global media section for shared image upload and management.
- On a site media page, the Global tab lists those files read-only (copy URL); platform admins get a Manage link.
- On upload/edit, Folder is a dropdown (none / existing / New folder + text field).

Why
- Avoid re-uploading the same logo on every site.
- Make folder tagging clearer without retyping names.

Technical notes
- lw_media.site_id NULL = global; files under uploads/global/; single reference (no per-site copy).
v1.0.302026-08-06 09:59:30ZIP import: mega-menus preservedWhen importing a ZIP template, rich mega-menu panels (columns, images, CTAs) and Bootstrap dropdown attributes are kept and rendered correctly.
For users
- Templates with mega-menus (full-width panels, grids, images) keep their look after import.
- Bootstrap dropdowns keep their options (data-bs-toggle, etc.).
- Items with a mega panel show an HTML field in Menus for edits (until the mega-menu extension).

Why
- Import only read nested <ul> lists; <div class="dropdown-menu"> panels were dropped when tokenizing {{​​​​menu:…}}.

Technical notes
- New item fields: panel_html, link_attrs, label_html; harvest detection; render anchor+panel; URL rewrite on persist.
v1.0.292026-08-06 09:42:25Fix header/footer save (duplication)Saving header and footer on a ZIP template no longer duplicates the footer under the copyright bar.
For users
- Saving “Header & footer” no longer leaves a second unstyled footer.
- Sites already affected are fixed on view (and permanently when you save chrome again).

Why
- The parser used the first inner </div> of the footer as the block end, then appended the remainder after the footer.

Technical notes
- after_footer extracted via DOM; only script/style/link/noscript kept; public render repair.
token is now recognized on the public site: the History page shows the version list instead of the raw token text.
For visitors
- History page: 

Platform version history (newest first).

v1.2.12026-08-09 16:47:35Extensible My account and classifieds lightboxPlugins can add My account tabs (e.g. My listings). Public pages now inject the classifieds gallery script at the end of the HTML.
For users
- My account: extensions can register new tabs via the CMS (?tab=… URLs).
- Classifieds 1.2.12: “My listings” tab with edit, delete, and mark as sold.
- Ad photo lightbox: works on CMS token pages too (not only /classifieds/… routes).

Why this change
- Keep listing management in My account alongside profile settings.
- Fix the gallery when ad HTML is rendered inside a site page without the plugin front router.

Technical notes
- CMS filters: public_account_tabs, public_account_tab_panels, public_account_post_actions, public_accounts_handle_post, public_page_html.
- Classifieds plugin: sold status, owner actions, defer gallery JS v4.
v1.2.0 Package2026-08-09 15:29:10ludiWARE 1.2.0 — public profiles and member identityMinor release 1.2.0: full install packages (ZIP + tar.gz), public member profiles, clickable names site-wide, unified activity history on profiles, and republished Forums / Classifieds plugins.
For users
- Download: ludiware-1.2.0.tar.gz + ludiware-1.2.0.zip
- Repo: https://repo.ludiware.com/releases/1.2.0/
- Includes /install/ wizard

CMS highlights (since 1.1.x)
- Public member profile: /membre/{uid} (avatar, name, member since)
- Member names link to profiles (blog, account strip, extensions)
- Activity history on profile: blog comments, forum topics/replies, classified ads and comments
- `public_member_profile_activity` filter for extensions

Republished MarketPlace plugins
- Forums 1.0.18 (profile links + forum activity)
- Classifieds 1.2.9 (linked comments, listing activity)

Technical notes
- OSS export without factory secrets
- VersionLog FileName → public tar.gz on repo.ludiware.com

Télécharger le package

v1.1.142026-08-09 15:26:40Activity history on public profileA member’s profile page now shows a unified timeline of their public contributions: blog comments, forum topics and replies, classified ads and ad comments.
For visitors
- “Public activity” section under the profile header (/membre/{uid}).
- Each row: date, action type, clickable title to the content, short excerpt when available.
- Newest first (up to 60 items), mixing blog, forums and active plugins.

For developers / extensions
- New `public_member_profile_activity` filter — return items `{at, kind, label, title, url, excerpt?}`.
- Helpers: `lw_public_accounts_collect_member_activity()`, `lw_public_accounts_render_member_activity_html()`, `lw_public_accounts_member_activity_item()`.
- Blog: `lw_blog_member_public_activity()` (published comments).
- Plugins register sources via the filter (Forums, Classifieds).

Why
- One consolidated view of a member’s public presence instead of isolated per-plugin sections.
v1.1.132026-08-09 15:23:12Member names link to public profileWherever a registered member appears (blog comments, account strip, etc.), their name now links to their public profile page when that profile is visible.
For visitors
- Click a local active member’s name → /membre/{uid} (or /member/{uid} in English).
- Account strip “Signed in as …”: your display name links to your profile.
- Blog post comments: authors tied to a local member account get a profile link.
- Guests, CDS portal users, or authors without a member account: plain text name (unchanged).

For developers / extensions
- Central helpers: `lw_public_accounts_author_context_from_row()`, `lw_public_accounts_resolve_content_author()`, `lw_public_accounts_render_author_name_html()`.
- Shared CSS class `lw-member-profile-link` for profile links.

Why
- Consistent public member identity across the site (blog, forums, classifieds, etc.) following public profiles in 1.1.12.
v1.1.122026-08-09 15:17:27Public profile for registered membersEach locally registered site member gets a public profile page with avatar and display name. Extensions can append content (e.g. published classifieds).
For visitors
- Public URL: /membre/{uid} (FR) or /member/{uid} (EN) — avatar, display name, member since date.
- Profiles are shown only for active local member accounts, not admins or CentreDeService portal users.

For developers / extensions
- New `public_member_profile_html` filter to extend the page (Classifieds plugin lists published ads).
- Helpers: `lw_public_accounts_public_profile_url()`, `lw_public_accounts_user_by_uid_public()`.

Why
- Let visitors see who published content and build a consistent public identity on the site.
v1.1.112026-08-09 14:33:21Standardized alerts for admin and pluginsNew unified alert system: success, error, warning, and info messages are shown consistently in lw-admin and on the public site. Plugins can contribute through dedicated hooks.
For users
- Admin confirmations and errors (e.g. “Listing deleted”, “Settings saved”) now appear at the top of the page in a consistent banner.
- On the public site, plugins can show user messages with the same visual style.

Why
- Each module and plugin handled its own alerts (different variables, query strings, custom CSS), causing duplication and inconsistency.

Technical notes
- New module lw-admin/functions/flash.php: lw_flash_add(), lw_flash_redirect(), lw_flash_render_html(), lw_public_flash_html().
- admin_flash and public_flash hooks for extensions.
- Backward compatible with $lwFlash and $lwPageFlashError.
- Shared lw-flash.css for admin/public.
- Classifieds plugin migrated as an example (v1.2.2).
v1.1.102026-08-08 18:52:20Portable site-to-site configurationconfig.php no longer holds secrets or factory domain settings: database, emails, and environment overrides live in config.local.php; hostname and defaults are inferred automatically.
For users
- Copy the CMS between sites without editing config.php: only config.local.php (or the /install/ wizard) needs to match the new host.
- Cookies and site name follow the real domain when HTTPpath / COOKIEpath are omitted.

Why
- config.php mixed MySQL credentials, the ludiware.com domain, and factory emails, making every client deploy error-prone.

Technical notes
- lw_config_detect_http_host() + lw_config_apply_runtime_defaults() after config.local.php.
- MySQL connects only when DBhost / DBname / DBusername are set.
- Updated config.local.example.php and installer (domain optional).
v1.1.92026-08-08 17:58:54Modal sign-in fix (POST fields + SQL)Sign-in from the modal now reliably sends email and password (POST to the current page, fields read explicitly) and works on hosts without mysqlnd.
For users
- The login/register modal posts to the page you are on (not only /sign-in/), avoiding silent failures.
- If the account has no password (Google/Facebook admin sign-in), a clear message appears instead of “invalid email or password”.

Why
- On some themes, fields did not always have a name attribute when FormData ran; on some hosts, user SQL reads failed without mysqlnd.

Technical notes
- lw-account-forms.js v4: explicit buildFormData; action = current page in modals.
- lw_public_accounts_stmt_fetch_one_assoc(); modal forms: post_url injected at render.
v1.1.82026-08-08 17:51:46Admin recognition on public site + cookie domainAn administrator signed into lw-admin is recognized again on the public site (My account header). Cookies align with the site’s actual domain (e.g. dormezcheznous.com).
For users
- If you are signed into lw-admin on the same domain as the public site, the header shows “My account” without using the modal again.
- After signing in via the modal, the public session persists.
- Check config.local.php: COOKIEpath must match the site domain (not ludiware.com if the site uses another hostname).

Why
- Admin cookies were sometimes set for ludiware.com while the site runs on a custom domain; the public site never received them. Modal sign-in could also fail when mismatched admin cookies interfered.

Technical notes
- lw_cookie_domain() uses current HTTP host when it differs from COOKIEpath.
- lw_public_accounts_auth_from_cookies() + member session sync.
- Auth bootstrap on public index.php.
v1.1.72026-08-08 17:31:50Conditional account header (snippets / tokens)Show “Sign in” or “My account” in the header based on session state, using an HTML snippet and {{​​​​account_if_guest}} / {{​​​​account_if_logged_in}} tokens.
For users
- In an HTML snippet (or layout): wrap the Sign in button with {{​​​​account_if_guest}}…{{​​​​/account_if_guest}} and My account with {{​​​​account_if_logged_in}}…{{​​​​/account_if_logged_in}}.
- Useful tokens: {{​​​​account_account_url}}, {{​​​​account_user_name}}, {{​​​​account_logout_url}}, {{​​​​account_logged_in}} (1 or empty).
- Put {{​​​​snippet:your_key}} in the layout header.
- Built-in alternative: {{​​​​account_strip}} (lw-admin banner).
- PHP snippets: $lw_db variable + lw_public_accounts_viewer().

Why
- Imported themes like DormezChezNous need a custom Bootstrap/modal button, not the generic banner.

Technical notes
- lw_public_accounts_apply_conditional_blocks() in apply_tokens; $lw_db exposed to PHP snippets.
v1.1.62026-08-08 17:25:08Account modal AJAX fix (Homelengo themes)Sign-in from a modal did not react on click: the account script now intercepts the click before theme scripts, shows errors (removes d-none), and shows loading state on the button.
For users
- The “Sign in” button in the modal works again: “…” while sending, visible red error on failure, page reload on success.
- No HTML change needed if data-lw-account and data-lw-account-error are already set.

Why
- Imported themes (Homelengo / DormezChezNous) registered listeners that blocked submit before our script; errors also stayed hidden behind Bootstrap d-none.

Technical notes
- lw-account-forms.js v3: capture click + submit, loaded last before </body>.
- Automatically removes d-none on data-lw-account-error.
v1.1.52026-08-08 17:13:29AJAX sign-in and register (modals)Account forms inside a modal (Bootstrap or similar) can submit without a full page reload: errors show in the modal, and the page refreshes after a successful sign-in.
For users
- If your login/register form is inside a modal (.modal or role="dialog"), submission uses AJAX automatically — no redirect to /sign-in/ that breaks the flow.
- Add an error slot: <div data-lw-account-error></div> in the modal.
- Force or disable: data-lw-account-ajax="1" or "0" on the <form>.
- On success: default is page reload (account menu updates); data-lw-account-on-success="redirect" to go to My account.
- Register captcha refreshes automatically after a failed attempt.

Why
- Sites like DormezChezNous open login/register in popups; a classic POST reloaded the whole page.

Technical notes
- lw-account-forms.js injected when data-lw-account is present.
- JSON responses server-side (lw_public_accounts_handle_post); index.php hook for POST from any page.
v1.1.42026-08-08 16:54:04Custom account forms (data-lw-account)Use your own HTML sign-in and register forms in the theme: the engine wires them automatically and exposes error messages via tokens or dedicated slots.
For users
- Form marker: data-lw-account="login" or "register" (also forgot, reset, profile, security).
- Fields: data-lw-account-field="email|password|…" or auto-detect via id/name/placeholder (like contact).
- Errors: {{​​​​account_error_text}} in your HTML, or <div data-lw-account-error></div>.
- Success: {{​​​​account_success_text}} or data-lw-account-success.
- Replace {{​​​​account_login}} with your markup on the /connexion/ shell page if you do not want the default lw-admin form.
- Register: <div class="lw-account-captcha-slot"></div> for captcha.
- Optional OAuth: <div data-lw-account-oauth></div>.

Why
- Imported themes like DormezChezNous keep their Bootstrap design without duplicating account logic.

Technical notes
- account_forms.php (same pattern as data-lw-contact).
- Injects CSRF + lw_account_action; POST action targets /connexion/, /register/, etc.
v1.1.32026-08-08 12:47:55HTML editors with syntax highlighting and tabsAll admin HTML and code fields now have syntax highlighting and Tab indentation (4 spaces), including TinyMCE’s source code view.
For users
- Raw HTML fields (header, footer, snippets, templates, custom CSS, etc.): line numbers, highlighting, Tab to indent.
- TinyMCE rich editor: the source code button opens the same highlighted experience.
- Imported themes: direct HTML editing with highlighting.

Why
- Easier markup editing without an external IDE.
- Tab inserts consistent indentation; Shift+Tab outdents.

Technical notes
- lw-code-editor.js module (CodeMirror 5 via CDN).
- html, css, and php modes per field.
- App-shell navigation compatible (reinit after page change).
v1.1.22026-08-08 11:37:45In-app CMS update and footer alertRemote installations show a visible admin footer warning when a newer package is available, and can install the update from Settings → Versions without manually re-uploading files.
For users
- Admin footer: “Update available (vX.Y.Z)” badge when a newer VersionLog package is published on repo.ludiware.com.
- Settings → Versions: banner with “Update now” (automatic download and deploy).
- Preserved local files: config.local.php, config.php (only the Version line is updated), uploads/, storage/, installed extensions.

Why
- Avoid manual FTP/SFTP updates on every hosted site.
- Surface an outdated version (e.g. 1.0.53 vs 1.1.x) without digging through history.

Technical notes
- lw_cms_update_apply(): downloads ZIP/tar.gz from repo.ludiware.com, extracts and copies core files.
- lw_versionlog_check_update() unchanged (30 min cache).
- Settings sidebar badge + chrome alert for managers.
v1.1.12026-08-08 11:30:24Version history: readable tokens and bracesVersionLog entries no longer show raw HTML codes ({): tokens like {{​​​​account_login}} display normally.
For visitors
- History page: CMS token examples show as plain text (visible braces), without double-encoded HTML entities.

Why
- Some VersionLog entries mentioned HTML entities ({) in their text; htmlspecialchars() displayed them literally on screen.

Technical
- lw_versionlog_prepare_display_source(): decode brace entities before zero-width neutralization and lw_e().
v1.1.0 Package2026-08-08 11:28:14ludiWARE 1.1.0 — public distributionMinor release 1.1.0: full install package (ZIP + tar.gz), public OAuth accounts, public version history, contact form prefill, and updated MarketPlace plugins.
For users
- Download: ludiware-1.1.0.tar.gz + ludiware-1.1.0.zip
- Repo: https://repo.ludiware.com/releases/1.1.0/
- Includes /install/ wizard (database, schema, admin account)

Since the 1.0.40 distribution
- Local member accounts: sign-up, login, forgot password, My account (profile / security tabs)
- Google and Facebook OAuth on the public site
- Public header recognizes lw-admin session and OAuth members
- {{​​​​versionlog}} token: version history on the public site
- Contact form: name and email prefilled when signed in
- Bootstrap Icons + admin icon picker
- MarketPlace plugins: FAQ, Testimonials, Gallery, Forms, Booking, Classifieds, Forums

Republished plugins (MarketPlace)
- Forums 1.0.16
- Classifieds 1.0.15

Technical notes
- OSS export without factory secrets; VersionLog FileName → public tar.gz.

Télécharger le package

v1.0.612026-08-08 11:25:48Version history: tokens display normallyExamples like {{​​​​account_login}} in version history show as readable text, without visible HTML entities ({).
For visitors / administrators
- History page and Settings → Versions: cited tokens appear as {{​​​​account_login}}, not as {{​​account_login}}.

Why
- Escaping braces as HTML entities then running htmlspecialchars() double-encoded and showed raw codes on screen.

Technical
- Zero-width space neutralization only (no { entities) in lw_versionlog_format_display_text() and lw_versionlog_shield_public_html().
v1.0.602026-08-08 11:24:31Contact form: name and email prefilled when signed inOn the contact form, Name and Email fields are filled automatically when the visitor is already signed in (local account, lw-admin, or CDS portal).
For users
- {{​​​​contact_form}} and theme ZIP contact forms: Name and Email prefilled when signed in.
- Fields already set in the template are not overwritten.

Why
- Avoid re-entering identity on every contact message.

Sources
- CDS portal (SSO session): full name + contact email.
- Public member account or lw-admin cookie: display_name + lw_users email.

Technical
- lw_contact_prefill_identity(), lw_contact_apply_prefill_to_form(), lw_contact_form_html().
v1.0.592026-08-08 11:20:46{{​​​​versionlog}} token works on the public siteThe {{​​​​versionlog}} token is now recognized on the public site: the History page shows the version list instead of the raw token text.
For visitors
- History page: {{​​​​versionlog}} content is replaced by the version list (styles and safe text).

Why
- The VersionLog module was only loaded in lw-admin; on index.php (public front), lw_versionlog_prepare_public_html() was missing and the token stayed literal.

Technical
- require versionlog.php in www/index.php before public_render.php.
v1.0.582026-08-08 11:07:13Public version history: CMS tokens shown as plain textOn the ludiware.com History page, mentions like {{​​​​account_login}}, {{​​​​menu:main}}, etc. in VersionLog entries display as text instead of injecting forms or menus.
For visitors
- History page (/historique/): version title, description and details show cited tokens as documentation, with no login form or menu injected mid-sentence.

Why
- VersionLog content is rendered via a PHP snippet then processed by the CMS token engine; example {{​​​​account_login}} was executed as a real token.

Technical
- Native {{​​​​versionlog}} / {{​​​​versionlog_list}} token; .lw-vl-* blocks shielded before the token pipeline; HTML entities for {{​​​​ and }} on display.
v1.0.572026-08-08 10:58:52Version history: CMS tokens shown as plain textMentions like {{​​​​account_login}}, {{​​​​menu:main}}, etc. in VersionLog technical details are no longer interpreted as CMS tokens.
For administrators
- Settings → Version history: title, description and full details show tokens literally (documentation), with no forms or injected content.

Why
- VersionLog entries often cite tokens as examples in “Technical detail”; the token engine must not execute them on display.

Technical
- Neutralize {{​​​​ → {{​​​​ + zero-width space on API output and lw-admin client; HTML-escaped display.
v1.0.562026-08-08 10:54:16Public header: lw-admin session recognitionWhen signed into lw-admin, you also appear as a member on the public site (header, My account), consistent with blog comments.
For visitors / administrators
- lw-admin cookies → {{​​​​account_strip}} shows your name and “My account”.
- /account/ works without visiting /login/ again.
- /login/ and /register/ redirect to My account when already recognized.

Identity priority (unchanged for blog when a Facebook session is active)
1. Public member session (login / OAuth)
2. lw-admin cookie

Public sign-out clears the member session only; if lw-admin remains, you stay signed in.
v1.0.552026-08-08 10:38:20Blog and forums: public member identity firstOn the public site, the member session (login / Facebook / Google) now takes precedence over lw-admin cookies for blog comments.
Fixed issue
- Header “Signed in as…” (member session) and blog “Commenting as…” (admin cookies) could show two different people when logged into lw-admin and Facebook on the public site.

Behavior
- Priority: CDS portal → public member (session) → admin staff (lw-admin cookie).
- Blog login hint links to /login/ when local accounts are active (no CDS).

Note
- If Facebook created a second lw_users account (different email from admin), that is expected: two separate profiles. Merge manually or delete the duplicate in Users.
v1.0.542026-08-08 10:11:29OAuth — stable redirect URLThe Google/Facebook callback URL in site settings now uses the site’s public domain (e.g. ludiware.com), not the admin host.
For administrators
- Settings → Member accounts: the “authorized redirect” URL matches the site’s public domain.
- Help note for adding the URI in Facebook Login → Valid OAuth Redirect URIs.

Why
- When opened from the admin panel (different subdomain), the generated URL could differ from the one used on the public site.
v1.0.532026-08-08 10:03:23Google and Facebook sign-in for membersVisitors can sign in or register with Google or Facebook on login and register pages when local accounts are used (no CentreDeService portal). A local member profile is created automatically when needed.
For visitors
- “Sign in with Google” and “Sign in with Facebook” on /login/ and /register/ (FR: /connexion/, /inscription/).
- If the email is not registered yet, a member account is created and the session starts.
- If an account already exists with the same email, the OAuth profile is linked to it.

For administrators
- Site settings → Member accounts: enable providers, OAuth credentials, and redirect URLs to paste into Google Cloud / Facebook Developer.
- Automatically disabled when the CentreDeService portal handles authentication.

Technical
- lw_users google_id / facebook_id columns, oauth_accounts.php module, /oauth/{provider}/callback/ routes.
v1.0.522026-08-08 08:35:18Icon picker — full catalogThe icon picker now shows useful favorites first, then all Bootstrap icons (~1,600) via search.
For administrators
- On open: a grid of favorites (home, commerce, transport, etc.).
- Search: filters the full set of ~1,683 installed Bootstrap Icons.
- Result count and message when the list is truncated.

Fix
- The list was previously capped at 120 icons in alphabetical order (123, alarm…), which felt incomplete.
v1.0.512026-08-08 08:29:09Bootstrap Icons and icon pickerBootstrap Icons now render reliably across the admin with complete font files. A reusable icon picker is available for forms (search, grid, preview).
For administrators
- Bootstrap Icons font files (woff/woff2) installed so existing `bi-*` icons in lw-admin display correctly.
- New reusable icon picker component (`lw_icon_picker_field`) for any admin form.

Usage
- Button with icon preview, name search, clickable grid, and a “No icon” option.
- PHP helpers `lw_bootstrap_icon_names()` and `lw_bootstrap_icon_class()`.

Technical
- Files: `functions/icon_picker.php`, `js/lw-icon-picker.js`, styles in `lw-admin.css`.
v1.0.502026-08-08 07:27:10My account — profile and security tabsThe My account page has two tabs: My information (first name, last name, avatar) and Access & security (email, password). New tokens for ZIP templates.
For users
- My information tab: first name, last name, avatar upload.
- Access & security tab: change email and/or password (current password required).

ZIP tokens
- {{​​​​account_panel}}: full panel with tabs.
- {{​​​​account_tabs}}, {{​​​​account_profile}}, {{​​​​account_security}}: custom layout.
- {{​​​​account_avatar}}, {{​​​​account_avatar_url}}, {{​​​​account_first_name}}, {{​​​​account_last_name}}, {{​​​​account_email}}.
- {{​​​​account_profile_url}}, {{​​​​account_security_url}}: direct links to each tab.

Technical notes
- lw_users.avatar_path column, files in uploads/users/, public session synced after updates.
v1.0.492026-08-08 07:17:18Public accounts unified in lw_usersRegistration, sign-in and forgot password on the public site now use the lw_users table (same as lw-admin). Only accounts with admin access can open lw-admin.
For users
- Same email and password everywhere: admin or visitor registered at /register/.
- Accounts created on the public site have the user role and cannot access lw-admin.
- Administrators can also sign in at /login/ with their usual credentials.

Why
- Removes the mistaken dual lw_site_members / lw_users system.

Technical notes
- public_accounts.php: auth, registration and reset on lw_users; per-site public session.
- auth.php unchanged: can_access_admin required for lw-admin.
- Obsolete lw_site_members table can be dropped in the database (DROP TABLE).
v1.0.482026-08-08 07:11:33Public sign-in with an administrator accountSite administrators can sign in on the public site (/login/) using the same email and password as lw-admin, without a separate registration.
For users
- At /login/, a global administrator or a user assigned to the site is accepted with lw-admin credentials.
- The first sign-in automatically creates the local member profile for that site; later sign-ins reuse it.

Why
- Before this fix, only accounts registered via /register/ (lw_site_members) were recognized; the first admin saw “Invalid email or password.”

Technical notes
- lw_users → lw_site_members bridge in lw_public_accounts_login(): admin password check, site access (global_admin or local_admin site member), hash sync and member session.
v1.0.472026-08-08 06:52:34Local member accounts on the public siteSites without a CentreDeService portal can offer registration, sign-in, forgot password and a member area on the public site, with tokens for ZIP templates and CMS shell pages.
For users
- Register at /register/ with captcha and password confirmation.
- Sign in at /login/, recover at /forgot-password/, reset via email link.
- “My account” when signed in; {{​​​​account_strip}} banner in the header.

For administrators
- Settings → Member accounts: CMS shells and “Generate system pages”.
- Menu editor: Add member (Sign in, Forgot password, Register, My account) when CDS is off.
- ZIP tokens: {{​​​​account_login}}, {{​​​​account_register}}, {{​​​​account_panel}}, {{​​​​account_forgot}}, {{​​​​account_reset}} and related URLs.

Why
- Let standalone ludiWARE sites (no CDS) offer visitor accounts for comments, gated content or future personalization.

Technical notes
- lw_site_members table, session CSRF, registration captcha separate from contact, try_serve routes, public_render apply_tokens.
v1.0.462026-08-07 12:59:32Contact captcha: fix valid answers rejectedWhen a page or template has multiple contact forms, the same security question is shown everywhere and a correct answer is accepted.
For users
- The “What is X + Y?” captcha is the same on all contact forms on a page.
- A correct answer is no longer rejected with “Incorrect security check.”

Why
- Each form could get a different question while the session stores only one expected answer (content and template finalized separately).

Technical notes
- lw_contact_captcha_issue() reuses a valid session challenge; contact finalize runs once on the full HTML (public_render.php).
v1.0.452026-08-07 12:15:48Blog tokens: latest posts (footer / sidebar)Use {{​​​​blog-latest-title-1}}, {{​​​​blog-latest-image-1}}, {{​​​​blog-latest-excerpt-1}}, etc. (up to 10) in a template or page to show the most recent posts.
For users
- {{​​​​blog-latest-title-N}}: title (N=1 = newest, 2 = second, … up to 10)
- {{​​​​blog-latest-image-N}}: featured image URL
- {{​​​​blog-latest-excerpt-N}}: excerpt from post body
- {{​​​​blog-latest-date-N}}: short date (e.g. April 15, 2020)
- {{​​​​blog-latest-date-long-N}}: long formatted date
- {{​​​​blog-latest-url-N}}: link to the post
- Ideal for a “Blog” block in the footer or sidebar of an imported ZIP theme.

Why
- Customize the footer without manually copying post titles and images.

Technical notes
- lw_blog_apply_latest_tokens() in blog.php, invoked from lw_blog_apply_tokens() on templates and pages.
v1.0.442026-08-07 12:10:34Theme contact: error messages and Subject fieldZIP theme contact forms again show the actual error message (captcha, missing fields, etc.) and the theme Subject field is supported.
For users
- After a failed send, the specific message appears (e.g. wrong captcha) instead of the generic “Could not send your message.”
- Theme Subject fields (e.g. msg_subject, placeholder or label “Subject”) are stored and included in notification email.
- Fields without a name attribute but with placeholder/label (Your name, Your email…) are detected on import and render.

Why
- lw_contact_form_html() cleared the session flash before theme forms could display it.
- Some themes name the subject field differently than subject.

Technical notes
- public_render.php: lw_contact_form_html() only when {{​​​​contact_form}} is present.
- contact_forms.php: msg_subject alias, placeholder/label detection, name/email fallbacks.
v1.0.432026-08-07 12:04:45Fix HTTP 500 on ZIP theme contact pagesImported “Contact us” pages no longer crash when the Send button sits inside the theme grid (Bootstrap, etc.).
For users
- Custom contact pages from imported themes render again with captcha and Messages inbox delivery.
- Before the fix, some layouts (e.g. Bootstrap grid forms) returned HTTP 500.

Why
- When wiring the theme form, the captcha slot was inserted at the wrong DOM level if the submit control was not a direct child of <form>.

Technical notes
- contact_forms.php: lw_contact_wire_form_element() inserts the captcha slot via the submit button’s immediate parent instead of form->insertBefore() on a nested node.
v1.0.422026-08-07 09:41:46Customizable CDS shop pages (shells and tokens)Like the blog, you can pick CMS pages as shells for the shop, categories, product pages, cart and orders, then place granular tokens (title, price, image, list, etc.).
For users
- In Site settings → CentreDeService.NET, “Shop shell pages”, map a CMS page to each screen type (/boutique/, category, product, cart, order).
- Without a shell, the default CDS render is unchanged.
- On a product shell: {{​​​​cds_product_title}}, {{​​​​cds_product_image}}, {{​​​​cds_product_price}}, {{​​​​cds_product_desc}}, {{​​​​cds_product_add_cart}}, or {{​​​​cds_product}} for the full card.
- On list / category: {{​​​​cds_shop_list}} (full block), or {{​​​​cds_shop_categories}}, {{​​​​cds_shop_products}}, {{​​​​cds_shop_pager}}, {{​​​​cds_category_title}}.
- Cart / order: {{​​​​cds_cart}}, {{​​​​cds_order}}, {{​​​​cds_cart_count}}.

Why
- Let the shop layout match the site theme, following the blog token pattern.

Technical notes
- Shells: cds_shop_*_page_uid; lw_cds_resolve_shell_page in lw_cds_try_serve.
- Tokens: lw_cds_apply_shop_field_tokens + context in lw_cds_apply_tokens.
v1.0.412026-08-07 09:03:11ZIP theme contact forms wired to the CMSContact forms already present in an imported theme can send messages through the lw-admin contact engine without replacing the theme design. Detection is automatic on import; you can also force it with data-lw-contact="1".
For users
- A theme contact form (classes / mailto / name-email-message fields) is wired to the Messages inbox and notification email.
- The form’s look (theme HTML/CSS) is preserved.
- Manual marker: data-lw-contact="1" forces binding; data-lw-contact="0" excludes it.
- Captcha and success/error messages work like {{​​​​contact_form}}.

Why
- Avoid replacing a polished theme form with the generic {{​​​​contact_form}} markup.

Technical notes
- lw_contact_wire_form_html (import); lw_contact_finalize_bound_forms (render); field aliases in lw_contact_submit.
v1.0.40 Package2026-08-06 13:07:30ludiWARE 1.0.40 — installation packageFull public distribution (ZIP + tar.gz) with installer. Includes recent work: blog (tokens, category URLs, subcategories), CMS 404 page, global media library, menus / ZIP import, and display fixes.
For users
- Downloadable package to install or update ludiWARE.
- Archives: ludiware-1.0.40.tar.gz and ludiware-1.0.40.zip
- Repo: https://repo.ludiware.com/releases/1.0.40/
- Includes /install/ wizard (database, schema, admin account)

Notable since last distribution
- Blog: author / long date / time / comments / categories tokens; /blogue/category/subcategory/slug URLs; admin subcategories; French comment agreement
- Designated CMS 404 page + badge; ZIP import (chrome, mega-menus, 404 detect)
- Global media library and folders; active menus; header dedupe

Why
- Ship an installable package aligned with the current CMS version.

Technical notes
- OSS export (no secrets, no factory api/admin); VersionLog FileName points to the public tar.gz.

Télécharger le package

v1.0.392026-08-06 13:01:02Singular “commentaire” for 0 or 1 commentIn the French blog post list, “0 commentaire” and “1 commentaire” (no trailing s) are shown; the plural starts at 2.
For users
- Post card meta: correct French agreement for commentaire (singular for 0/1).

Why
- “0 commentaires” was incorrect in French.

Technical notes
- lw_blog_format_comments_count: singular when count <= 1 (FR).
v1.0.382026-08-06 13:00:31Easier blog subcategories in adminIn lw-admin, each category has a button to add a subcategory. The Parent category field is more prominent, with a tree-style list.
For users
- Categories list: diagram icon creates a subcategory already linked to the right parent.
- Form: parent field first, help about /blogue/parent/child/… URLs.
- “Subcategory” badge and Parent column in the table.

Why
- Hierarchy already existed in the database but was too easy to miss in the UI.

Technical notes
- blogcats.php (?new=1&parent=uid); blog.cat_* i18n keys; category cache bust.
v1.0.372026-08-06 12:51:12Blog URLs with nested categoriesPosts are now available at /blogue/category/subcategory/post-slug. Old /blogue/slug addresses redirect to the new URL automatically.
For users
- Post URL: /blogue/{category}/{subcategory}/{slug} from the category tree.
- No category: /blogue/{slug} as before.
- Category lists: /blogue/{category}/{subcategory} (legacy /blogue/categorie/… redirects).
- List links, comments, sitemap and admin use the new structure.

Why
- Mirror the category tree in the URL for clearer SEO and navigation.

Technical notes
- lw_blog_post_url / lw_blog_post_path_extra; path resolution in lw_blog_try_serve; 301 redirects.
v1.0.362026-08-06 12:48:37New blog tokens (author, date, comments…)Article templates can show the comment count, author, a long date, publish time, and the categories list. An Author field was added when editing posts.
For users
- New tokens: {{​​​​blog_comments_count}} (number only), {{​​​​blog_author}}, {{​​​​blog_date_long}} (e.g. Thursday, September 3, 2024), {{​​​​blog_time}} (HH:MM), {{​​​​blog_categories}} (published categories list).
- {{​​​​blog_date}} stays YYYY-MM-DD.
- “Author” field on create/edit, used by {{​​​​blog_author}}.

Why
- Richer article layouts without hard-coded HTML.

Technical notes
- author_name column; lw_blog_format_date_long / lw_blog_render_categories_token_list helpers; tokens documented in templates.php.
v1.0.352026-08-06 11:32:25CMS 404 page: fixed display + badgeThe page set as 404 now renders correctly (including on draft sites / preview). The pages list shows a “404” badge like the home badge. ZIP imports auto-detect 404 error pages.
For users
- When you check “Use as 404 page”, unknown URLs show that themed page instead of the generic dark 404.
- This also works in preview and while the site is still a draft.
- Pages list: orange “404” badge next to status, like the Home badge.
- New ZIP imports: a page named 404 / not-found is assigned automatically.

Why
- 404 page rendering ignored preview mode and rejected draft sites (“Site not published”), falling back to the generic page.

Technical notes
- lw_public_site_404(..., $preview); force preview render when site is draft; pages.badge_404; auto page_404_page_uid on ZIP import.
v1.0.342026-08-06 11:26:54ZIP import: no duplicate header in page contentWhen importing a template, the header (and similar wrappers) is removed from page content once it lives in the global header. Already-imported sites are cleaned on view.
For users
- Imported pages no longer keep a copy of the menu/header in their content when global chrome is active.
- Templates without a <header> tag (e.g. #header / .header-area) are supported too.

Why
- Stripping was too strict (majority vote, non-semantic wrappers ignored), leaving leftovers in page HTML.

Technical notes
- Structural detection + normalized affix (ignore active); broader DOM strip/dedupe; public render cleanup.
v1.0.332026-08-06 11:16:07Menu: current item highlighted correctlyOn sites (including imported templates), the active menu item follows the page being viewed instead of staying stuck on Home.
For users
- Visiting About (or another page) highlights that item, not Home.
- Parents of an active submenu item stay highlighted too.

Why
- Import copied the homepage’s active class into the CMS menu and never recalculated it from the URL.

Technical notes
- Menu render strips imported active/current classes, marks by page_uid or current path, aria-current=page.
v1.0.322026-08-06 11:00:39Fix media “New folder” fieldChoosing “New folder” in the media library correctly shows the name field again, including after in-app navigation.
For users
- The text field under “New folder” appears reliably when selected.

Why
- The script did not rebind after app-shell fragment navigation.

Technical notes
- Event delegation + re-init on lw:fragment-loaded (lw-media-folder.js v2).
v1.0.312026-08-06 10:50:19Global media library and foldersUpload shared images (logos, etc.) once under Library → Global media and reuse them on every site. Folder selection on upload lists existing folders or “New folder”.
For users
- New Library → Global media section for shared image upload and management.
- On a site media page, the Global tab lists those files read-only (copy URL); platform admins get a Manage link.
- On upload/edit, Folder is a dropdown (none / existing / New folder + text field).

Why
- Avoid re-uploading the same logo on every site.
- Make folder tagging clearer without retyping names.

Technical notes
- lw_media.site_id NULL = global; files under uploads/global/; single reference (no per-site copy).
v1.0.302026-08-06 09:59:30ZIP import: mega-menus preservedWhen importing a ZIP template, rich mega-menu panels (columns, images, CTAs) and Bootstrap dropdown attributes are kept and rendered correctly.
For users
- Templates with mega-menus (full-width panels, grids, images) keep their look after import.
- Bootstrap dropdowns keep their options (data-bs-toggle, etc.).
- Items with a mega panel show an HTML field in Menus for edits (until the mega-menu extension).

Why
- Import only read nested <ul> lists; <div class="dropdown-menu"> panels were dropped when tokenizing {{​​​​menu:…}}.

Technical notes
- New item fields: panel_html, link_attrs, label_html; harvest detection; render anchor+panel; URL rewrite on persist.
v1.0.292026-08-06 09:42:25Fix header/footer save (duplication)Saving header and footer on a ZIP template no longer duplicates the footer under the copyright bar.
For users
- Saving “Header & footer” no longer leaves a second unstyled footer.
- Sites already affected are fixed on view (and permanently when you save chrome again).

Why
- The parser used the first inner </div> of the footer as the block end, then appended the remainder after the footer.

Technical notes
- after_footer extracted via DOM; only script/style/link/noscript kept; public render repair.
content is replaced by the version list (styles and safe text). Why - The VersionLog module was only loaded in lw-admin; on index.php (public front), lw_versionlog_prepare_public_html() was missing and the token stayed literal. Technical - require versionlog.php in www/index.php before public_render.php.
v1.0.582026-08-08 11:07:13Public version history: CMS tokens shown as plain textOn the ludiware.com History page, mentions like {{​account_login}}, {{​menu:main}}, etc. in VersionLog entries display as text instead of injecting forms or menus.
For visitors
- History page (/historique/): version title, description and details show cited tokens as documentation, with no login form or menu injected mid-sentence.

Why
- VersionLog content is rendered via a PHP snippet then processed by the CMS token engine; example {{​account_login}} was executed as a real token.

Technical
- Native 

Platform version history (newest first).

v1.2.12026-08-09 16:47:35Extensible My account and classifieds lightboxPlugins can add My account tabs (e.g. My listings). Public pages now inject the classifieds gallery script at the end of the HTML.
For users
- My account: extensions can register new tabs via the CMS (?tab=… URLs).
- Classifieds 1.2.12: “My listings” tab with edit, delete, and mark as sold.
- Ad photo lightbox: works on CMS token pages too (not only /classifieds/… routes).

Why this change
- Keep listing management in My account alongside profile settings.
- Fix the gallery when ad HTML is rendered inside a site page without the plugin front router.

Technical notes
- CMS filters: public_account_tabs, public_account_tab_panels, public_account_post_actions, public_accounts_handle_post, public_page_html.
- Classifieds plugin: sold status, owner actions, defer gallery JS v4.
v1.2.0 Package2026-08-09 15:29:10ludiWARE 1.2.0 — public profiles and member identityMinor release 1.2.0: full install packages (ZIP + tar.gz), public member profiles, clickable names site-wide, unified activity history on profiles, and republished Forums / Classifieds plugins.
For users
- Download: ludiware-1.2.0.tar.gz + ludiware-1.2.0.zip
- Repo: https://repo.ludiware.com/releases/1.2.0/
- Includes /install/ wizard

CMS highlights (since 1.1.x)
- Public member profile: /membre/{uid} (avatar, name, member since)
- Member names link to profiles (blog, account strip, extensions)
- Activity history on profile: blog comments, forum topics/replies, classified ads and comments
- `public_member_profile_activity` filter for extensions

Republished MarketPlace plugins
- Forums 1.0.18 (profile links + forum activity)
- Classifieds 1.2.9 (linked comments, listing activity)

Technical notes
- OSS export without factory secrets
- VersionLog FileName → public tar.gz on repo.ludiware.com

Télécharger le package

v1.1.142026-08-09 15:26:40Activity history on public profileA member’s profile page now shows a unified timeline of their public contributions: blog comments, forum topics and replies, classified ads and ad comments.
For visitors
- “Public activity” section under the profile header (/membre/{uid}).
- Each row: date, action type, clickable title to the content, short excerpt when available.
- Newest first (up to 60 items), mixing blog, forums and active plugins.

For developers / extensions
- New `public_member_profile_activity` filter — return items `{at, kind, label, title, url, excerpt?}`.
- Helpers: `lw_public_accounts_collect_member_activity()`, `lw_public_accounts_render_member_activity_html()`, `lw_public_accounts_member_activity_item()`.
- Blog: `lw_blog_member_public_activity()` (published comments).
- Plugins register sources via the filter (Forums, Classifieds).

Why
- One consolidated view of a member’s public presence instead of isolated per-plugin sections.
v1.1.132026-08-09 15:23:12Member names link to public profileWherever a registered member appears (blog comments, account strip, etc.), their name now links to their public profile page when that profile is visible.
For visitors
- Click a local active member’s name → /membre/{uid} (or /member/{uid} in English).
- Account strip “Signed in as …”: your display name links to your profile.
- Blog post comments: authors tied to a local member account get a profile link.
- Guests, CDS portal users, or authors without a member account: plain text name (unchanged).

For developers / extensions
- Central helpers: `lw_public_accounts_author_context_from_row()`, `lw_public_accounts_resolve_content_author()`, `lw_public_accounts_render_author_name_html()`.
- Shared CSS class `lw-member-profile-link` for profile links.

Why
- Consistent public member identity across the site (blog, forums, classifieds, etc.) following public profiles in 1.1.12.
v1.1.122026-08-09 15:17:27Public profile for registered membersEach locally registered site member gets a public profile page with avatar and display name. Extensions can append content (e.g. published classifieds).
For visitors
- Public URL: /membre/{uid} (FR) or /member/{uid} (EN) — avatar, display name, member since date.
- Profiles are shown only for active local member accounts, not admins or CentreDeService portal users.

For developers / extensions
- New `public_member_profile_html` filter to extend the page (Classifieds plugin lists published ads).
- Helpers: `lw_public_accounts_public_profile_url()`, `lw_public_accounts_user_by_uid_public()`.

Why
- Let visitors see who published content and build a consistent public identity on the site.
v1.1.112026-08-09 14:33:21Standardized alerts for admin and pluginsNew unified alert system: success, error, warning, and info messages are shown consistently in lw-admin and on the public site. Plugins can contribute through dedicated hooks.
For users
- Admin confirmations and errors (e.g. “Listing deleted”, “Settings saved”) now appear at the top of the page in a consistent banner.
- On the public site, plugins can show user messages with the same visual style.

Why
- Each module and plugin handled its own alerts (different variables, query strings, custom CSS), causing duplication and inconsistency.

Technical notes
- New module lw-admin/functions/flash.php: lw_flash_add(), lw_flash_redirect(), lw_flash_render_html(), lw_public_flash_html().
- admin_flash and public_flash hooks for extensions.
- Backward compatible with $lwFlash and $lwPageFlashError.
- Shared lw-flash.css for admin/public.
- Classifieds plugin migrated as an example (v1.2.2).
v1.1.102026-08-08 18:52:20Portable site-to-site configurationconfig.php no longer holds secrets or factory domain settings: database, emails, and environment overrides live in config.local.php; hostname and defaults are inferred automatically.
For users
- Copy the CMS between sites without editing config.php: only config.local.php (or the /install/ wizard) needs to match the new host.
- Cookies and site name follow the real domain when HTTPpath / COOKIEpath are omitted.

Why
- config.php mixed MySQL credentials, the ludiware.com domain, and factory emails, making every client deploy error-prone.

Technical notes
- lw_config_detect_http_host() + lw_config_apply_runtime_defaults() after config.local.php.
- MySQL connects only when DBhost / DBname / DBusername are set.
- Updated config.local.example.php and installer (domain optional).
v1.1.92026-08-08 17:58:54Modal sign-in fix (POST fields + SQL)Sign-in from the modal now reliably sends email and password (POST to the current page, fields read explicitly) and works on hosts without mysqlnd.
For users
- The login/register modal posts to the page you are on (not only /sign-in/), avoiding silent failures.
- If the account has no password (Google/Facebook admin sign-in), a clear message appears instead of “invalid email or password”.

Why
- On some themes, fields did not always have a name attribute when FormData ran; on some hosts, user SQL reads failed without mysqlnd.

Technical notes
- lw-account-forms.js v4: explicit buildFormData; action = current page in modals.
- lw_public_accounts_stmt_fetch_one_assoc(); modal forms: post_url injected at render.
v1.1.82026-08-08 17:51:46Admin recognition on public site + cookie domainAn administrator signed into lw-admin is recognized again on the public site (My account header). Cookies align with the site’s actual domain (e.g. dormezcheznous.com).
For users
- If you are signed into lw-admin on the same domain as the public site, the header shows “My account” without using the modal again.
- After signing in via the modal, the public session persists.
- Check config.local.php: COOKIEpath must match the site domain (not ludiware.com if the site uses another hostname).

Why
- Admin cookies were sometimes set for ludiware.com while the site runs on a custom domain; the public site never received them. Modal sign-in could also fail when mismatched admin cookies interfered.

Technical notes
- lw_cookie_domain() uses current HTTP host when it differs from COOKIEpath.
- lw_public_accounts_auth_from_cookies() + member session sync.
- Auth bootstrap on public index.php.
v1.1.72026-08-08 17:31:50Conditional account header (snippets / tokens)Show “Sign in” or “My account” in the header based on session state, using an HTML snippet and {{​​​​account_if_guest}} / {{​​​​account_if_logged_in}} tokens.
For users
- In an HTML snippet (or layout): wrap the Sign in button with {{​​​​account_if_guest}}…{{​​​​/account_if_guest}} and My account with {{​​​​account_if_logged_in}}…{{​​​​/account_if_logged_in}}.
- Useful tokens: {{​​​​account_account_url}}, {{​​​​account_user_name}}, {{​​​​account_logout_url}}, {{​​​​account_logged_in}} (1 or empty).
- Put {{​​​​snippet:your_key}} in the layout header.
- Built-in alternative: {{​​​​account_strip}} (lw-admin banner).
- PHP snippets: $lw_db variable + lw_public_accounts_viewer().

Why
- Imported themes like DormezChezNous need a custom Bootstrap/modal button, not the generic banner.

Technical notes
- lw_public_accounts_apply_conditional_blocks() in apply_tokens; $lw_db exposed to PHP snippets.
v1.1.62026-08-08 17:25:08Account modal AJAX fix (Homelengo themes)Sign-in from a modal did not react on click: the account script now intercepts the click before theme scripts, shows errors (removes d-none), and shows loading state on the button.
For users
- The “Sign in” button in the modal works again: “…” while sending, visible red error on failure, page reload on success.
- No HTML change needed if data-lw-account and data-lw-account-error are already set.

Why
- Imported themes (Homelengo / DormezChezNous) registered listeners that blocked submit before our script; errors also stayed hidden behind Bootstrap d-none.

Technical notes
- lw-account-forms.js v3: capture click + submit, loaded last before </body>.
- Automatically removes d-none on data-lw-account-error.
v1.1.52026-08-08 17:13:29AJAX sign-in and register (modals)Account forms inside a modal (Bootstrap or similar) can submit without a full page reload: errors show in the modal, and the page refreshes after a successful sign-in.
For users
- If your login/register form is inside a modal (.modal or role="dialog"), submission uses AJAX automatically — no redirect to /sign-in/ that breaks the flow.
- Add an error slot: <div data-lw-account-error></div> in the modal.
- Force or disable: data-lw-account-ajax="1" or "0" on the <form>.
- On success: default is page reload (account menu updates); data-lw-account-on-success="redirect" to go to My account.
- Register captcha refreshes automatically after a failed attempt.

Why
- Sites like DormezChezNous open login/register in popups; a classic POST reloaded the whole page.

Technical notes
- lw-account-forms.js injected when data-lw-account is present.
- JSON responses server-side (lw_public_accounts_handle_post); index.php hook for POST from any page.
v1.1.42026-08-08 16:54:04Custom account forms (data-lw-account)Use your own HTML sign-in and register forms in the theme: the engine wires them automatically and exposes error messages via tokens or dedicated slots.
For users
- Form marker: data-lw-account="login" or "register" (also forgot, reset, profile, security).
- Fields: data-lw-account-field="email|password|…" or auto-detect via id/name/placeholder (like contact).
- Errors: {{​​​​account_error_text}} in your HTML, or <div data-lw-account-error></div>.
- Success: {{​​​​account_success_text}} or data-lw-account-success.
- Replace {{​​​​account_login}} with your markup on the /connexion/ shell page if you do not want the default lw-admin form.
- Register: <div class="lw-account-captcha-slot"></div> for captcha.
- Optional OAuth: <div data-lw-account-oauth></div>.

Why
- Imported themes like DormezChezNous keep their Bootstrap design without duplicating account logic.

Technical notes
- account_forms.php (same pattern as data-lw-contact).
- Injects CSRF + lw_account_action; POST action targets /connexion/, /register/, etc.
v1.1.32026-08-08 12:47:55HTML editors with syntax highlighting and tabsAll admin HTML and code fields now have syntax highlighting and Tab indentation (4 spaces), including TinyMCE’s source code view.
For users
- Raw HTML fields (header, footer, snippets, templates, custom CSS, etc.): line numbers, highlighting, Tab to indent.
- TinyMCE rich editor: the source code button opens the same highlighted experience.
- Imported themes: direct HTML editing with highlighting.

Why
- Easier markup editing without an external IDE.
- Tab inserts consistent indentation; Shift+Tab outdents.

Technical notes
- lw-code-editor.js module (CodeMirror 5 via CDN).
- html, css, and php modes per field.
- App-shell navigation compatible (reinit after page change).
v1.1.22026-08-08 11:37:45In-app CMS update and footer alertRemote installations show a visible admin footer warning when a newer package is available, and can install the update from Settings → Versions without manually re-uploading files.
For users
- Admin footer: “Update available (vX.Y.Z)” badge when a newer VersionLog package is published on repo.ludiware.com.
- Settings → Versions: banner with “Update now” (automatic download and deploy).
- Preserved local files: config.local.php, config.php (only the Version line is updated), uploads/, storage/, installed extensions.

Why
- Avoid manual FTP/SFTP updates on every hosted site.
- Surface an outdated version (e.g. 1.0.53 vs 1.1.x) without digging through history.

Technical notes
- lw_cms_update_apply(): downloads ZIP/tar.gz from repo.ludiware.com, extracts and copies core files.
- lw_versionlog_check_update() unchanged (30 min cache).
- Settings sidebar badge + chrome alert for managers.
v1.1.12026-08-08 11:30:24Version history: readable tokens and bracesVersionLog entries no longer show raw HTML codes ({): tokens like {{​​​​account_login}} display normally.
For visitors
- History page: CMS token examples show as plain text (visible braces), without double-encoded HTML entities.

Why
- Some VersionLog entries mentioned HTML entities ({) in their text; htmlspecialchars() displayed them literally on screen.

Technical
- lw_versionlog_prepare_display_source(): decode brace entities before zero-width neutralization and lw_e().
v1.1.0 Package2026-08-08 11:28:14ludiWARE 1.1.0 — public distributionMinor release 1.1.0: full install package (ZIP + tar.gz), public OAuth accounts, public version history, contact form prefill, and updated MarketPlace plugins.
For users
- Download: ludiware-1.1.0.tar.gz + ludiware-1.1.0.zip
- Repo: https://repo.ludiware.com/releases/1.1.0/
- Includes /install/ wizard (database, schema, admin account)

Since the 1.0.40 distribution
- Local member accounts: sign-up, login, forgot password, My account (profile / security tabs)
- Google and Facebook OAuth on the public site
- Public header recognizes lw-admin session and OAuth members
- {{​​​​versionlog}} token: version history on the public site
- Contact form: name and email prefilled when signed in
- Bootstrap Icons + admin icon picker
- MarketPlace plugins: FAQ, Testimonials, Gallery, Forms, Booking, Classifieds, Forums

Republished plugins (MarketPlace)
- Forums 1.0.16
- Classifieds 1.0.15

Technical notes
- OSS export without factory secrets; VersionLog FileName → public tar.gz.

Télécharger le package

v1.0.612026-08-08 11:25:48Version history: tokens display normallyExamples like {{​​​​account_login}} in version history show as readable text, without visible HTML entities ({).
For visitors / administrators
- History page and Settings → Versions: cited tokens appear as {{​​​​account_login}}, not as {{​​account_login}}.

Why
- Escaping braces as HTML entities then running htmlspecialchars() double-encoded and showed raw codes on screen.

Technical
- Zero-width space neutralization only (no { entities) in lw_versionlog_format_display_text() and lw_versionlog_shield_public_html().
v1.0.602026-08-08 11:24:31Contact form: name and email prefilled when signed inOn the contact form, Name and Email fields are filled automatically when the visitor is already signed in (local account, lw-admin, or CDS portal).
For users
- {{​​​​contact_form}} and theme ZIP contact forms: Name and Email prefilled when signed in.
- Fields already set in the template are not overwritten.

Why
- Avoid re-entering identity on every contact message.

Sources
- CDS portal (SSO session): full name + contact email.
- Public member account or lw-admin cookie: display_name + lw_users email.

Technical
- lw_contact_prefill_identity(), lw_contact_apply_prefill_to_form(), lw_contact_form_html().
v1.0.592026-08-08 11:20:46{{​​​​versionlog}} token works on the public siteThe {{​​​​versionlog}} token is now recognized on the public site: the History page shows the version list instead of the raw token text.
For visitors
- History page: {{​​​​versionlog}} content is replaced by the version list (styles and safe text).

Why
- The VersionLog module was only loaded in lw-admin; on index.php (public front), lw_versionlog_prepare_public_html() was missing and the token stayed literal.

Technical
- require versionlog.php in www/index.php before public_render.php.
v1.0.582026-08-08 11:07:13Public version history: CMS tokens shown as plain textOn the ludiware.com History page, mentions like {{​​​​account_login}}, {{​​​​menu:main}}, etc. in VersionLog entries display as text instead of injecting forms or menus.
For visitors
- History page (/historique/): version title, description and details show cited tokens as documentation, with no login form or menu injected mid-sentence.

Why
- VersionLog content is rendered via a PHP snippet then processed by the CMS token engine; example {{​​​​account_login}} was executed as a real token.

Technical
- Native {{​​​​versionlog}} / {{​​​​versionlog_list}} token; .lw-vl-* blocks shielded before the token pipeline; HTML entities for {{​​​​ and }} on display.
v1.0.572026-08-08 10:58:52Version history: CMS tokens shown as plain textMentions like {{​​​​account_login}}, {{​​​​menu:main}}, etc. in VersionLog technical details are no longer interpreted as CMS tokens.
For administrators
- Settings → Version history: title, description and full details show tokens literally (documentation), with no forms or injected content.

Why
- VersionLog entries often cite tokens as examples in “Technical detail”; the token engine must not execute them on display.

Technical
- Neutralize {{​​​​ → {{​​​​ + zero-width space on API output and lw-admin client; HTML-escaped display.
v1.0.562026-08-08 10:54:16Public header: lw-admin session recognitionWhen signed into lw-admin, you also appear as a member on the public site (header, My account), consistent with blog comments.
For visitors / administrators
- lw-admin cookies → {{​​​​account_strip}} shows your name and “My account”.
- /account/ works without visiting /login/ again.
- /login/ and /register/ redirect to My account when already recognized.

Identity priority (unchanged for blog when a Facebook session is active)
1. Public member session (login / OAuth)
2. lw-admin cookie

Public sign-out clears the member session only; if lw-admin remains, you stay signed in.
v1.0.552026-08-08 10:38:20Blog and forums: public member identity firstOn the public site, the member session (login / Facebook / Google) now takes precedence over lw-admin cookies for blog comments.
Fixed issue
- Header “Signed in as…” (member session) and blog “Commenting as…” (admin cookies) could show two different people when logged into lw-admin and Facebook on the public site.

Behavior
- Priority: CDS portal → public member (session) → admin staff (lw-admin cookie).
- Blog login hint links to /login/ when local accounts are active (no CDS).

Note
- If Facebook created a second lw_users account (different email from admin), that is expected: two separate profiles. Merge manually or delete the duplicate in Users.
v1.0.542026-08-08 10:11:29OAuth — stable redirect URLThe Google/Facebook callback URL in site settings now uses the site’s public domain (e.g. ludiware.com), not the admin host.
For administrators
- Settings → Member accounts: the “authorized redirect” URL matches the site’s public domain.
- Help note for adding the URI in Facebook Login → Valid OAuth Redirect URIs.

Why
- When opened from the admin panel (different subdomain), the generated URL could differ from the one used on the public site.
v1.0.532026-08-08 10:03:23Google and Facebook sign-in for membersVisitors can sign in or register with Google or Facebook on login and register pages when local accounts are used (no CentreDeService portal). A local member profile is created automatically when needed.
For visitors
- “Sign in with Google” and “Sign in with Facebook” on /login/ and /register/ (FR: /connexion/, /inscription/).
- If the email is not registered yet, a member account is created and the session starts.
- If an account already exists with the same email, the OAuth profile is linked to it.

For administrators
- Site settings → Member accounts: enable providers, OAuth credentials, and redirect URLs to paste into Google Cloud / Facebook Developer.
- Automatically disabled when the CentreDeService portal handles authentication.

Technical
- lw_users google_id / facebook_id columns, oauth_accounts.php module, /oauth/{provider}/callback/ routes.
v1.0.522026-08-08 08:35:18Icon picker — full catalogThe icon picker now shows useful favorites first, then all Bootstrap icons (~1,600) via search.
For administrators
- On open: a grid of favorites (home, commerce, transport, etc.).
- Search: filters the full set of ~1,683 installed Bootstrap Icons.
- Result count and message when the list is truncated.

Fix
- The list was previously capped at 120 icons in alphabetical order (123, alarm…), which felt incomplete.
v1.0.512026-08-08 08:29:09Bootstrap Icons and icon pickerBootstrap Icons now render reliably across the admin with complete font files. A reusable icon picker is available for forms (search, grid, preview).
For administrators
- Bootstrap Icons font files (woff/woff2) installed so existing `bi-*` icons in lw-admin display correctly.
- New reusable icon picker component (`lw_icon_picker_field`) for any admin form.

Usage
- Button with icon preview, name search, clickable grid, and a “No icon” option.
- PHP helpers `lw_bootstrap_icon_names()` and `lw_bootstrap_icon_class()`.

Technical
- Files: `functions/icon_picker.php`, `js/lw-icon-picker.js`, styles in `lw-admin.css`.
v1.0.502026-08-08 07:27:10My account — profile and security tabsThe My account page has two tabs: My information (first name, last name, avatar) and Access & security (email, password). New tokens for ZIP templates.
For users
- My information tab: first name, last name, avatar upload.
- Access & security tab: change email and/or password (current password required).

ZIP tokens
- {{​​​​account_panel}}: full panel with tabs.
- {{​​​​account_tabs}}, {{​​​​account_profile}}, {{​​​​account_security}}: custom layout.
- {{​​​​account_avatar}}, {{​​​​account_avatar_url}}, {{​​​​account_first_name}}, {{​​​​account_last_name}}, {{​​​​account_email}}.
- {{​​​​account_profile_url}}, {{​​​​account_security_url}}: direct links to each tab.

Technical notes
- lw_users.avatar_path column, files in uploads/users/, public session synced after updates.
v1.0.492026-08-08 07:17:18Public accounts unified in lw_usersRegistration, sign-in and forgot password on the public site now use the lw_users table (same as lw-admin). Only accounts with admin access can open lw-admin.
For users
- Same email and password everywhere: admin or visitor registered at /register/.
- Accounts created on the public site have the user role and cannot access lw-admin.
- Administrators can also sign in at /login/ with their usual credentials.

Why
- Removes the mistaken dual lw_site_members / lw_users system.

Technical notes
- public_accounts.php: auth, registration and reset on lw_users; per-site public session.
- auth.php unchanged: can_access_admin required for lw-admin.
- Obsolete lw_site_members table can be dropped in the database (DROP TABLE).
v1.0.482026-08-08 07:11:33Public sign-in with an administrator accountSite administrators can sign in on the public site (/login/) using the same email and password as lw-admin, without a separate registration.
For users
- At /login/, a global administrator or a user assigned to the site is accepted with lw-admin credentials.
- The first sign-in automatically creates the local member profile for that site; later sign-ins reuse it.

Why
- Before this fix, only accounts registered via /register/ (lw_site_members) were recognized; the first admin saw “Invalid email or password.”

Technical notes
- lw_users → lw_site_members bridge in lw_public_accounts_login(): admin password check, site access (global_admin or local_admin site member), hash sync and member session.
v1.0.472026-08-08 06:52:34Local member accounts on the public siteSites without a CentreDeService portal can offer registration, sign-in, forgot password and a member area on the public site, with tokens for ZIP templates and CMS shell pages.
For users
- Register at /register/ with captcha and password confirmation.
- Sign in at /login/, recover at /forgot-password/, reset via email link.
- “My account” when signed in; {{​​​​account_strip}} banner in the header.

For administrators
- Settings → Member accounts: CMS shells and “Generate system pages”.
- Menu editor: Add member (Sign in, Forgot password, Register, My account) when CDS is off.
- ZIP tokens: {{​​​​account_login}}, {{​​​​account_register}}, {{​​​​account_panel}}, {{​​​​account_forgot}}, {{​​​​account_reset}} and related URLs.

Why
- Let standalone ludiWARE sites (no CDS) offer visitor accounts for comments, gated content or future personalization.

Technical notes
- lw_site_members table, session CSRF, registration captcha separate from contact, try_serve routes, public_render apply_tokens.
v1.0.462026-08-07 12:59:32Contact captcha: fix valid answers rejectedWhen a page or template has multiple contact forms, the same security question is shown everywhere and a correct answer is accepted.
For users
- The “What is X + Y?” captcha is the same on all contact forms on a page.
- A correct answer is no longer rejected with “Incorrect security check.”

Why
- Each form could get a different question while the session stores only one expected answer (content and template finalized separately).

Technical notes
- lw_contact_captcha_issue() reuses a valid session challenge; contact finalize runs once on the full HTML (public_render.php).
v1.0.452026-08-07 12:15:48Blog tokens: latest posts (footer / sidebar)Use {{​​​​blog-latest-title-1}}, {{​​​​blog-latest-image-1}}, {{​​​​blog-latest-excerpt-1}}, etc. (up to 10) in a template or page to show the most recent posts.
For users
- {{​​​​blog-latest-title-N}}: title (N=1 = newest, 2 = second, … up to 10)
- {{​​​​blog-latest-image-N}}: featured image URL
- {{​​​​blog-latest-excerpt-N}}: excerpt from post body
- {{​​​​blog-latest-date-N}}: short date (e.g. April 15, 2020)
- {{​​​​blog-latest-date-long-N}}: long formatted date
- {{​​​​blog-latest-url-N}}: link to the post
- Ideal for a “Blog” block in the footer or sidebar of an imported ZIP theme.

Why
- Customize the footer without manually copying post titles and images.

Technical notes
- lw_blog_apply_latest_tokens() in blog.php, invoked from lw_blog_apply_tokens() on templates and pages.
v1.0.442026-08-07 12:10:34Theme contact: error messages and Subject fieldZIP theme contact forms again show the actual error message (captcha, missing fields, etc.) and the theme Subject field is supported.
For users
- After a failed send, the specific message appears (e.g. wrong captcha) instead of the generic “Could not send your message.”
- Theme Subject fields (e.g. msg_subject, placeholder or label “Subject”) are stored and included in notification email.
- Fields without a name attribute but with placeholder/label (Your name, Your email…) are detected on import and render.

Why
- lw_contact_form_html() cleared the session flash before theme forms could display it.
- Some themes name the subject field differently than subject.

Technical notes
- public_render.php: lw_contact_form_html() only when {{​​​​contact_form}} is present.
- contact_forms.php: msg_subject alias, placeholder/label detection, name/email fallbacks.
v1.0.432026-08-07 12:04:45Fix HTTP 500 on ZIP theme contact pagesImported “Contact us” pages no longer crash when the Send button sits inside the theme grid (Bootstrap, etc.).
For users
- Custom contact pages from imported themes render again with captcha and Messages inbox delivery.
- Before the fix, some layouts (e.g. Bootstrap grid forms) returned HTTP 500.

Why
- When wiring the theme form, the captcha slot was inserted at the wrong DOM level if the submit control was not a direct child of <form>.

Technical notes
- contact_forms.php: lw_contact_wire_form_element() inserts the captcha slot via the submit button’s immediate parent instead of form->insertBefore() on a nested node.
v1.0.422026-08-07 09:41:46Customizable CDS shop pages (shells and tokens)Like the blog, you can pick CMS pages as shells for the shop, categories, product pages, cart and orders, then place granular tokens (title, price, image, list, etc.).
For users
- In Site settings → CentreDeService.NET, “Shop shell pages”, map a CMS page to each screen type (/boutique/, category, product, cart, order).
- Without a shell, the default CDS render is unchanged.
- On a product shell: {{​​​​cds_product_title}}, {{​​​​cds_product_image}}, {{​​​​cds_product_price}}, {{​​​​cds_product_desc}}, {{​​​​cds_product_add_cart}}, or {{​​​​cds_product}} for the full card.
- On list / category: {{​​​​cds_shop_list}} (full block), or {{​​​​cds_shop_categories}}, {{​​​​cds_shop_products}}, {{​​​​cds_shop_pager}}, {{​​​​cds_category_title}}.
- Cart / order: {{​​​​cds_cart}}, {{​​​​cds_order}}, {{​​​​cds_cart_count}}.

Why
- Let the shop layout match the site theme, following the blog token pattern.

Technical notes
- Shells: cds_shop_*_page_uid; lw_cds_resolve_shell_page in lw_cds_try_serve.
- Tokens: lw_cds_apply_shop_field_tokens + context in lw_cds_apply_tokens.
v1.0.412026-08-07 09:03:11ZIP theme contact forms wired to the CMSContact forms already present in an imported theme can send messages through the lw-admin contact engine without replacing the theme design. Detection is automatic on import; you can also force it with data-lw-contact="1".
For users
- A theme contact form (classes / mailto / name-email-message fields) is wired to the Messages inbox and notification email.
- The form’s look (theme HTML/CSS) is preserved.
- Manual marker: data-lw-contact="1" forces binding; data-lw-contact="0" excludes it.
- Captcha and success/error messages work like {{​​​​contact_form}}.

Why
- Avoid replacing a polished theme form with the generic {{​​​​contact_form}} markup.

Technical notes
- lw_contact_wire_form_html (import); lw_contact_finalize_bound_forms (render); field aliases in lw_contact_submit.
v1.0.40 Package2026-08-06 13:07:30ludiWARE 1.0.40 — installation packageFull public distribution (ZIP + tar.gz) with installer. Includes recent work: blog (tokens, category URLs, subcategories), CMS 404 page, global media library, menus / ZIP import, and display fixes.
For users
- Downloadable package to install or update ludiWARE.
- Archives: ludiware-1.0.40.tar.gz and ludiware-1.0.40.zip
- Repo: https://repo.ludiware.com/releases/1.0.40/
- Includes /install/ wizard (database, schema, admin account)

Notable since last distribution
- Blog: author / long date / time / comments / categories tokens; /blogue/category/subcategory/slug URLs; admin subcategories; French comment agreement
- Designated CMS 404 page + badge; ZIP import (chrome, mega-menus, 404 detect)
- Global media library and folders; active menus; header dedupe

Why
- Ship an installable package aligned with the current CMS version.

Technical notes
- OSS export (no secrets, no factory api/admin); VersionLog FileName points to the public tar.gz.

Télécharger le package

v1.0.392026-08-06 13:01:02Singular “commentaire” for 0 or 1 commentIn the French blog post list, “0 commentaire” and “1 commentaire” (no trailing s) are shown; the plural starts at 2.
For users
- Post card meta: correct French agreement for commentaire (singular for 0/1).

Why
- “0 commentaires” was incorrect in French.

Technical notes
- lw_blog_format_comments_count: singular when count <= 1 (FR).
v1.0.382026-08-06 13:00:31Easier blog subcategories in adminIn lw-admin, each category has a button to add a subcategory. The Parent category field is more prominent, with a tree-style list.
For users
- Categories list: diagram icon creates a subcategory already linked to the right parent.
- Form: parent field first, help about /blogue/parent/child/… URLs.
- “Subcategory” badge and Parent column in the table.

Why
- Hierarchy already existed in the database but was too easy to miss in the UI.

Technical notes
- blogcats.php (?new=1&parent=uid); blog.cat_* i18n keys; category cache bust.
v1.0.372026-08-06 12:51:12Blog URLs with nested categoriesPosts are now available at /blogue/category/subcategory/post-slug. Old /blogue/slug addresses redirect to the new URL automatically.
For users
- Post URL: /blogue/{category}/{subcategory}/{slug} from the category tree.
- No category: /blogue/{slug} as before.
- Category lists: /blogue/{category}/{subcategory} (legacy /blogue/categorie/… redirects).
- List links, comments, sitemap and admin use the new structure.

Why
- Mirror the category tree in the URL for clearer SEO and navigation.

Technical notes
- lw_blog_post_url / lw_blog_post_path_extra; path resolution in lw_blog_try_serve; 301 redirects.
v1.0.362026-08-06 12:48:37New blog tokens (author, date, comments…)Article templates can show the comment count, author, a long date, publish time, and the categories list. An Author field was added when editing posts.
For users
- New tokens: {{​​​​blog_comments_count}} (number only), {{​​​​blog_author}}, {{​​​​blog_date_long}} (e.g. Thursday, September 3, 2024), {{​​​​blog_time}} (HH:MM), {{​​​​blog_categories}} (published categories list).
- {{​​​​blog_date}} stays YYYY-MM-DD.
- “Author” field on create/edit, used by {{​​​​blog_author}}.

Why
- Richer article layouts without hard-coded HTML.

Technical notes
- author_name column; lw_blog_format_date_long / lw_blog_render_categories_token_list helpers; tokens documented in templates.php.
v1.0.352026-08-06 11:32:25CMS 404 page: fixed display + badgeThe page set as 404 now renders correctly (including on draft sites / preview). The pages list shows a “404” badge like the home badge. ZIP imports auto-detect 404 error pages.
For users
- When you check “Use as 404 page”, unknown URLs show that themed page instead of the generic dark 404.
- This also works in preview and while the site is still a draft.
- Pages list: orange “404” badge next to status, like the Home badge.
- New ZIP imports: a page named 404 / not-found is assigned automatically.

Why
- 404 page rendering ignored preview mode and rejected draft sites (“Site not published”), falling back to the generic page.

Technical notes
- lw_public_site_404(..., $preview); force preview render when site is draft; pages.badge_404; auto page_404_page_uid on ZIP import.
v1.0.342026-08-06 11:26:54ZIP import: no duplicate header in page contentWhen importing a template, the header (and similar wrappers) is removed from page content once it lives in the global header. Already-imported sites are cleaned on view.
For users
- Imported pages no longer keep a copy of the menu/header in their content when global chrome is active.
- Templates without a <header> tag (e.g. #header / .header-area) are supported too.

Why
- Stripping was too strict (majority vote, non-semantic wrappers ignored), leaving leftovers in page HTML.

Technical notes
- Structural detection + normalized affix (ignore active); broader DOM strip/dedupe; public render cleanup.
v1.0.332026-08-06 11:16:07Menu: current item highlighted correctlyOn sites (including imported templates), the active menu item follows the page being viewed instead of staying stuck on Home.
For users
- Visiting About (or another page) highlights that item, not Home.
- Parents of an active submenu item stay highlighted too.

Why
- Import copied the homepage’s active class into the CMS menu and never recalculated it from the URL.

Technical notes
- Menu render strips imported active/current classes, marks by page_uid or current path, aria-current=page.
v1.0.322026-08-06 11:00:39Fix media “New folder” fieldChoosing “New folder” in the media library correctly shows the name field again, including after in-app navigation.
For users
- The text field under “New folder” appears reliably when selected.

Why
- The script did not rebind after app-shell fragment navigation.

Technical notes
- Event delegation + re-init on lw:fragment-loaded (lw-media-folder.js v2).
v1.0.312026-08-06 10:50:19Global media library and foldersUpload shared images (logos, etc.) once under Library → Global media and reuse them on every site. Folder selection on upload lists existing folders or “New folder”.
For users
- New Library → Global media section for shared image upload and management.
- On a site media page, the Global tab lists those files read-only (copy URL); platform admins get a Manage link.
- On upload/edit, Folder is a dropdown (none / existing / New folder + text field).

Why
- Avoid re-uploading the same logo on every site.
- Make folder tagging clearer without retyping names.

Technical notes
- lw_media.site_id NULL = global; files under uploads/global/; single reference (no per-site copy).
v1.0.302026-08-06 09:59:30ZIP import: mega-menus preservedWhen importing a ZIP template, rich mega-menu panels (columns, images, CTAs) and Bootstrap dropdown attributes are kept and rendered correctly.
For users
- Templates with mega-menus (full-width panels, grids, images) keep their look after import.
- Bootstrap dropdowns keep their options (data-bs-toggle, etc.).
- Items with a mega panel show an HTML field in Menus for edits (until the mega-menu extension).

Why
- Import only read nested <ul> lists; <div class="dropdown-menu"> panels were dropped when tokenizing {{​​​​menu:…}}.

Technical notes
- New item fields: panel_html, link_attrs, label_html; harvest detection; render anchor+panel; URL rewrite on persist.
v1.0.292026-08-06 09:42:25Fix header/footer save (duplication)Saving header and footer on a ZIP template no longer duplicates the footer under the copyright bar.
For users
- Saving “Header & footer” no longer leaves a second unstyled footer.
- Sites already affected are fixed on view (and permanently when you save chrome again).

Why
- The parser used the first inner </div> of the footer as the block end, then appended the remainder after the footer.

Technical notes
- after_footer extracted via DOM; only script/style/link/noscript kept; public render repair.
/

Platform version history (newest first).

v1.2.12026-08-09 16:47:35Extensible My account and classifieds lightboxPlugins can add My account tabs (e.g. My listings). Public pages now inject the classifieds gallery script at the end of the HTML.
For users
- My account: extensions can register new tabs via the CMS (?tab=… URLs).
- Classifieds 1.2.12: “My listings” tab with edit, delete, and mark as sold.
- Ad photo lightbox: works on CMS token pages too (not only /classifieds/… routes).

Why this change
- Keep listing management in My account alongside profile settings.
- Fix the gallery when ad HTML is rendered inside a site page without the plugin front router.

Technical notes
- CMS filters: public_account_tabs, public_account_tab_panels, public_account_post_actions, public_accounts_handle_post, public_page_html.
- Classifieds plugin: sold status, owner actions, defer gallery JS v4.
v1.2.0 Package2026-08-09 15:29:10ludiWARE 1.2.0 — public profiles and member identityMinor release 1.2.0: full install packages (ZIP + tar.gz), public member profiles, clickable names site-wide, unified activity history on profiles, and republished Forums / Classifieds plugins.
For users
- Download: ludiware-1.2.0.tar.gz + ludiware-1.2.0.zip
- Repo: https://repo.ludiware.com/releases/1.2.0/
- Includes /install/ wizard

CMS highlights (since 1.1.x)
- Public member profile: /membre/{uid} (avatar, name, member since)
- Member names link to profiles (blog, account strip, extensions)
- Activity history on profile: blog comments, forum topics/replies, classified ads and comments
- `public_member_profile_activity` filter for extensions

Republished MarketPlace plugins
- Forums 1.0.18 (profile links + forum activity)
- Classifieds 1.2.9 (linked comments, listing activity)

Technical notes
- OSS export without factory secrets
- VersionLog FileName → public tar.gz on repo.ludiware.com

Télécharger le package

v1.1.142026-08-09 15:26:40Activity history on public profileA member’s profile page now shows a unified timeline of their public contributions: blog comments, forum topics and replies, classified ads and ad comments.
For visitors
- “Public activity” section under the profile header (/membre/{uid}).
- Each row: date, action type, clickable title to the content, short excerpt when available.
- Newest first (up to 60 items), mixing blog, forums and active plugins.

For developers / extensions
- New `public_member_profile_activity` filter — return items `{at, kind, label, title, url, excerpt?}`.
- Helpers: `lw_public_accounts_collect_member_activity()`, `lw_public_accounts_render_member_activity_html()`, `lw_public_accounts_member_activity_item()`.
- Blog: `lw_blog_member_public_activity()` (published comments).
- Plugins register sources via the filter (Forums, Classifieds).

Why
- One consolidated view of a member’s public presence instead of isolated per-plugin sections.
v1.1.132026-08-09 15:23:12Member names link to public profileWherever a registered member appears (blog comments, account strip, etc.), their name now links to their public profile page when that profile is visible.
For visitors
- Click a local active member’s name → /membre/{uid} (or /member/{uid} in English).
- Account strip “Signed in as …”: your display name links to your profile.
- Blog post comments: authors tied to a local member account get a profile link.
- Guests, CDS portal users, or authors without a member account: plain text name (unchanged).

For developers / extensions
- Central helpers: `lw_public_accounts_author_context_from_row()`, `lw_public_accounts_resolve_content_author()`, `lw_public_accounts_render_author_name_html()`.
- Shared CSS class `lw-member-profile-link` for profile links.

Why
- Consistent public member identity across the site (blog, forums, classifieds, etc.) following public profiles in 1.1.12.
v1.1.122026-08-09 15:17:27Public profile for registered membersEach locally registered site member gets a public profile page with avatar and display name. Extensions can append content (e.g. published classifieds).
For visitors
- Public URL: /membre/{uid} (FR) or /member/{uid} (EN) — avatar, display name, member since date.
- Profiles are shown only for active local member accounts, not admins or CentreDeService portal users.

For developers / extensions
- New `public_member_profile_html` filter to extend the page (Classifieds plugin lists published ads).
- Helpers: `lw_public_accounts_public_profile_url()`, `lw_public_accounts_user_by_uid_public()`.

Why
- Let visitors see who published content and build a consistent public identity on the site.
v1.1.112026-08-09 14:33:21Standardized alerts for admin and pluginsNew unified alert system: success, error, warning, and info messages are shown consistently in lw-admin and on the public site. Plugins can contribute through dedicated hooks.
For users
- Admin confirmations and errors (e.g. “Listing deleted”, “Settings saved”) now appear at the top of the page in a consistent banner.
- On the public site, plugins can show user messages with the same visual style.

Why
- Each module and plugin handled its own alerts (different variables, query strings, custom CSS), causing duplication and inconsistency.

Technical notes
- New module lw-admin/functions/flash.php: lw_flash_add(), lw_flash_redirect(), lw_flash_render_html(), lw_public_flash_html().
- admin_flash and public_flash hooks for extensions.
- Backward compatible with $lwFlash and $lwPageFlashError.
- Shared lw-flash.css for admin/public.
- Classifieds plugin migrated as an example (v1.2.2).
v1.1.102026-08-08 18:52:20Portable site-to-site configurationconfig.php no longer holds secrets or factory domain settings: database, emails, and environment overrides live in config.local.php; hostname and defaults are inferred automatically.
For users
- Copy the CMS between sites without editing config.php: only config.local.php (or the /install/ wizard) needs to match the new host.
- Cookies and site name follow the real domain when HTTPpath / COOKIEpath are omitted.

Why
- config.php mixed MySQL credentials, the ludiware.com domain, and factory emails, making every client deploy error-prone.

Technical notes
- lw_config_detect_http_host() + lw_config_apply_runtime_defaults() after config.local.php.
- MySQL connects only when DBhost / DBname / DBusername are set.
- Updated config.local.example.php and installer (domain optional).
v1.1.92026-08-08 17:58:54Modal sign-in fix (POST fields + SQL)Sign-in from the modal now reliably sends email and password (POST to the current page, fields read explicitly) and works on hosts without mysqlnd.
For users
- The login/register modal posts to the page you are on (not only /sign-in/), avoiding silent failures.
- If the account has no password (Google/Facebook admin sign-in), a clear message appears instead of “invalid email or password”.

Why
- On some themes, fields did not always have a name attribute when FormData ran; on some hosts, user SQL reads failed without mysqlnd.

Technical notes
- lw-account-forms.js v4: explicit buildFormData; action = current page in modals.
- lw_public_accounts_stmt_fetch_one_assoc(); modal forms: post_url injected at render.
v1.1.82026-08-08 17:51:46Admin recognition on public site + cookie domainAn administrator signed into lw-admin is recognized again on the public site (My account header). Cookies align with the site’s actual domain (e.g. dormezcheznous.com).
For users
- If you are signed into lw-admin on the same domain as the public site, the header shows “My account” without using the modal again.
- After signing in via the modal, the public session persists.
- Check config.local.php: COOKIEpath must match the site domain (not ludiware.com if the site uses another hostname).

Why
- Admin cookies were sometimes set for ludiware.com while the site runs on a custom domain; the public site never received them. Modal sign-in could also fail when mismatched admin cookies interfered.

Technical notes
- lw_cookie_domain() uses current HTTP host when it differs from COOKIEpath.
- lw_public_accounts_auth_from_cookies() + member session sync.
- Auth bootstrap on public index.php.
v1.1.72026-08-08 17:31:50Conditional account header (snippets / tokens)Show “Sign in” or “My account” in the header based on session state, using an HTML snippet and {{​​​​account_if_guest}} / {{​​​​account_if_logged_in}} tokens.
For users
- In an HTML snippet (or layout): wrap the Sign in button with {{​​​​account_if_guest}}…{{​​​​/account_if_guest}} and My account with {{​​​​account_if_logged_in}}…{{​​​​/account_if_logged_in}}.
- Useful tokens: {{​​​​account_account_url}}, {{​​​​account_user_name}}, {{​​​​account_logout_url}}, {{​​​​account_logged_in}} (1 or empty).
- Put {{​​​​snippet:your_key}} in the layout header.
- Built-in alternative: {{​​​​account_strip}} (lw-admin banner).
- PHP snippets: $lw_db variable + lw_public_accounts_viewer().

Why
- Imported themes like DormezChezNous need a custom Bootstrap/modal button, not the generic banner.

Technical notes
- lw_public_accounts_apply_conditional_blocks() in apply_tokens; $lw_db exposed to PHP snippets.
v1.1.62026-08-08 17:25:08Account modal AJAX fix (Homelengo themes)Sign-in from a modal did not react on click: the account script now intercepts the click before theme scripts, shows errors (removes d-none), and shows loading state on the button.
For users
- The “Sign in” button in the modal works again: “…” while sending, visible red error on failure, page reload on success.
- No HTML change needed if data-lw-account and data-lw-account-error are already set.

Why
- Imported themes (Homelengo / DormezChezNous) registered listeners that blocked submit before our script; errors also stayed hidden behind Bootstrap d-none.

Technical notes
- lw-account-forms.js v3: capture click + submit, loaded last before </body>.
- Automatically removes d-none on data-lw-account-error.
v1.1.52026-08-08 17:13:29AJAX sign-in and register (modals)Account forms inside a modal (Bootstrap or similar) can submit without a full page reload: errors show in the modal, and the page refreshes after a successful sign-in.
For users
- If your login/register form is inside a modal (.modal or role="dialog"), submission uses AJAX automatically — no redirect to /sign-in/ that breaks the flow.
- Add an error slot: <div data-lw-account-error></div> in the modal.
- Force or disable: data-lw-account-ajax="1" or "0" on the <form>.
- On success: default is page reload (account menu updates); data-lw-account-on-success="redirect" to go to My account.
- Register captcha refreshes automatically after a failed attempt.

Why
- Sites like DormezChezNous open login/register in popups; a classic POST reloaded the whole page.

Technical notes
- lw-account-forms.js injected when data-lw-account is present.
- JSON responses server-side (lw_public_accounts_handle_post); index.php hook for POST from any page.
v1.1.42026-08-08 16:54:04Custom account forms (data-lw-account)Use your own HTML sign-in and register forms in the theme: the engine wires them automatically and exposes error messages via tokens or dedicated slots.
For users
- Form marker: data-lw-account="login" or "register" (also forgot, reset, profile, security).
- Fields: data-lw-account-field="email|password|…" or auto-detect via id/name/placeholder (like contact).
- Errors: {{​​​​account_error_text}} in your HTML, or <div data-lw-account-error></div>.
- Success: {{​​​​account_success_text}} or data-lw-account-success.
- Replace {{​​​​account_login}} with your markup on the /connexion/ shell page if you do not want the default lw-admin form.
- Register: <div class="lw-account-captcha-slot"></div> for captcha.
- Optional OAuth: <div data-lw-account-oauth></div>.

Why
- Imported themes like DormezChezNous keep their Bootstrap design without duplicating account logic.

Technical notes
- account_forms.php (same pattern as data-lw-contact).
- Injects CSRF + lw_account_action; POST action targets /connexion/, /register/, etc.
v1.1.32026-08-08 12:47:55HTML editors with syntax highlighting and tabsAll admin HTML and code fields now have syntax highlighting and Tab indentation (4 spaces), including TinyMCE’s source code view.
For users
- Raw HTML fields (header, footer, snippets, templates, custom CSS, etc.): line numbers, highlighting, Tab to indent.
- TinyMCE rich editor: the source code button opens the same highlighted experience.
- Imported themes: direct HTML editing with highlighting.

Why
- Easier markup editing without an external IDE.
- Tab inserts consistent indentation; Shift+Tab outdents.

Technical notes
- lw-code-editor.js module (CodeMirror 5 via CDN).
- html, css, and php modes per field.
- App-shell navigation compatible (reinit after page change).
v1.1.22026-08-08 11:37:45In-app CMS update and footer alertRemote installations show a visible admin footer warning when a newer package is available, and can install the update from Settings → Versions without manually re-uploading files.
For users
- Admin footer: “Update available (vX.Y.Z)” badge when a newer VersionLog package is published on repo.ludiware.com.
- Settings → Versions: banner with “Update now” (automatic download and deploy).
- Preserved local files: config.local.php, config.php (only the Version line is updated), uploads/, storage/, installed extensions.

Why
- Avoid manual FTP/SFTP updates on every hosted site.
- Surface an outdated version (e.g. 1.0.53 vs 1.1.x) without digging through history.

Technical notes
- lw_cms_update_apply(): downloads ZIP/tar.gz from repo.ludiware.com, extracts and copies core files.
- lw_versionlog_check_update() unchanged (30 min cache).
- Settings sidebar badge + chrome alert for managers.
v1.1.12026-08-08 11:30:24Version history: readable tokens and bracesVersionLog entries no longer show raw HTML codes ({): tokens like {{​​​​account_login}} display normally.
For visitors
- History page: CMS token examples show as plain text (visible braces), without double-encoded HTML entities.

Why
- Some VersionLog entries mentioned HTML entities ({) in their text; htmlspecialchars() displayed them literally on screen.

Technical
- lw_versionlog_prepare_display_source(): decode brace entities before zero-width neutralization and lw_e().
v1.1.0 Package2026-08-08 11:28:14ludiWARE 1.1.0 — public distributionMinor release 1.1.0: full install package (ZIP + tar.gz), public OAuth accounts, public version history, contact form prefill, and updated MarketPlace plugins.
For users
- Download: ludiware-1.1.0.tar.gz + ludiware-1.1.0.zip
- Repo: https://repo.ludiware.com/releases/1.1.0/
- Includes /install/ wizard (database, schema, admin account)

Since the 1.0.40 distribution
- Local member accounts: sign-up, login, forgot password, My account (profile / security tabs)
- Google and Facebook OAuth on the public site
- Public header recognizes lw-admin session and OAuth members
- {{​​​​versionlog}} token: version history on the public site
- Contact form: name and email prefilled when signed in
- Bootstrap Icons + admin icon picker
- MarketPlace plugins: FAQ, Testimonials, Gallery, Forms, Booking, Classifieds, Forums

Republished plugins (MarketPlace)
- Forums 1.0.16
- Classifieds 1.0.15

Technical notes
- OSS export without factory secrets; VersionLog FileName → public tar.gz.

Télécharger le package

v1.0.612026-08-08 11:25:48Version history: tokens display normallyExamples like {{​​​​account_login}} in version history show as readable text, without visible HTML entities ({).
For visitors / administrators
- History page and Settings → Versions: cited tokens appear as {{​​​​account_login}}, not as {{​​account_login}}.

Why
- Escaping braces as HTML entities then running htmlspecialchars() double-encoded and showed raw codes on screen.

Technical
- Zero-width space neutralization only (no { entities) in lw_versionlog_format_display_text() and lw_versionlog_shield_public_html().
v1.0.602026-08-08 11:24:31Contact form: name and email prefilled when signed inOn the contact form, Name and Email fields are filled automatically when the visitor is already signed in (local account, lw-admin, or CDS portal).
For users
- {{​​​​contact_form}} and theme ZIP contact forms: Name and Email prefilled when signed in.
- Fields already set in the template are not overwritten.

Why
- Avoid re-entering identity on every contact message.

Sources
- CDS portal (SSO session): full name + contact email.
- Public member account or lw-admin cookie: display_name + lw_users email.

Technical
- lw_contact_prefill_identity(), lw_contact_apply_prefill_to_form(), lw_contact_form_html().
v1.0.592026-08-08 11:20:46{{​​​​versionlog}} token works on the public siteThe {{​​​​versionlog}} token is now recognized on the public site: the History page shows the version list instead of the raw token text.
For visitors
- History page: {{​​​​versionlog}} content is replaced by the version list (styles and safe text).

Why
- The VersionLog module was only loaded in lw-admin; on index.php (public front), lw_versionlog_prepare_public_html() was missing and the token stayed literal.

Technical
- require versionlog.php in www/index.php before public_render.php.
v1.0.582026-08-08 11:07:13Public version history: CMS tokens shown as plain textOn the ludiware.com History page, mentions like {{​​​​account_login}}, {{​​​​menu:main}}, etc. in VersionLog entries display as text instead of injecting forms or menus.
For visitors
- History page (/historique/): version title, description and details show cited tokens as documentation, with no login form or menu injected mid-sentence.

Why
- VersionLog content is rendered via a PHP snippet then processed by the CMS token engine; example {{​​​​account_login}} was executed as a real token.

Technical
- Native {{​​​​versionlog}} / {{​​​​versionlog_list}} token; .lw-vl-* blocks shielded before the token pipeline; HTML entities for {{​​​​ and }} on display.
v1.0.572026-08-08 10:58:52Version history: CMS tokens shown as plain textMentions like {{​​​​account_login}}, {{​​​​menu:main}}, etc. in VersionLog technical details are no longer interpreted as CMS tokens.
For administrators
- Settings → Version history: title, description and full details show tokens literally (documentation), with no forms or injected content.

Why
- VersionLog entries often cite tokens as examples in “Technical detail”; the token engine must not execute them on display.

Technical
- Neutralize {{​​​​ → {{​​​​ + zero-width space on API output and lw-admin client; HTML-escaped display.
v1.0.562026-08-08 10:54:16Public header: lw-admin session recognitionWhen signed into lw-admin, you also appear as a member on the public site (header, My account), consistent with blog comments.
For visitors / administrators
- lw-admin cookies → {{​​​​account_strip}} shows your name and “My account”.
- /account/ works without visiting /login/ again.
- /login/ and /register/ redirect to My account when already recognized.

Identity priority (unchanged for blog when a Facebook session is active)
1. Public member session (login / OAuth)
2. lw-admin cookie

Public sign-out clears the member session only; if lw-admin remains, you stay signed in.
v1.0.552026-08-08 10:38:20Blog and forums: public member identity firstOn the public site, the member session (login / Facebook / Google) now takes precedence over lw-admin cookies for blog comments.
Fixed issue
- Header “Signed in as…” (member session) and blog “Commenting as…” (admin cookies) could show two different people when logged into lw-admin and Facebook on the public site.

Behavior
- Priority: CDS portal → public member (session) → admin staff (lw-admin cookie).
- Blog login hint links to /login/ when local accounts are active (no CDS).

Note
- If Facebook created a second lw_users account (different email from admin), that is expected: two separate profiles. Merge manually or delete the duplicate in Users.
v1.0.542026-08-08 10:11:29OAuth — stable redirect URLThe Google/Facebook callback URL in site settings now uses the site’s public domain (e.g. ludiware.com), not the admin host.
For administrators
- Settings → Member accounts: the “authorized redirect” URL matches the site’s public domain.
- Help note for adding the URI in Facebook Login → Valid OAuth Redirect URIs.

Why
- When opened from the admin panel (different subdomain), the generated URL could differ from the one used on the public site.
v1.0.532026-08-08 10:03:23Google and Facebook sign-in for membersVisitors can sign in or register with Google or Facebook on login and register pages when local accounts are used (no CentreDeService portal). A local member profile is created automatically when needed.
For visitors
- “Sign in with Google” and “Sign in with Facebook” on /login/ and /register/ (FR: /connexion/, /inscription/).
- If the email is not registered yet, a member account is created and the session starts.
- If an account already exists with the same email, the OAuth profile is linked to it.

For administrators
- Site settings → Member accounts: enable providers, OAuth credentials, and redirect URLs to paste into Google Cloud / Facebook Developer.
- Automatically disabled when the CentreDeService portal handles authentication.

Technical
- lw_users google_id / facebook_id columns, oauth_accounts.php module, /oauth/{provider}/callback/ routes.
v1.0.522026-08-08 08:35:18Icon picker — full catalogThe icon picker now shows useful favorites first, then all Bootstrap icons (~1,600) via search.
For administrators
- On open: a grid of favorites (home, commerce, transport, etc.).
- Search: filters the full set of ~1,683 installed Bootstrap Icons.
- Result count and message when the list is truncated.

Fix
- The list was previously capped at 120 icons in alphabetical order (123, alarm…), which felt incomplete.
v1.0.512026-08-08 08:29:09Bootstrap Icons and icon pickerBootstrap Icons now render reliably across the admin with complete font files. A reusable icon picker is available for forms (search, grid, preview).
For administrators
- Bootstrap Icons font files (woff/woff2) installed so existing `bi-*` icons in lw-admin display correctly.
- New reusable icon picker component (`lw_icon_picker_field`) for any admin form.

Usage
- Button with icon preview, name search, clickable grid, and a “No icon” option.
- PHP helpers `lw_bootstrap_icon_names()` and `lw_bootstrap_icon_class()`.

Technical
- Files: `functions/icon_picker.php`, `js/lw-icon-picker.js`, styles in `lw-admin.css`.
v1.0.502026-08-08 07:27:10My account — profile and security tabsThe My account page has two tabs: My information (first name, last name, avatar) and Access & security (email, password). New tokens for ZIP templates.
For users
- My information tab: first name, last name, avatar upload.
- Access & security tab: change email and/or password (current password required).

ZIP tokens
- {{​​​​account_panel}}: full panel with tabs.
- {{​​​​account_tabs}}, {{​​​​account_profile}}, {{​​​​account_security}}: custom layout.
- {{​​​​account_avatar}}, {{​​​​account_avatar_url}}, {{​​​​account_first_name}}, {{​​​​account_last_name}}, {{​​​​account_email}}.
- {{​​​​account_profile_url}}, {{​​​​account_security_url}}: direct links to each tab.

Technical notes
- lw_users.avatar_path column, files in uploads/users/, public session synced after updates.
v1.0.492026-08-08 07:17:18Public accounts unified in lw_usersRegistration, sign-in and forgot password on the public site now use the lw_users table (same as lw-admin). Only accounts with admin access can open lw-admin.
For users
- Same email and password everywhere: admin or visitor registered at /register/.
- Accounts created on the public site have the user role and cannot access lw-admin.
- Administrators can also sign in at /login/ with their usual credentials.

Why
- Removes the mistaken dual lw_site_members / lw_users system.

Technical notes
- public_accounts.php: auth, registration and reset on lw_users; per-site public session.
- auth.php unchanged: can_access_admin required for lw-admin.
- Obsolete lw_site_members table can be dropped in the database (DROP TABLE).
v1.0.482026-08-08 07:11:33Public sign-in with an administrator accountSite administrators can sign in on the public site (/login/) using the same email and password as lw-admin, without a separate registration.
For users
- At /login/, a global administrator or a user assigned to the site is accepted with lw-admin credentials.
- The first sign-in automatically creates the local member profile for that site; later sign-ins reuse it.

Why
- Before this fix, only accounts registered via /register/ (lw_site_members) were recognized; the first admin saw “Invalid email or password.”

Technical notes
- lw_users → lw_site_members bridge in lw_public_accounts_login(): admin password check, site access (global_admin or local_admin site member), hash sync and member session.
v1.0.472026-08-08 06:52:34Local member accounts on the public siteSites without a CentreDeService portal can offer registration, sign-in, forgot password and a member area on the public site, with tokens for ZIP templates and CMS shell pages.
For users
- Register at /register/ with captcha and password confirmation.
- Sign in at /login/, recover at /forgot-password/, reset via email link.
- “My account” when signed in; {{​​​​account_strip}} banner in the header.

For administrators
- Settings → Member accounts: CMS shells and “Generate system pages”.
- Menu editor: Add member (Sign in, Forgot password, Register, My account) when CDS is off.
- ZIP tokens: {{​​​​account_login}}, {{​​​​account_register}}, {{​​​​account_panel}}, {{​​​​account_forgot}}, {{​​​​account_reset}} and related URLs.

Why
- Let standalone ludiWARE sites (no CDS) offer visitor accounts for comments, gated content or future personalization.

Technical notes
- lw_site_members table, session CSRF, registration captcha separate from contact, try_serve routes, public_render apply_tokens.
v1.0.462026-08-07 12:59:32Contact captcha: fix valid answers rejectedWhen a page or template has multiple contact forms, the same security question is shown everywhere and a correct answer is accepted.
For users
- The “What is X + Y?” captcha is the same on all contact forms on a page.
- A correct answer is no longer rejected with “Incorrect security check.”

Why
- Each form could get a different question while the session stores only one expected answer (content and template finalized separately).

Technical notes
- lw_contact_captcha_issue() reuses a valid session challenge; contact finalize runs once on the full HTML (public_render.php).
v1.0.452026-08-07 12:15:48Blog tokens: latest posts (footer / sidebar)Use {{​​​​blog-latest-title-1}}, {{​​​​blog-latest-image-1}}, {{​​​​blog-latest-excerpt-1}}, etc. (up to 10) in a template or page to show the most recent posts.
For users
- {{​​​​blog-latest-title-N}}: title (N=1 = newest, 2 = second, … up to 10)
- {{​​​​blog-latest-image-N}}: featured image URL
- {{​​​​blog-latest-excerpt-N}}: excerpt from post body
- {{​​​​blog-latest-date-N}}: short date (e.g. April 15, 2020)
- {{​​​​blog-latest-date-long-N}}: long formatted date
- {{​​​​blog-latest-url-N}}: link to the post
- Ideal for a “Blog” block in the footer or sidebar of an imported ZIP theme.

Why
- Customize the footer without manually copying post titles and images.

Technical notes
- lw_blog_apply_latest_tokens() in blog.php, invoked from lw_blog_apply_tokens() on templates and pages.
v1.0.442026-08-07 12:10:34Theme contact: error messages and Subject fieldZIP theme contact forms again show the actual error message (captcha, missing fields, etc.) and the theme Subject field is supported.
For users
- After a failed send, the specific message appears (e.g. wrong captcha) instead of the generic “Could not send your message.”
- Theme Subject fields (e.g. msg_subject, placeholder or label “Subject”) are stored and included in notification email.
- Fields without a name attribute but with placeholder/label (Your name, Your email…) are detected on import and render.

Why
- lw_contact_form_html() cleared the session flash before theme forms could display it.
- Some themes name the subject field differently than subject.

Technical notes
- public_render.php: lw_contact_form_html() only when {{​​​​contact_form}} is present.
- contact_forms.php: msg_subject alias, placeholder/label detection, name/email fallbacks.
v1.0.432026-08-07 12:04:45Fix HTTP 500 on ZIP theme contact pagesImported “Contact us” pages no longer crash when the Send button sits inside the theme grid (Bootstrap, etc.).
For users
- Custom contact pages from imported themes render again with captcha and Messages inbox delivery.
- Before the fix, some layouts (e.g. Bootstrap grid forms) returned HTTP 500.

Why
- When wiring the theme form, the captcha slot was inserted at the wrong DOM level if the submit control was not a direct child of <form>.

Technical notes
- contact_forms.php: lw_contact_wire_form_element() inserts the captcha slot via the submit button’s immediate parent instead of form->insertBefore() on a nested node.
v1.0.422026-08-07 09:41:46Customizable CDS shop pages (shells and tokens)Like the blog, you can pick CMS pages as shells for the shop, categories, product pages, cart and orders, then place granular tokens (title, price, image, list, etc.).
For users
- In Site settings → CentreDeService.NET, “Shop shell pages”, map a CMS page to each screen type (/boutique/, category, product, cart, order).
- Without a shell, the default CDS render is unchanged.
- On a product shell: {{​​​​cds_product_title}}, {{​​​​cds_product_image}}, {{​​​​cds_product_price}}, {{​​​​cds_product_desc}}, {{​​​​cds_product_add_cart}}, or {{​​​​cds_product}} for the full card.
- On list / category: {{​​​​cds_shop_list}} (full block), or {{​​​​cds_shop_categories}}, {{​​​​cds_shop_products}}, {{​​​​cds_shop_pager}}, {{​​​​cds_category_title}}.
- Cart / order: {{​​​​cds_cart}}, {{​​​​cds_order}}, {{​​​​cds_cart_count}}.

Why
- Let the shop layout match the site theme, following the blog token pattern.

Technical notes
- Shells: cds_shop_*_page_uid; lw_cds_resolve_shell_page in lw_cds_try_serve.
- Tokens: lw_cds_apply_shop_field_tokens + context in lw_cds_apply_tokens.
v1.0.412026-08-07 09:03:11ZIP theme contact forms wired to the CMSContact forms already present in an imported theme can send messages through the lw-admin contact engine without replacing the theme design. Detection is automatic on import; you can also force it with data-lw-contact="1".
For users
- A theme contact form (classes / mailto / name-email-message fields) is wired to the Messages inbox and notification email.
- The form’s look (theme HTML/CSS) is preserved.
- Manual marker: data-lw-contact="1" forces binding; data-lw-contact="0" excludes it.
- Captcha and success/error messages work like {{​​​​contact_form}}.

Why
- Avoid replacing a polished theme form with the generic {{​​​​contact_form}} markup.

Technical notes
- lw_contact_wire_form_html (import); lw_contact_finalize_bound_forms (render); field aliases in lw_contact_submit.
v1.0.40 Package2026-08-06 13:07:30ludiWARE 1.0.40 — installation packageFull public distribution (ZIP + tar.gz) with installer. Includes recent work: blog (tokens, category URLs, subcategories), CMS 404 page, global media library, menus / ZIP import, and display fixes.
For users
- Downloadable package to install or update ludiWARE.
- Archives: ludiware-1.0.40.tar.gz and ludiware-1.0.40.zip
- Repo: https://repo.ludiware.com/releases/1.0.40/
- Includes /install/ wizard (database, schema, admin account)

Notable since last distribution
- Blog: author / long date / time / comments / categories tokens; /blogue/category/subcategory/slug URLs; admin subcategories; French comment agreement
- Designated CMS 404 page + badge; ZIP import (chrome, mega-menus, 404 detect)
- Global media library and folders; active menus; header dedupe

Why
- Ship an installable package aligned with the current CMS version.

Technical notes
- OSS export (no secrets, no factory api/admin); VersionLog FileName points to the public tar.gz.

Télécharger le package

v1.0.392026-08-06 13:01:02Singular “commentaire” for 0 or 1 commentIn the French blog post list, “0 commentaire” and “1 commentaire” (no trailing s) are shown; the plural starts at 2.
For users
- Post card meta: correct French agreement for commentaire (singular for 0/1).

Why
- “0 commentaires” was incorrect in French.

Technical notes
- lw_blog_format_comments_count: singular when count <= 1 (FR).
v1.0.382026-08-06 13:00:31Easier blog subcategories in adminIn lw-admin, each category has a button to add a subcategory. The Parent category field is more prominent, with a tree-style list.
For users
- Categories list: diagram icon creates a subcategory already linked to the right parent.
- Form: parent field first, help about /blogue/parent/child/… URLs.
- “Subcategory” badge and Parent column in the table.

Why
- Hierarchy already existed in the database but was too easy to miss in the UI.

Technical notes
- blogcats.php (?new=1&parent=uid); blog.cat_* i18n keys; category cache bust.
v1.0.372026-08-06 12:51:12Blog URLs with nested categoriesPosts are now available at /blogue/category/subcategory/post-slug. Old /blogue/slug addresses redirect to the new URL automatically.
For users
- Post URL: /blogue/{category}/{subcategory}/{slug} from the category tree.
- No category: /blogue/{slug} as before.
- Category lists: /blogue/{category}/{subcategory} (legacy /blogue/categorie/… redirects).
- List links, comments, sitemap and admin use the new structure.

Why
- Mirror the category tree in the URL for clearer SEO and navigation.

Technical notes
- lw_blog_post_url / lw_blog_post_path_extra; path resolution in lw_blog_try_serve; 301 redirects.
v1.0.362026-08-06 12:48:37New blog tokens (author, date, comments…)Article templates can show the comment count, author, a long date, publish time, and the categories list. An Author field was added when editing posts.
For users
- New tokens: {{​​​​blog_comments_count}} (number only), {{​​​​blog_author}}, {{​​​​blog_date_long}} (e.g. Thursday, September 3, 2024), {{​​​​blog_time}} (HH:MM), {{​​​​blog_categories}} (published categories list).
- {{​​​​blog_date}} stays YYYY-MM-DD.
- “Author” field on create/edit, used by {{​​​​blog_author}}.

Why
- Richer article layouts without hard-coded HTML.

Technical notes
- author_name column; lw_blog_format_date_long / lw_blog_render_categories_token_list helpers; tokens documented in templates.php.
v1.0.352026-08-06 11:32:25CMS 404 page: fixed display + badgeThe page set as 404 now renders correctly (including on draft sites / preview). The pages list shows a “404” badge like the home badge. ZIP imports auto-detect 404 error pages.
For users
- When you check “Use as 404 page”, unknown URLs show that themed page instead of the generic dark 404.
- This also works in preview and while the site is still a draft.
- Pages list: orange “404” badge next to status, like the Home badge.
- New ZIP imports: a page named 404 / not-found is assigned automatically.

Why
- 404 page rendering ignored preview mode and rejected draft sites (“Site not published”), falling back to the generic page.

Technical notes
- lw_public_site_404(..., $preview); force preview render when site is draft; pages.badge_404; auto page_404_page_uid on ZIP import.
v1.0.342026-08-06 11:26:54ZIP import: no duplicate header in page contentWhen importing a template, the header (and similar wrappers) is removed from page content once it lives in the global header. Already-imported sites are cleaned on view.
For users
- Imported pages no longer keep a copy of the menu/header in their content when global chrome is active.
- Templates without a <header> tag (e.g. #header / .header-area) are supported too.

Why
- Stripping was too strict (majority vote, non-semantic wrappers ignored), leaving leftovers in page HTML.

Technical notes
- Structural detection + normalized affix (ignore active); broader DOM strip/dedupe; public render cleanup.
v1.0.332026-08-06 11:16:07Menu: current item highlighted correctlyOn sites (including imported templates), the active menu item follows the page being viewed instead of staying stuck on Home.
For users
- Visiting About (or another page) highlights that item, not Home.
- Parents of an active submenu item stay highlighted too.

Why
- Import copied the homepage’s active class into the CMS menu and never recalculated it from the URL.

Technical notes
- Menu render strips imported active/current classes, marks by page_uid or current path, aria-current=page.
v1.0.322026-08-06 11:00:39Fix media “New folder” fieldChoosing “New folder” in the media library correctly shows the name field again, including after in-app navigation.
For users
- The text field under “New folder” appears reliably when selected.

Why
- The script did not rebind after app-shell fragment navigation.

Technical notes
- Event delegation + re-init on lw:fragment-loaded (lw-media-folder.js v2).
v1.0.312026-08-06 10:50:19Global media library and foldersUpload shared images (logos, etc.) once under Library → Global media and reuse them on every site. Folder selection on upload lists existing folders or “New folder”.
For users
- New Library → Global media section for shared image upload and management.
- On a site media page, the Global tab lists those files read-only (copy URL); platform admins get a Manage link.
- On upload/edit, Folder is a dropdown (none / existing / New folder + text field).

Why
- Avoid re-uploading the same logo on every site.
- Make folder tagging clearer without retyping names.

Technical notes
- lw_media.site_id NULL = global; files under uploads/global/; single reference (no per-site copy).
v1.0.302026-08-06 09:59:30ZIP import: mega-menus preservedWhen importing a ZIP template, rich mega-menu panels (columns, images, CTAs) and Bootstrap dropdown attributes are kept and rendered correctly.
For users
- Templates with mega-menus (full-width panels, grids, images) keep their look after import.
- Bootstrap dropdowns keep their options (data-bs-toggle, etc.).
- Items with a mega panel show an HTML field in Menus for edits (until the mega-menu extension).

Why
- Import only read nested <ul> lists; <div class="dropdown-menu"> panels were dropped when tokenizing {{​​​​menu:…}}.

Technical notes
- New item fields: panel_html, link_attrs, label_html; harvest detection; render anchor+panel; URL rewrite on persist.
v1.0.292026-08-06 09:42:25Fix header/footer save (duplication)Saving header and footer on a ZIP template no longer duplicates the footer under the copyright bar.
For users
- Saving “Header & footer” no longer leaves a second unstyled footer.
- Sites already affected are fixed on view (and permanently when you save chrome again).

Why
- The parser used the first inner </div> of the footer as the block end, then appended the remainder after the footer.

Technical notes
- after_footer extracted via DOM; only script/style/link/noscript kept; public render repair.
token; .lw-vl-* blocks shielded before the token pipeline; HTML entities for {{ and }} on display.
v1.0.572026-08-08 10:58:52Version history: CMS tokens shown as plain textMentions like {{​account_login}}, {{​menu:main}}, etc. in VersionLog technical details are no longer interpreted as CMS tokens.
For administrators
- Settings → Version history: title, description and full details show tokens literally (documentation), with no forms or injected content.

Why
- VersionLog entries often cite tokens as examples in “Technical detail”; the token engine must not execute them on display.

Technical
- Neutralize {{​ → {{​ + zero-width space on API output and lw-admin client; HTML-escaped display.
v1.0.562026-08-08 10:54:16Public header: lw-admin session recognitionWhen signed into lw-admin, you also appear as a member on the public site (header, My account), consistent with blog comments.
For visitors / administrators
- lw-admin cookies → {{​account_strip}} shows your name and “My account”.
- /account/ works without visiting /login/ again.
- /login/ and /register/ redirect to My account when already recognized.

Identity priority (unchanged for blog when a Facebook session is active)
1. Public member session (login / OAuth)
2. lw-admin cookie

Public sign-out clears the member session only; if lw-admin remains, you stay signed in.
v1.0.552026-08-08 10:38:20Blog and forums: public member identity firstOn the public site, the member session (login / Facebook / Google) now takes precedence over lw-admin cookies for blog comments.
Fixed issue
- Header “Signed in as…” (member session) and blog “Commenting as…” (admin cookies) could show two different people when logged into lw-admin and Facebook on the public site.

Behavior
- Priority: CDS portal → public member (session) → admin staff (lw-admin cookie).
- Blog login hint links to /login/ when local accounts are active (no CDS).

Note
- If Facebook created a second lw_users account (different email from admin), that is expected: two separate profiles. Merge manually or delete the duplicate in Users.
v1.0.542026-08-08 10:11:29OAuth — stable redirect URLThe Google/Facebook callback URL in site settings now uses the site’s public domain (e.g. ludiware.com), not the admin host.
For administrators
- Settings → Member accounts: the “authorized redirect” URL matches the site’s public domain.
- Help note for adding the URI in Facebook Login → Valid OAuth Redirect URIs.

Why
- When opened from the admin panel (different subdomain), the generated URL could differ from the one used on the public site.
v1.0.532026-08-08 10:03:23Google and Facebook sign-in for membersVisitors can sign in or register with Google or Facebook on login and register pages when local accounts are used (no CentreDeService portal). A local member profile is created automatically when needed.
For visitors
- “Sign in with Google” and “Sign in with Facebook” on /login/ and /register/ (FR: /connexion/, /inscription/).
- If the email is not registered yet, a member account is created and the session starts.
- If an account already exists with the same email, the OAuth profile is linked to it.

For administrators
- Site settings → Member accounts: enable providers, OAuth credentials, and redirect URLs to paste into Google Cloud / Facebook Developer.
- Automatically disabled when the CentreDeService portal handles authentication.

Technical
- lw_users google_id / facebook_id columns, oauth_accounts.php module, /oauth/{provider}/callback/ routes.
v1.0.522026-08-08 08:35:18Icon picker — full catalogThe icon picker now shows useful favorites first, then all Bootstrap icons (~1,600) via search.
For administrators
- On open: a grid of favorites (home, commerce, transport, etc.).
- Search: filters the full set of ~1,683 installed Bootstrap Icons.
- Result count and message when the list is truncated.

Fix
- The list was previously capped at 120 icons in alphabetical order (123, alarm…), which felt incomplete.
v1.0.512026-08-08 08:29:09Bootstrap Icons and icon pickerBootstrap Icons now render reliably across the admin with complete font files. A reusable icon picker is available for forms (search, grid, preview).
For administrators
- Bootstrap Icons font files (woff/woff2) installed so existing `bi-*` icons in lw-admin display correctly.
- New reusable icon picker component (`lw_icon_picker_field`) for any admin form.

Usage
- Button with icon preview, name search, clickable grid, and a “No icon” option.
- PHP helpers `lw_bootstrap_icon_names()` and `lw_bootstrap_icon_class()`.

Technical
- Files: `functions/icon_picker.php`, `js/lw-icon-picker.js`, styles in `lw-admin.css`.
v1.0.502026-08-08 07:27:10My account — profile and security tabsThe My account page has two tabs: My information (first name, last name, avatar) and Access & security (email, password). New tokens for ZIP templates.
For users
- My information tab: first name, last name, avatar upload.
- Access & security tab: change email and/or password (current password required).

ZIP tokens
- {{​account_panel}}: full panel with tabs.
- {{​account_tabs}}, {{​account_profile}}, {{​account_security}}: custom layout.
- {{​account_avatar}}, {{​account_avatar_url}}, {{​account_first_name}}, {{​account_last_name}}, {{​account_email}}.
- {{​account_profile_url}}, {{​account_security_url}}: direct links to each tab.

Technical notes
- lw_users.avatar_path column, files in uploads/users/, public session synced after updates.
v1.0.492026-08-08 07:17:18Public accounts unified in lw_usersRegistration, sign-in and forgot password on the public site now use the lw_users table (same as lw-admin). Only accounts with admin access can open lw-admin.
For users
- Same email and password everywhere: admin or visitor registered at /register/.
- Accounts created on the public site have the user role and cannot access lw-admin.
- Administrators can also sign in at /login/ with their usual credentials.

Why
- Removes the mistaken dual lw_site_members / lw_users system.

Technical notes
- public_accounts.php: auth, registration and reset on lw_users; per-site public session.
- auth.php unchanged: can_access_admin required for lw-admin.
- Obsolete lw_site_members table can be dropped in the database (DROP TABLE).
v1.0.482026-08-08 07:11:33Public sign-in with an administrator accountSite administrators can sign in on the public site (/login/) using the same email and password as lw-admin, without a separate registration.
For users
- At /login/, a global administrator or a user assigned to the site is accepted with lw-admin credentials.
- The first sign-in automatically creates the local member profile for that site; later sign-ins reuse it.

Why
- Before this fix, only accounts registered via /register/ (lw_site_members) were recognized; the first admin saw “Invalid email or password.”

Technical notes
- lw_users → lw_site_members bridge in lw_public_accounts_login(): admin password check, site access (global_admin or local_admin site member), hash sync and member session.
v1.0.472026-08-08 06:52:34Local member accounts on the public siteSites without a CentreDeService portal can offer registration, sign-in, forgot password and a member area on the public site, with tokens for ZIP templates and CMS shell pages.
For users
- Register at /register/ with captcha and password confirmation.
- Sign in at /login/, recover at /forgot-password/, reset via email link.
- “My account” when signed in; {{​account_strip}} banner in the header.

For administrators
- Settings → Member accounts: CMS shells and “Generate system pages”.
- Menu editor: Add member (Sign in, Forgot password, Register, My account) when CDS is off.
- ZIP tokens: {{​account_login}}, {{​account_register}}, {{​account_panel}}, {{​account_forgot}}, {{​account_reset}} and related URLs.

Why
- Let standalone ludiWARE sites (no CDS) offer visitor accounts for comments, gated content or future personalization.

Technical notes
- lw_site_members table, session CSRF, registration captcha separate from contact, try_serve routes, public_render apply_tokens.
v1.0.462026-08-07 12:59:32Contact captcha: fix valid answers rejectedWhen a page or template has multiple contact forms, the same security question is shown everywhere and a correct answer is accepted.
For users
- The “What is X + Y?” captcha is the same on all contact forms on a page.
- A correct answer is no longer rejected with “Incorrect security check.”

Why
- Each form could get a different question while the session stores only one expected answer (content and template finalized separately).

Technical notes
- lw_contact_captcha_issue() reuses a valid session challenge; contact finalize runs once on the full HTML (public_render.php).
v1.0.452026-08-07 12:15:48Blog tokens: latest posts (footer / sidebar)Use {{​blog-latest-title-1}}, {{​blog-latest-image-1}}, {{​blog-latest-excerpt-1}}, etc. (up to 10) in a template or page to show the most recent posts.
For users
- {{​blog-latest-title-N}}: title (N=1 = newest, 2 = second, … up to 10)
- {{​blog-latest-image-N}}: featured image URL
- {{​blog-latest-excerpt-N}}: excerpt from post body
- {{​blog-latest-date-N}}: short date (e.g. April 15, 2020)
- {{​blog-latest-date-long-N}}: long formatted date
- {{​blog-latest-url-N}}: link to the post
- Ideal for a “Blog” block in the footer or sidebar of an imported ZIP theme.

Why
- Customize the footer without manually copying post titles and images.

Technical notes
- lw_blog_apply_latest_tokens() in blog.php, invoked from lw_blog_apply_tokens() on templates and pages.
v1.0.442026-08-07 12:10:34Theme contact: error messages and Subject fieldZIP theme contact forms again show the actual error message (captcha, missing fields, etc.) and the theme Subject field is supported.
For users
- After a failed send, the specific message appears (e.g. wrong captcha) instead of the generic “Could not send your message.”
- Theme Subject fields (e.g. msg_subject, placeholder or label “Subject”) are stored and included in notification email.
- Fields without a name attribute but with placeholder/label (Your name, Your email…) are detected on import and render.

Why
- lw_contact_form_html() cleared the session flash before theme forms could display it.
- Some themes name the subject field differently than subject.

Technical notes
- public_render.php: lw_contact_form_html() only when {{​contact_form}} is present.
- contact_forms.php: msg_subject alias, placeholder/label detection, name/email fallbacks.
v1.0.432026-08-07 12:04:45Fix HTTP 500 on ZIP theme contact pagesImported “Contact us” pages no longer crash when the Send button sits inside the theme grid (Bootstrap, etc.).
For users
- Custom contact pages from imported themes render again with captcha and Messages inbox delivery.
- Before the fix, some layouts (e.g. Bootstrap grid forms) returned HTTP 500.

Why
- When wiring the theme form, the captcha slot was inserted at the wrong DOM level if the submit control was not a direct child of <form>.

Technical notes
- contact_forms.php: lw_contact_wire_form_element() inserts the captcha slot via the submit button’s immediate parent instead of form->insertBefore() on a nested node.
v1.0.422026-08-07 09:41:46Customizable CDS shop pages (shells and tokens)Like the blog, you can pick CMS pages as shells for the shop, categories, product pages, cart and orders, then place granular tokens (title, price, image, list, etc.).
For users
- In Site settings → CentreDeService.NET, “Shop shell pages”, map a CMS page to each screen type (/boutique/, category, product, cart, order).
- Without a shell, the default CDS render is unchanged.
- On a product shell: {{​cds_product_title}}, {{​cds_product_image}}, {{​cds_product_price}}, {{​cds_product_desc}}, {{​cds_product_add_cart}}, or {{​cds_product}} for the full card.
- On list / category: {{​cds_shop_list}} (full block), or {{​cds_shop_categories}}, {{​cds_shop_products}}, {{​cds_shop_pager}}, {{​cds_category_title}}.
- Cart / order: {{​cds_cart}}, {{​cds_order}}, {{​cds_cart_count}}.

Why
- Let the shop layout match the site theme, following the blog token pattern.

Technical notes
- Shells: cds_shop_*_page_uid; lw_cds_resolve_shell_page in lw_cds_try_serve.
- Tokens: lw_cds_apply_shop_field_tokens + context in lw_cds_apply_tokens.
v1.0.412026-08-07 09:03:11ZIP theme contact forms wired to the CMSContact forms already present in an imported theme can send messages through the lw-admin contact engine without replacing the theme design. Detection is automatic on import; you can also force it with data-lw-contact="1".
For users
- A theme contact form (classes / mailto / name-email-message fields) is wired to the Messages inbox and notification email.
- The form’s look (theme HTML/CSS) is preserved.
- Manual marker: data-lw-contact="1" forces binding; data-lw-contact="0" excludes it.
- Captcha and success/error messages work like {{​contact_form}}.

Why
- Avoid replacing a polished theme form with the generic {{​contact_form}} markup.

Technical notes
- lw_contact_wire_form_html (import); lw_contact_finalize_bound_forms (render); field aliases in lw_contact_submit.
v1.0.40 Package2026-08-06 13:07:30ludiWARE 1.0.40 — installation packageFull public distribution (ZIP + tar.gz) with installer. Includes recent work: blog (tokens, category URLs, subcategories), CMS 404 page, global media library, menus / ZIP import, and display fixes.
For users
- Downloadable package to install or update ludiWARE.
- Archives: ludiware-1.0.40.tar.gz and ludiware-1.0.40.zip
- Repo: https://repo.ludiware.com/releases/1.0.40/
- Includes /install/ wizard (database, schema, admin account)

Notable since last distribution
- Blog: author / long date / time / comments / categories tokens; /blogue/category/subcategory/slug URLs; admin subcategories; French comment agreement
- Designated CMS 404 page + badge; ZIP import (chrome, mega-menus, 404 detect)
- Global media library and folders; active menus; header dedupe

Why
- Ship an installable package aligned with the current CMS version.

Technical notes
- OSS export (no secrets, no factory api/admin); VersionLog FileName points to the public tar.gz.

Télécharger le package

v1.0.392026-08-06 13:01:02Singular “commentaire” for 0 or 1 commentIn the French blog post list, “0 commentaire” and “1 commentaire” (no trailing s) are shown; the plural starts at 2.
For users
- Post card meta: correct French agreement for commentaire (singular for 0/1).

Why
- “0 commentaires” was incorrect in French.

Technical notes
- lw_blog_format_comments_count: singular when count <= 1 (FR).
v1.0.382026-08-06 13:00:31Easier blog subcategories in adminIn lw-admin, each category has a button to add a subcategory. The Parent category field is more prominent, with a tree-style list.
For users
- Categories list: diagram icon creates a subcategory already linked to the right parent.
- Form: parent field first, help about /blogue/parent/child/… URLs.
- “Subcategory” badge and Parent column in the table.

Why
- Hierarchy already existed in the database but was too easy to miss in the UI.

Technical notes
- blogcats.php (?new=1&parent=uid); blog.cat_* i18n keys; category cache bust.
v1.0.372026-08-06 12:51:12Blog URLs with nested categoriesPosts are now available at /blogue/category/subcategory/post-slug. Old /blogue/slug addresses redirect to the new URL automatically.
For users
- Post URL: /blogue/{category}/{subcategory}/{slug} from the category tree.
- No category: /blogue/{slug} as before.
- Category lists: /blogue/{category}/{subcategory} (legacy /blogue/categorie/… redirects).
- List links, comments, sitemap and admin use the new structure.

Why
- Mirror the category tree in the URL for clearer SEO and navigation.

Technical notes
- lw_blog_post_url / lw_blog_post_path_extra; path resolution in lw_blog_try_serve; 301 redirects.
v1.0.362026-08-06 12:48:37New blog tokens (author, date, comments…)Article templates can show the comment count, author, a long date, publish time, and the categories list. An Author field was added when editing posts.
For users
- New tokens: {{​blog_comments_count}} (number only), {{​blog_author}}, {{​blog_date_long}} (e.g. Thursday, September 3, 2024), {{​blog_time}} (HH:MM), {{​blog_categories}} (published categories list).
- {{​blog_date}} stays YYYY-MM-DD.
- “Author” field on create/edit, used by {{​blog_author}}.

Why
- Richer article layouts without hard-coded HTML.

Technical notes
- author_name column; lw_blog_format_date_long / lw_blog_render_categories_token_list helpers; tokens documented in templates.php.
v1.0.352026-08-06 11:32:25CMS 404 page: fixed display + badgeThe page set as 404 now renders correctly (including on draft sites / preview). The pages list shows a “404” badge like the home badge. ZIP imports auto-detect 404 error pages.
For users
- When you check “Use as 404 page”, unknown URLs show that themed page instead of the generic dark 404.
- This also works in preview and while the site is still a draft.
- Pages list: orange “404” badge next to status, like the Home badge.
- New ZIP imports: a page named 404 / not-found is assigned automatically.

Why
- 404 page rendering ignored preview mode and rejected draft sites (“Site not published”), falling back to the generic page.

Technical notes
- lw_public_site_404(..., $preview); force preview render when site is draft; pages.badge_404; auto page_404_page_uid on ZIP import.
v1.0.342026-08-06 11:26:54ZIP import: no duplicate header in page contentWhen importing a template, the header (and similar wrappers) is removed from page content once it lives in the global header. Already-imported sites are cleaned on view.
For users
- Imported pages no longer keep a copy of the menu/header in their content when global chrome is active.
- Templates without a <header> tag (e.g. #header / .header-area) are supported too.

Why
- Stripping was too strict (majority vote, non-semantic wrappers ignored), leaving leftovers in page HTML.

Technical notes
- Structural detection + normalized affix (ignore active); broader DOM strip/dedupe; public render cleanup.
v1.0.332026-08-06 11:16:07Menu: current item highlighted correctlyOn sites (including imported templates), the active menu item follows the page being viewed instead of staying stuck on Home.
For users
- Visiting About (or another page) highlights that item, not Home.
- Parents of an active submenu item stay highlighted too.

Why
- Import copied the homepage’s active class into the CMS menu and never recalculated it from the URL.

Technical notes
- Menu render strips imported active/current classes, marks by page_uid or current path, aria-current=page.
v1.0.322026-08-06 11:00:39Fix media “New folder” fieldChoosing “New folder” in the media library correctly shows the name field again, including after in-app navigation.
For users
- The text field under “New folder” appears reliably when selected.

Why
- The script did not rebind after app-shell fragment navigation.

Technical notes
- Event delegation + re-init on lw:fragment-loaded (lw-media-folder.js v2).
v1.0.312026-08-06 10:50:19Global media library and foldersUpload shared images (logos, etc.) once under Library → Global media and reuse them on every site. Folder selection on upload lists existing folders or “New folder”.
For users
- New Library → Global media section for shared image upload and management.
- On a site media page, the Global tab lists those files read-only (copy URL); platform admins get a Manage link.
- On upload/edit, Folder is a dropdown (none / existing / New folder + text field).

Why
- Avoid re-uploading the same logo on every site.
- Make folder tagging clearer without retyping names.

Technical notes
- lw_media.site_id NULL = global; files under uploads/global/; single reference (no per-site copy).
v1.0.302026-08-06 09:59:30ZIP import: mega-menus preservedWhen importing a ZIP template, rich mega-menu panels (columns, images, CTAs) and Bootstrap dropdown attributes are kept and rendered correctly.
For users
- Templates with mega-menus (full-width panels, grids, images) keep their look after import.
- Bootstrap dropdowns keep their options (data-bs-toggle, etc.).
- Items with a mega panel show an HTML field in Menus for edits (until the mega-menu extension).

Why
- Import only read nested <ul> lists; <div class="dropdown-menu"> panels were dropped when tokenizing {{​menu:…}}.

Technical notes
- New item fields: panel_html, link_attrs, label_html; harvest detection; render anchor+panel; URL rewrite on persist.
v1.0.292026-08-06 09:42:25Fix header/footer save (duplication)Saving header and footer on a ZIP template no longer duplicates the footer under the copyright bar.
For users
- Saving “Header & footer” no longer leaves a second unstyled footer.
- Sites already affected are fixed on view (and permanently when you save chrome again).

Why
- The parser used the first inner </div> of the footer as the block end, then appended the remainder after the footer.

Technical notes
- after_footer extracted via DOM; only script/style/link/noscript kept; public render repair.